Dealing with the open/save/save as window in IE 9 on Excel 2013 VBA (x64)

Catius

New Member
Joined
Feb 9, 2015
Messages
12
Hello everyone,

I have read many articles about dealing with the open/save/save as window in IE when using VBA, however none of the mentioned solutions is working in my situation.
I am trying to automate the following procedure:

  1. go on Free Keyword Density Analyzer Tool
  2. enter the wanted url in the appropriate field
  3. click submit
  4. then on the following page, click the export buttons placed in the middle and right columns
  5. each time save the file as "Desired name".csv
The subroutine I wrote manages to go through points 1 to 4 but I'm struck for the 5th point. Sendkeys (link) don't work, as well as this link, which seems to be written for 32bits systems.
Here is the subroutine:
Code:
Public Sub principal()Dim i As Long
Dim IE As Object
Dim objElement As Object
Dim objCollection As Object


Set IE = CreateObject("InternetExplorer.Application")


IE.Visible = True
IE.Navigate "http://tools.seobook.com/general/keyword-density/"


Do
DoEvents
Loop Until IE.READYSTATE = 3


Do
DoEvents
Loop Until IE.READYSTATE = 4


Set objCollection = IE.document.getElementsByTagName("textarea")
   i = 0
   For Each objets In objCollection
           objets.InnerText = "http://www.bbc.com/"
   Next objets




With IE.document


    Set elems = .getElementsByTagName("input")
    For Each e In elems
        If (e.className = "btn btn-primary pull-right") Then
            e.Click
            Exit For
        End If
    Next e


End With




Do
DoEvents
Loop Until IE.READYSTATE = 3


Do
DoEvents
Loop Until IE.READYSTATE = 4


'second page
With IE.document


    Set elems = .getElementsByTagName("a")
    For Each e In elems
        If (e.className = "btn btn-small pull-right export") Then
            e.Click
            SendKeys "{DOWN}", True
              SendKeys "{TAB}", True
                SendKeys "{TAB}", True
                SendKeys "{ENTER}", True
        End If
    Next e


End With





End Sub



I am on Excel 2013, with IE 9, on a 64 bits system.
Thanks in advance for your help,
 

Excel Facts

How to calculate loan payments in Excel?
Use the PMT function: =PMT(5%/12,60,-25000) is for a $25,000 loan, 5% annual interest, 60 month loan.
this link, which seems to be written for 32bits systems.

I am on Excel 2013, with IE 9, on a 64 bits system.
Yes, that code is written for 32-bit Office. You will have change the Windows API declarations to 64-bit to run it on your system; see Excel: Declaring API functions in 64 bit Office. For example, change FindWindow to:
Code:
Private Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal WindowName As String) As LongPtr
See Download Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support from Official Microsoft Download Center (linked on that JKP page) for the other API declarations.

However, rather than clicking the Export links and handling the IE file download windows, it would be easier to simply scrape the data from the page by parsing the HTML elements.
 
Upvote 0
Thank you for your answer John_w .


I looked at the link you mention. There are however some functions that are not translated into the 64-bit system:
Code:
Private Declare Function GetWindowTextLength Lib "user32" Alias _
"GetWindowTextLengthA" (ByVal hwnd As Long) As Long


Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long
 
Private Declare Sub SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal _
hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As _
Long, ByVal cy As Long, ByVal wFlags As Long)
 
Private Declare Function SetCursorPos Lib "user32" _
(ByVal X As Integer, ByVal Y As Integer) As Long
 
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
 
Private Declare Sub mouse_event Lib "user32.dll" (ByVal dwFlags As Long, _
ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
How to convert these?



As for parsing the HTML elements, I unfortunately don't know the steps on how to do it and would need to start from scratch... If I manage to get the APIs to work, I think it will just do the trick.
 
Upvote 0
For those functions add "PtrSafe" after the "Declare" and change the hwnd argument to LongPtr. E.g.
Code:
Private Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias _
"GetWindowTextLengthA" (ByVal hwnd As LongPtr) As Long

Other changes may be needed for the other functions you listed. As mentioned on the JKP page, if you download and install Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support, all the declarations are in the installed .txt file.
 
Upvote 0
Ok, I managed to enter all the functions in the 64-bits style and to modify the rest of the code accordingly.

What I found after several tries is that Excel cannot find the download window. This seems to come from the fact that it is in fact a frame notification bar:
WBNI3.png


There are few information about this bar. I tried what is mentionned here , but I get an error message on the InvokePattern.

Here is my current code (handling the window popup):
Code:
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr


Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr


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


Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As LongPtr) As Long




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


Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As RECT) As Long


Declare PtrSafe Function SetWindowPos Lib "user32" (ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long


Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long


Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)


Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As LongPtr)


Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal hwnd As LongPtr) As Long


'~~> Constants for pressing left button of the mouse
Const MOUSEEVENTF_LEFTDOWN As Long = &H2
'~~> Constants for Releasing left button of the mouse
Const MOUSEEVENTF_LEFTUP As Long = &H4
Const WM_SETTEXT As Long = &HC
Const BM_CLICK = &HF5
Const HWND_TOPMOST = -1
Const HWND_NOTOPMOST = -2
Const SWP_NOSIZE = &H1
Const SWP_NOMOVE = &H2
Const SWP_NOACTIVATE = &H10
Const SWP_SHOWWINDOW = &H40
 
Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
 
Dim Ret As LongPtr, OpenRet As LongPtr, FlDwndHwnd As Long
Dim ChildRet As LongPtr
Dim strBuff As String, ButCap As String
Dim pos As RECT


Public IE As Object


Public h As LongPtr
Dim IeHandle As LongPtr
 
'~~> Use this if you want to specify your own name in the Save As Window
Const FileSaveAsName = "C:MyFile.csv"


Public Sub Wait(nSec As Double)
    nSec = nSec + Timer
    While nSec > Timer
        DoEvents
    Wend
End Sub
 
Public Sub SendMess(Message As String, hwnd As LongPtr)
    Call SendMessage(hwnd, WM_SETTEXT, False, ByVal Message)
End Sub
 
Public Sub CommandButton1_Click()


Dim o As IUIAutomation
Dim e As IUIAutomationElement
    
    Ret = FindWindow(vbNullString, "File Download")
    
    If Ret <> 0 Then
        MsgBox "Main Window Found"
 
        '~~> Get the handle of the Button's "Window"
        ChildRet = FindWindowEx(Ret, ByVal 0&, "Button", vbNullString)
        ChildRet = FindWindowEx(Ret, ByVal 0&, "Bouton", vbNullString)
        If ChildRet = 0 Then
            MsgBox "Child Window Not Found"
            Exit Sub
        End If
 
        '~~> 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 "Save"
            If InStr(1, ButCap, "Save") 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
            MsgBox "The Handle of Save Button was not found"
            Exit Sub
        End If
 
        '~~> Retrieve the dimensions of the bounding rectangle of the
        '~~> specified window. The dimensions are given in screen
        '~~> coordinates that are relative to the upper-left corner of the screen.
        GetWindowRect OpenRet, pos
 
        '~~> Move the cursor to the specified screen coordinates.
        SetCursorPos (pos.Left - 10), (pos.Top - 10)
        '~~> Suspends the execution of the current thread for a specified interval.
        '~~> This give ample amount time for the API to position the cursor
        Sleep 100
        SetCursorPos pos.Left, pos.Top
        Sleep 100
        SetCursorPos (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2
 
        '~~> Set the size, position, and Z order of "File Download" Window
        SetWindowPos Ret, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE
        Sleep 100
 
        '~~> Simulate mouse motion and click the button
        '~~> Simulate LEFT CLICK
        mouse_event MOUSEEVENTF_LEFTDOWN, (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2, 0, 0
        Sleep 700
        '~~> Simulate Release of LEFT CLICK
        mouse_event MOUSEEVENTF_LEFTUP, (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2, 0, 0
 
        Wait 10
 
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        ' START OF SAVEAS ROUTINE '
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        Ret = FindWindow(vbNullString, "Save As")
 
        If Ret = 0 Then
            MsgBox "Save As Window Not Found"
            Exit Sub
        End If
 
        '~~> UNCOMMENT this if using IE6 and COMMENT the code for "DUIViewWndClassName"
        '~~> "DirectUIHWND" and "FloatNotifySink"
 
        ' '~~> Get the handle of the Main ComboBox
        ' ChildRet = FindWindowEx(Ret, ByVal 0&, "ComboBoxEx32", "")
        '
        ' If ChildRet = 0 Then
        ' MsgBox "ComboBoxEx32 Window Not Found"
        ' Exit Sub
        ' End If
 
        ChildRet = FindWindowEx(Ret, ByVal 0&, "DUIViewWndClassName", "")
        If ChildRet = 0 Then
            MsgBox "DUIViewWndClassName Not Found"
            Exit Sub
        End If
 
        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "DirectUIHWND", "")
        If ChildRet = 0 Then
            MsgBox "DirectUIHWND Not Found"
            Exit Sub
        End If
 
        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "FloatNotifySink", "")
        If ChildRet = 0 Then
            MsgBox "FloatNotifySink Not Found"
            Exit Sub
        End If
 
        '~~> Get the handle of the Main ComboBox
        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "ComboBox", "")
 
        If ChildRet = 0 Then
            MsgBox "ComboBox Window Not Found"
            Exit Sub
        End If
 
        '~~> Get the handle of the Edit
        ChildRet = FindWindowEx(ChildRet, ByVal 0&, "Edit", "")
 
        If ChildRet = 0 Then
            MsgBox "Edit Window Not Found"
            Exit Sub
        End If
 
        '~~> COMMENT the below 3 lines if you do not want to specify a filename
        Wait 10
        SendMess FileSaveAsName, ChildRet
        Wait 10
 
        '~~> Get the handle of the Save Button in the Save As Dialog Box
        ChildRet = FindWindowEx(Ret, ByVal 0&, "Button", vbNullString)
 
        '~~> Check if we found it or not
        If ChildRet = 0 Then
            MsgBox "Save Button in Save As Window Not Found"
            Exit Sub
        End If
 
        '~~> 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 "Save"
            If InStr(1, ButCap, "Save") 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
            MsgBox "The Handle of Save Button in Save As Window was not found"
            Exit Sub
        End If
 
        '~~> Save the file
        SendMessage OpenRet, BM_CLICK, 0, ByVal 0&
 
        Wait 10
    Else
        MsgBox "File Download Window Not found"
    End If
    Exit Sub


End Sub
 




Public Sub principal()
'Private Sub Populate_Click()
    Dim i As Long


    Dim objElement As Object
    Dim objCollection As Object


Set IE = CreateObject("InternetExplorer.Application")
IeHandle = IE.hwnd


IE.Visible = True
IE.Navigate "http://tools.seobook.com/general/keyword-density/"


'Do Until IE.READYSTATE = READYSTATE_COMPLETE
'Loop




Do
DoEvents
Loop Until IE.READYSTATE = 3


Do
DoEvents
Loop Until IE.READYSTATE = 4


Set objCollection = IE.document.getElementsByTagName("textarea")
   i = 0
   For Each objets In objCollection
           objets.InnerText = "http://www.bbc.com" 'nom page web
   Next objets
   


With IE.document


    Set elems = .getElementsByTagName("input")
    For Each e In elems
        If (e.className = "btn btn-primary pull-right") Then
            e.Click
            Exit For
        End If
    Next e


End With




Do
DoEvents
Loop Until IE.READYSTATE = 3


Do
DoEvents
Loop Until IE.READYSTATE = 4


'2eme page
With IE.document


    Set elems = .getElementsByTagName("a")
    For Each e In elems
        If (e.className = "btn btn-small pull-right export") Then
            e.Click
             Call CommandButton1_Click
        End If
    Next e


End With




End Sub

Thanks for any help
 
Last edited:
Upvote 0
What I found after several tries is that Excel cannot find the download window. This seems to come from the fact that it is in fact a frame notification bar:
WBNI3.png


There are few information about this bar. I tried what is mentionned here , but I get an error message on the InvokePattern.
Did you see:

"NOTE: For people using IE9, depending on the link that you pass to the browser, you may or may not see the Info Security Bar. If you see the Info security bar then I suggest seeing this link where I have attached an exe file which you can use to bypass the IE9 Info Security Bar."
 
Upvote 0
Yes, I tried with the exe file and the problem remains the same. I have tried the workarounds mentionned but the notification still appears as a frame notification bar.
I am now trying to solve it by using Selenium with Firefox browser...
 
Upvote 0
Thank you for your answer John_w .


I looked at the link you mention. There are however some functions that are not translated into the 64-bit system:
Code:
Private Declare Function GetWindowTextLength Lib "user32" Alias _
"GetWindowTextLengthA" (ByVal hwnd As Long) As Long


Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _
lpRect As RECT) As Long
 
Private Declare Sub SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal _
hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As _
Long, ByVal cy As Long, ByVal wFlags As Long)
 
Private Declare Function SetCursorPos Lib "user32" _
(ByVal X As Integer, ByVal Y As Integer) As Long
 
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
 
Private Declare Sub mouse_event Lib "user32.dll" (ByVal dwFlags As Long, _
ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
How to convert these?



As for parsing the HTML elements, I unfortunately don't know the steps on how to do it and would need to start from scratch... If I manage to get the APIs to work, I think it will just do the trick.

Even I am on this assignment for sometime but I could not find the handle of Save Button on
the download notification bar. Even SPYXX Tool is not finding the handle.
However pressing Alt+s saving the file. Therefore you could do sendkeys alt+s as below and try
SetForegroundWindow (IE.hWnd)
SetActiveWindow (IE.hWnd)
Sleep 20
SendKeys ("%{s}")
Sleep 20
Also Cntrl j opens Download Manager and you could do something using that
 
Upvote 0
Thanks for the code. Unfortunately I did not manage to make solutions based on sendkeys worked. Even with the SetActiveWindow command, nothing happens on the screen, as if the sendkeys were not transmitted to IE. Same thing for CTRL+J, did not open anything...
 
Upvote 0

Forum statistics

Threads
1,214,947
Messages
6,122,411
Members
449,081
Latest member
JAMES KECULAH

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top