0

I am trying to unlock a password protected excel sheet using code found here

I am successfully able to unlock the excel file, but I do not want the user to see any windows. I tried setting this setting: xlAp.Visible = False But I still see the Project Properties window. How can you hide all the windows in this process?

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Declare Function GetWindowTextLength Lib "user32" Alias _
"GetWindowTextLengthA" (ByVal hwnd As Long) As Long

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Dim Ret As Long, ChildRet As Long, OpenRet As Long
Dim strBuff As String, ButCap As String
Dim MyPassword As String

Const WM_SETTEXT = &HC
Const BM_CLICK = &HF5

Sub UnlockVBA()
    Dim xlAp As Object, oWb As Object

    Set xlAp = CreateObject("Excel.Application")

    xlAp.Visible = True

    '~~> Open the workbook in a separate instance
    Set oWb = xlAp.Workbooks.Open("C:\Sample.xlsm")

    '~~> Launch the VBA Project Password window
    '~~> I am assuming that it is protected. If not then
    '~~> put a check here.
    xlAp.VBE.CommandBars(1).FindControl(ID:=2578, recursive:=True).Execute

    '~~> Your passwword to open then VBA Project
    MyPassword = "Blah Blah"

    '~~> Get the handle of the "VBAProject Password" Window
    Ret = FindWindow(vbNullString, "VBAProject Password")

    If Ret <> 0 Then
        'MsgBox "VBAProject Password Window Found"

        '~~> Get the handle of the TextBox Window where we need to type the password
        ChildRet = FindWindowEx(Ret, ByVal 0&, "Edit", vbNullString)

        If ChildRet <> 0 Then
            'MsgBox "TextBox's Window Found"
            '~~> This is where we send the password to the Text Window
            SendMess MyPassword, ChildRet

            DoEvents

            '~~> Get the handle of the Button's "Window"
            ChildRet = FindWindowEx(Ret, ByVal 0&, "Button", vbNullString)

            '~~> Check if we found it or not
            If ChildRet <> 0 Then
                'MsgBox "Button's Window Found"

                '~~> Get the caption of the child window
                strBuff = String(GetWindowTextLength(ChildRet) + 1, Chr$(0))
                GetWindowText ChildRet, strBuff, Len(strBuff)
                ButCap = strBuff

                '~~> Loop through all child windows
                Do While ChildRet <> 0
                    '~~> Check if the caption has the word "OK"
                    If InStr(1, ButCap, "OK") Then
                        '~~> If this is the button we are looking for then exit
                        OpenRet = ChildRet
                        Exit Do
                    End If

                    '~~> Get the handle of the next child window
                    ChildRet = FindWindowEx(Ret, ChildRet, "Button", vbNullString)
                    '~~> Get the caption of the child window
                    strBuff = String(GetWindowTextLength(ChildRet) + 1, Chr$(0))
                    GetWindowText ChildRet, strBuff, Len(strBuff)
                    ButCap = strBuff
                Loop

                '~~> Check if we found it or not
                If OpenRet <> 0 Then
                    '~~> Click the OK Button
                    SendMessage ChildRet, BM_CLICK, 0, vbNullString
                Else
                    MsgBox "The Handle of OK Button was not found"
                End If
            Else
                 MsgBox "Button's Window Not Found"
            End If
        Else
            MsgBox "The Edit Box was not found"
        End If
    Else
        MsgBox "VBAProject Password Window was not Found"
    End If
End Sub

Sub SendMess(Message As String, hwnd As Long)
    Call SendMessage(hwnd, WM_SETTEXT, False, ByVal Message)
End Sub
Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
Amelie Peter
  • 93
  • 3
  • 14
  • 1
    You need to find the handle of `VBAProject - Properties Window` and then close it :) – Siddharth Rout May 28 '15 at 13:58
  • 1
    Once you find the handle, use `SendMessage hWnd, WM_CLOSE, 0, 0` to close the window – Siddharth Rout May 28 '15 at 14:01
  • I am fairly new to vba programming. Could you please tell me how to do that? – Amelie Peter May 28 '15 at 14:01
  • Well, if you go through the code, it tells you how to find the handle of the window :) Give it a try and if you are still stuck then post the code that you tried and we will take it from there? – Siddharth Rout May 28 '15 at 14:02
  • I tried this Ret1 = FindWindow(vbNullString, "VBAProject - Project Properties") If Ret1 <> 0 Then SendMessage Ret1, WM_CLOSE, 0, 0 Else MsgBox "The Handle of OK Button was not found" End If But no luck. And I am not sure where to place it. – Amelie Peter May 28 '15 at 14:17
  • 2
    Ok.. lets think logically here. `1` When will you try to find that window? Before that window opens? Or after that window opens? if you think it is after that window opens when which line in the above code is causing that window to open? Do you think placing that code after that line might help? :) – Siddharth Rout May 28 '15 at 14:21
  • I suppose Ret = FindWindow(vbNullString, "VBAProject Password") ChildRet = FindWindowEx(Ret, ByVal 0&, "Edit", vbNullString) is what opens the VBAProject Password window. But not able to figure out what opens VBAProject - Project Properties :( – Amelie Peter May 28 '15 at 14:33
  • 1
    It is very easy for me to give you the answer that you are looking for but that won't help you in the long run :) I would recommend taking some time out to understand the code and then stepping through the code to see what each line does. – Siddharth Rout May 28 '15 at 14:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/79024/discussion-between-siddharth-rout-and-amelie-peter). – Siddharth Rout May 28 '15 at 14:37
  • Could you please provide the solution. I am badly in need of it. – Amelie Peter May 28 '15 at 17:53
  • Amelie, StackOverflow is not a code writing service where we give the code in a platter. And I don't want to start a wrong precedence. I tried helping you but you are not ready to help yourself. If you really need someone to code it for you then may I please suggest www.Freelancer.com or www.elance.com. I am sorry I won't be of much help anymore. – Siddharth Rout May 28 '15 at 17:56
  • I never ask you to write code for me. It was because I was not able to understand the code completely, I posted this question on stack overflow. Please understand that not every one is a expert. You said me you were trying to help me out. If so, Why could you have done it straight forward way? Its always better to keep the conversation short and crisp. – Amelie Peter May 28 '15 at 19:13

1 Answers1

2

@Amelie:

    Ret1 = FindWindow(vbNullString, "VBAProject - Project Properties")

If Ret1 <> 0 Then
ChildRet1 = FindWindowEx(Ret1, ByVal 0&, "Button", vbNullString)

If ChildRet1 <> 0 Then
    strBuff = String(GetWindowTextLength(ChildRet1) + 1, Chr$(0))

    GetWindowText ChildRet1, strBuff, Len(strBuff)

    ButCap = strBuff

    Do While ChildRet1 <> 0
        If InStr(1, ButCap, "OK") Then
            OpenRet1 = ChildRet1
            Exit Do
        End If

        ChildRet1 = FindWindowEx(Ret, ChildRet1, "Button", vbNullString)
        strBuff = String(GetWindowTextLength(ChildRet1) + 1, Chr$(0))
        GetWindowText ChildRet1, strBuff, Len(strBuff)
        ButCap = strBuff
    Loop

    If OpenRet1 <> 0 Then SendMessageA OpenRet1, BM_CLICK, 0, vbNullString
End If
End If
findwindow
  • 3,133
  • 1
  • 13
  • 30