Need help regarding IE Automation using VBA

image_1

New Member
Joined
Oct 17, 2010
Messages
9
I have to download a csv file from a website like 50 times a day. I want to automate the process using vba so that i can process it later in excel.
the details are :
website: http://www.nrldc.org/WBS/injsch.aspx
csv file to download labelled by : (ncr)
here is what i have tried but it is not working. need help



Sub Update()
Dim IE As Object
On Error GoTo error_handler
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Navigate "http://www.nrldc.org/WBS/injsch.aspx"
Do While .Busy: DoEvents: Loop
Do While .ReadyState <> 4: DoEvents: Loop
.Visible = True
End With
For Each lnk In objIE.document.Links
If (InStr(lnk, "(ncr)")) Then
'Code to be executed in case it's a good link
objIEPage.Navigate lnk
While objIEPage.Busy
DoEvents
Wend
End If
Next lnk


objIE.Quit
Set IE = Nothing
Exit Sub
error_handler:
MsgBox ("Unexpected Error, I'm quitting.")
objIE.Quit
Set IE = Nothing
End Sub
 
Well it might be easier to just enter a date in the input box rather than picking the data from the popup calendar.

I'm not even sure it would be possible to do it with calendar.

The other dropdowns are easier.

The only thing is that I thought you didn't want to do that?

That's kind of what I had in my mind earlier and was why I was asking if the only way to get the data was with the download link.

As for the file not saving where you want to, I'm sure it's possible to get it to save where you want.

Frankly though we should think ourselves lucky to even have code that does the download.

When it was posted by John_w it was the first time I'd seen it done.

I kind of knew it was possible but always opted to explore other methods of getting the data if possible.

Can you post some examples of the inputs you might want to use for the date and the other variables?

PS I just had a look at the code for the popup and it is just showing for showing a calendar sized ASP page.

Each date in the month is a link that fires some code that 'posts' the selected date to the main form.

It probably is possible to use code to 'click' those links or run the code but it would be easier just to put the date in the inputbox.

I'll post some code for that later.:)
 
Upvote 0

Excel Facts

Best way to learn Power Query?
Read M is for (Data) Monkey book by Ken Puls and Miguel Escobar. It is the complete guide to Power Query.
Hi image_1

Do you want to get data for a particular date?
If yes, please check the code below

Code:
Private Sub GetData()

'Add YOUR website
'to Internet Explorer
'trusted website

'Open IE-Internet Options-Security-Trusted Sites-Sites
'then YOUR site

Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
IE.Visible = True

'To open the website
.navigate "http://www.nrldc.org/WBS/injsch.aspx"
Do While .Busy: DoEvents: Loop
Do While .readyState <> 4: DoEvents: Loop

[COLOR="DarkOrange"]'To set the date
IE.document.all.Item("txtStartDate").Value = "19-11-2010"
'here put your date or
'programatically get date

Do While .Busy: DoEvents: Loop
Do While .readyState <> 4: DoEvents: Loop[/COLOR]

'To download the file
IE.navigate "javascript:__doPostBack('downloadncr','')"
Do While .Busy: DoEvents: Loop
End With

End Sub
 
Upvote 0
john,

I tried to run the subroutine as specified by you but it is saving the file in the default directory only. I m using Windows Vista + IE 8.
The code was developed on Windows XP and IE8. Sorry, I can't help with testing it on Vista. There might be an issue with UIPI, because the code uses SendMessage to send mouse clicks to IE, though according to that page IE has the lowest privilege level and therefore any other process should be able to send messages to it.
1. "Test_Save_As_Set_Filename()" is never called then whats the use of it.
It tests the setting of the file name, to allow me to test this part of the download sequence in isolation. The Save As window must be displayed before running this routine.
2. In "Save_As_Set_Filename(folder As String, filename As String)" the code is trying to find the "child edit window" which I could not understand as when I save the file in IE I get a "Save as" dialog box with a save button. Then after clicking on the save button i get a window in which we can directly enter the fullfilename (folder & filename). So I could not understand the role of "child edit window"

This is the hierarchy in the code:
Code:
hWnd = FindWindow("#32770", "Save As")
hWnd = FindWindowEx(hWnd, 0, "ComboBoxEx32", vbNullString)
hWnd = FindWindowEx(hWnd, 0, "ComboBox", "")
hWnd = FindWindowEx(hWnd, 0, "Edit", "")

I am pretty sure that this will definitely have some significance otherwise you wouldn't have included it but I hope my doubt also make some sense.
I am using the term 'window' in its Windows API sense: virtually every control (e.g. button, edit box, combobox) in a window is itself a window as far as the API is concerned, hence the use of FindWindow and FindWindowEx to find those 'windows'.

I've designed the code based on processing the normal visible windows that appear when the whole download sequence is done manually or automatically, and the subroutine names are based on the window caption and required action in that window:

File_Download_Click_Save
Save_As_Set_Filename saveInFolder, saveAsFilename
Save_As_Click_Save
Download_complete_Click_Close

Note that the 'Download complete' window is displayed only if 'Notify when download completes' in IE's Advanced Options is ticked (which can be set via the 'Close this window when download completes' checkbox on the window itself), however Download_complete_Click_Close will just time out if the window isn't displayed.

To prevent the '< file> already exists' window appearing, you must ensure that the filename is unique. Some web sites generate a unique filename, but yours is always "FileName". To generate your own unique filename, you could use:

Code:
    Dim saveInFolder As String, saveAsFilename As String
    
    saveInFolder = "C:\my\folder\"
    saveAsFilename = "test_" & Format(Now, "yyyymmdd_HhNnSs")

    Download_File URL, saveInFolder, saveAsFilename
 
Last edited:
Upvote 0
Hi Guys, I know this thread is really old but I am sure it is relevant. Has anybody been able to get this to work on Windows 7. I keep getting a mismatch error on the Save_As_Set_Filename. Next it does not locate the Combobox or Edit.

I do not know how to locate the download URL.

Is there possibly an updated code?
 
Last edited:
Upvote 0
sskicker23, I don't have Windows 7 so can't test it on that system. Regarding the mismatch error, make sure you have Option Explicit at the top of every VBA module, compile the project and correct any resulting errors.

Here is updated code which handles the 'File already exists. Do you want to replace it?' window and clicks the 'Yes' button.

The code automates IE, navigating to http://www.nrldc.org/WBS/injsch.aspx and clicking the '(ncr)' link to download the .csv file. The IE automation is specific to http://www.nrldc.org/WBS/injsch.aspx, but the code which handles the IE download (the Download_File subroutine) should work with most sites from which you can download files.

Put the following code in a standard VBA module (named modMain):
Code:
Option Explicit

'Note - IE may block the download, displaying its Information Bar at the top of the tab, and preventing this program from
'automatically downloading the file.  To prevent this, add http://www.nrldc.org to IE's Trusted sites (Tools - Internet Options -
'Security - Trusted sites - Sites)


Public Sub Main_Download()
    
    Dim URL As String
    Dim startDate As Date
    Dim saveInFolder As String, saveAsFilename As String
    
    URL = "http://www.nrldc.org/WBS/injsch.aspx"
    
    saveInFolder = "C:\temp\Excel\"    
    saveAsFilename = ""     'use default filename
    startDate = Date
    
    IE_Navigate_and_Download URL, startDate, saveInFolder, saveAsFilename

End Sub


Private Sub IE_Navigate_and_Download(URL As String, startDate As Date, saveInFolder As String, saveAsFilename As String)

    Dim IE As Object
    Dim dateInput As Object
    
    'Use existing IE window or open a new IE window
        
    Set IE = Get_IE_Window()
    If IE Is Nothing Then
        Set IE = CreateObject("InternetExplorer.Application")
    End If
    
    With IE
        SetForegroundWindow .hWnd
        .Visible = True
        .Navigate URL
        While .Busy Or .ReadyState <> 4: DoEvents: Wend
    
        'Populate HTML text box with specified date and refresh page
        
        Set dateInput = .Document.forms(0).elements("txtStartDate")
        If Not dateInput Is Nothing Then
            dateInput.Value = Format(startDate, "dd-mm-yyyy")
            .Navigate "javascript:__doPostBack('txtStartDate','')"
            While .Busy Or .ReadyState <> READYSTATE_COMPLETE: DoEvents: Wend
        Else
            MsgBox "txtStartDate HTML element not found - unable to set specified date"
        End If
        
        'Click the download ncr link
        
        .Navigate "javascript:__doPostBack('downloadncr','')"
    
    End With
    
    Download_File saveInFolder, saveAsFilename
    
    SetForegroundWindow Application.hWnd

End Sub


Private Sub Download_File(saveInFolder As String, saveAsFilename As String)

    'Handles the whole IE download file sequence
    
    Dim fileExists As Boolean
    
    'File Download window, with Open, Save and Cancel buttons - click Save
    
    File_Download_Click_Save
       
    'Save As window - set full filename
    
    Save_As_Set_Filename saveInFolder, saveAsFilename
    
    'Save As window - click Save and replace file if the '<file> already exists' popup window appears
    
    fileExists = Save_As_Click_Save
    If fileExists Then
        File_Already_Exists Replace:=True
    End If
    
    'Optional Download complete window, with Open, Open Folder and Close buttons - click Close, or time out if window is not present
    'This window also has a checkbox 'Close this dialog box when download completes'.  This checkbox setting is controlled
    'by 'Notify when downloads complete' in IE advanced options.  If this checkbox is ticked, the following line is not required,
    'though it shouldn't matter if it is left in as the routine will time out if the window isn't found.
    
    Download_complete_Click_Close
    
    Debug.Print "Download finished"

End Sub


Private Sub File_Download_Click_Save()
    
    Dim hWnd As Long
    Dim timeout As Date
    
    Debug.Print "File_Download_Click_Save"
    
    'Find the File Download window, waiting a maximum of 30 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:30")
    Do
        hWnd = FindWindow("#32770", "File Download")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout
    
    Debug.Print "   File Download window "; Hex(hWnd)
    
    If hWnd Then

        'Find the child Save button
        
        hWnd = FindWindowEx(hWnd, 0, "Button", "&Save")
        Debug.Print "   Save button "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Click the Save button
        
        SetForegroundWindow hWnd
        Sleep 600  'this sleep is required and 600 milliseconds seems to be the minimum that works
        SendMessage hWnd, BM_CLICK, 0, 0
    End If

End Sub


Private Sub Save_As_Set_Filename(folder As String, filename As String)

    'Populate the 'File name:' edit window in the Save As dialogue with the specified folder and/or filename.
    'If folder = "" a folder path is not prepended to the filename and therefore the default save folder is used.
    'If filename = "" the default file name (already populated) is used.
    
    'The Save As window has the following child window hierarchy:
    
    '   "Save As", #32770 Dialog
    '       "FileName", ComboBoxEx32        (FileName is the default File name value in combobox)
    '           "", ComboBox
    '               "FileName", Edit        (FileName is the default File name value in combobox's edit box)
    
    Dim hWnd As Long
    Dim timeout As Date
    Dim fullFilename As String
    
    Debug.Print "Save_As_Set_Filename"
    Debug.Print "folder   = " & folder
    Debug.Print "filename = " & filename
    
    'Find the Save As window, waiting a maximum of 10 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:10")
    Do
        hWnd = FindWindow("#32770", "Save As")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout

    If hWnd Then
    
        SetForegroundWindow hWnd
        
        'Find the child ComboBoxEx32 window
        
        hWnd = FindWindowEx(hWnd, 0, "ComboBoxEx32", vbNullString)
        Debug.Print "   ComboBoxEx32 "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Find the child ComboBox window
        
        hWnd = FindWindowEx(hWnd, 0, "ComboBox", "")
        Debug.Print "   ComboBox "; Hex(hWnd)
    End If
                 
    If hWnd Then
        
        SetForegroundWindow hWnd

        'Find the child Edit window
        
        hWnd = FindWindowEx(hWnd, 0, "Edit", "")
        Debug.Print "   Edit "; Hex(hWnd)
    End If
    
    If hWnd Then
            
        If filename = "" Then
            'Get default filename (already populated in Edit window)
            filename = Get_Window_Text(hWnd)
        End If
       
        'If specified, ensure folder ends with \
        If folder <> "" And Right(folder, 1) <> "\" Then folder = folder & "\"
        
        fullFilename = folder & filename
        Debug.Print "Full filename " & fullFilename
        
        'Populate the Edit window with the full file name
        
        Sleep 200
        SetForegroundWindow hWnd
        SendMessageByString hWnd, WM_SETTEXT, Len(fullFilename), fullFilename
    End If
    
End Sub


Private Function Get_Window_Text(hWnd As Long) As String

    'Returns the text in the specified window
    
    Dim Buffer As String
    Dim length As Long
    Dim result As Long
    
    SetForegroundWindow hWnd
    length = SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0)
    Buffer = Space(length + 1)  '+1 for the null terminator
    result = SendMessage(hWnd, WM_GETTEXT, Len(Buffer), ByVal Buffer)
    Debug.Print "Edit File name = " & Left(Buffer, length)
    Debug.Print "        length = " & length
    
    Get_Window_Text = Left(Buffer, length)
    
End Function


Private Function Save_As_Click_Save() As Boolean

    'Click the Save button in the Save As dialogue, returning True if the '<file> already exists'
    'window appears, otherwise False
    
    Dim hWnd As Long, hWndSaveAs As Long
    Dim timeout As Date
    
    Debug.Print "Save_As_Click_Save"

    'Find the Save As window, waiting a maximum of 10 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:10")
    Do
        hWnd = FindWindow(vbNullString, "Save As")
        hWndSaveAs = hWnd
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout
    Debug.Print "   Save As window "; Hex(hWnd)

    If hWnd Then
    
        SetForegroundWindow hWnd
            
        'Get the child Save button
        
        hWnd = FindWindowEx(hWnd, 0, "Button", "&Save")
        Debug.Print "   Save button "; Hex(hWnd)
    End If
    
    If hWnd Then
        
        'Click the Save button
        
        'This can cause the '<file> already exists' popup window to be displayed.  The button click is sent with PostMessage
        'because SendMessage doesn't return until the window is closed (by clicking Yes or No)
        
        'PostMessage - http://msdn.microsoft.com/en-us/library/ms644944%28v=VS.85%29.aspx
        'Places (posts) a message in the message queue associated with the thread that created the specified window and returns
        'without waiting for the thread to process the message.
        
        'SendMessage - http://msdn.microsoft.com/en-us/library/ms644950%28VS.85%29.aspx
        'The SendMessage function calls the window procedure for the specified window and does not return until the
        'window procedure has processed the message.
        
        'SendMessage hWnd, BM_CLICK, 0, 0
        Sleep 100
        SetForegroundWindow hWnd
        PostMessage hWnd, BM_CLICK, 0, 0
        Debug.Print "   Clicked Save button"
    End If
        
    If hWnd Then
    
        'Set function return value depending on whether or not the '<file> already exists' popup window exists
        
        'Note - the popup window is a modal dialogue box and a child of the main Save As window.  Both windows have the
        'same class (#32770) and caption (Save As).  This may present a problem in finding the popup window, however in all tests
        'FindWindow has correctly found the popup window.  Therefore the additional FindWindowEx, which looks for the Yes button
        'as a child of the popup window is not necessary
        
        Sleep 500
        hWnd = FindWindow("#32770", "Save As")
        
        'This alternative FindWindowEx call, which looks for the popup window as a child of the main Save As window, doesn't find it,
        'returning 0 for hWnd
        'hWnd = FindWindowEx(hWndSaveAs, 0, "#32770", "Save As")
        
        Debug.Print "   Save As - <file> already exists popup window "; Hex(hWnd)
        'hWnd = FindWindowEx(hWnd, 0, "Button", "&Yes")
        
        If hWnd Then
            Save_As_Click_Save = True
        Else
            Save_As_Click_Save = False
        End If
        
    End If
        
End Function


Private Sub File_Already_Exists(Replace As Boolean)

    'Click Yes or No in the '<file> already exists. Do you want to replace it?' window
    
    Dim hWnd As Long
    
    Debug.Print "File_Already_Exists("; Replace; ")"

    hWnd = FindWindow("#32770", "Save As")
    Debug.Print "   Save As popup window "; Hex(hWnd)
    
    If hWnd Then
        If Replace Then
            hWnd = FindWindowEx(hWnd, 0, "Button", "&Yes")
            Debug.Print "   Yes button "; Hex(hWnd)
        Else
            hWnd = FindWindowEx(hWnd, 0, "Button", "&No")
            Debug.Print "   No button "; Hex(hWnd)
        End If
    End If
    
    If hWnd Then
        SendMessage hWnd, BM_CLICK, 0, 0
    End If

End Sub


Private Sub Download_complete_Click_Close()
    
    Dim hWnd As Long
    Dim timeout As Date
    
    Debug.Print "Download_complete_Click_Close"
        
    'Find the Download complete window, waiting a maximum of 30 seconds for it to appear.  Timeout value is
    'dependent on the size of the download, so make it longer for larger files.
    
    timeout = Now + TimeValue("00:00:30")
    Do
        hWnd = FindWindow("#32770", "Download complete")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout

    Debug.Print "   Download complete window "; Hex(hWnd)
    
    If hWnd Then

        'Find the child Close button
        
        hWnd = FindWindowEx(hWnd, 0, "Button", "Close")
        Debug.Print "   Close button "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Click the Close button
        
        SetForegroundWindow hWnd
        Sleep 600  'this sleep is required and 600 milliseconds seems to be the minimum that works
        SendMessage hWnd, BM_CLICK, 0, 0
    End If

End Sub


Private Function Get_IE_Window() As Object

    'Look for an IE browser window and, if found, return that browser as an InternetExplorer object.  Otherwise return Nothing

    Dim Shell As Object
    Dim IE As Object
    Dim i As Variant 'Integer
    
    Set Shell = CreateObject("Shell.Application")
    
    i = 0
    Set Get_IE_Window = Nothing
    While i < Shell.Windows.Count And Get_IE_Window Is Nothing
        Set IE = Shell.Windows.Item(i)
        If Not IE Is Nothing Then
            If TypeName(IE.Document) = "HTMLDocument" Then
                Set Get_IE_Window = IE
            
                'Activate this tab (the first tab) by pressing Ctrl+1
                
                SetForegroundWindow Get_IE_Window.hWnd
                PressKeys VK_CONTROL, Asc("1")
            
            End If
        End If
        i = i + 1
    Wend
    
End Function


Private Sub PressKeys(vKey1 As Long, vKey2 As Long)
    KeyEvent vKey1, True, False     'key1 down
    Sleep 10
    KeyEvent vKey2, True, True      'key2 down and up
    Sleep 10
    KeyEvent vKey1, False, True     'key1 up
End Sub


Private Sub KeyEvent(ByVal vKey As Long, ByVal keyDown As Boolean, ByVal keyUp As Boolean)
    If keyDown Then keybd_event vKey, 0, VK_KEYDOWN, -11
    If keyUp Then keybd_event vKey, 0, VK_KEYUP, -11
End Sub


'---------- Testing and debugging ---------

Private Sub Test_Save_As_Set_Filename()
    
    'Set the folder and filename in the Save As window.  The Save As window must be already displayed
    
    Dim folder As String, filename As String
    
    folder = ""     'use IE's default download folder
    filename = "test " & Format(Now, "hh_mm_ss") & ".xls"
    Save_As_Set_Filename folder, filename
End Sub


Private Sub Test_Save_As_Click_Save()

    'Click Save in the Save As window and replace file if it already exists.  The Save As window must be already displayed
    
    Dim fileExists As Boolean
    fileExists = Save_As_Click_Save
    If fileExists Then
        File_Already_Exists True
    End If
    Download_complete_Click_Close
End Sub
Put the following code in another standard VBA module (named modWindowsAPI):
Code:
Option Explicit

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

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

Public 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

Public Declare Function SetForegroundWindow Lib "user32" _
    (ByVal hWnd As Long) As Long

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

Public Declare Function SendMessageByString Lib "user32" Alias "SendMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long

Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Declare Sub keybd_event Lib "user32" _
    (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

Public Const BM_CLICK = &HF5
Public Const WM_SETTEXT = &HC
Public Const WM_GETTEXT = &HD
Public Const WM_GETTEXTLENGTH = &HE

Public Const VK_KEYDOWN = &H0
Public Const VK_KEYUP = &H2
Public Const VK_CONTROL = &H11
 
Upvote 0
Hi John,

I modified your code to suit my project however I am not able to find the click command in the website, i did manage to login with username and passward, then go into the page that i want then filled in some information and execute the download option to download the excel file, i would assume if I could do that download execution the rest of your macro should work fine. Here is my macro code, of course i will have a separate module for modWindowsAPI

Code:
Option Explicit
 
'Note - IE may block the download, displaying its Information Bar at the top of the tab, and preventing this program from
'automatically downloading the file.  To prevent this, add [url=http://www.nrldc.org]NRLDC[/url] to IE's Trusted sites (Tools - Internet Options -
'Security - Trusted sites - Sites)
 
 
Public Sub Main_Download()
    
    Dim URL As String
    Dim startDate As Date
    Dim saveInFolder As String, saveAsFilename As String
    
    URL = "[url=http://www.entsoe.net/default.aspx]Entsoe.net[/url]"
    
    saveInFolder = "C:\Documents and Settings\manees\Desktop\power project\"
    saveAsFilename = ""     'use default filename
    'startDate = Date
    
    IE_Navigate_and_Download URL, saveInFolder, saveAsFilename
    
End Sub
 
 
Private Sub IE_Navigate_and_Download(URL As String, saveInFolder As String, saveAsFilename As String)
 
    Dim IE As Object
    Dim myURL As String
    'Dim dateInput As Object
    
    'Use existing IE window or open a new IE window
        
    'Set IE = Get_IE_Window()
    'If IE Is Nothing Then
        Set IE = CreateObject("InternetExplorer.Application")
    'End If
    
    With IE
        SetForegroundWindow .hWnd
        .Navigate URL
        .Visible = True
        .Document.all("ctl00$mainInside$txtUsername").Value = "manees"
        .Document.all("ctl00$mainInside$txtPassword").Value = "Yee3906419"
        .Document.all("ctl00_mainInside_lnkSignIn").Click
        
        While .Busy Or .ReadyState <> 4: DoEvents: Wend
         .Navigate "[url=http://www.entsoe.net/data.aspx?IdMenu=2]Entsoe.net[/url]"
         
         .Document.all("ctl00$mainInside$DataMenu1$cboTimeSeries").Value = "66" '15 --- GREECE
         .Document.all("ctl00$mainInside$DataMenu1$txtDate").Value = "19.09.2012"
         .Document.all("ctl00$mainInside$DataMenu1$cboVisualisation").Value = "1"
        
     'Don't know 1. how to refresh the page to take into account my inputs i.e. country, date and tabular 2. execute the click on excel file to download the excel file
 
    End With
    
 
    
    Download_File saveInFolder, saveAsFilename
    
    SetForegroundWindow Application.hWnd
    IE.Quit
End Sub
 
 
Private Sub Download_File(saveInFolder As String, saveAsFilename As String)
 
    'Handles the whole IE download file sequence
    
    Dim fileExists As Boolean
    
    'File Download window, with Open, Save and Cancel buttons - click Save
    
    File_Download_Click_Save
       
    'Save As window - set full filename
    
    Save_As_Set_Filename saveInFolder, saveAsFilename
    
    'Save As window - click Save and replace file if the ' already exists' popup window appears
    
    fileExists = Save_As_Click_Save
    If fileExists Then
        File_Already_Exists Replace:=True
    End If
    
    'Optional Download complete window, with Open, Open Folder and Close buttons - click Close, or time out if window is not present
    'This window also has a checkbox 'Close this dialog box when download completes'.  This checkbox setting is controlled
    'by 'Notify when downloads complete' in IE advanced options.  If this checkbox is ticked, the following line is not required,
    'though it shouldn't matter if it is left in as the routine will time out if the window isn't found.
    
    Download_complete_Click_Close
    
    Debug.Print "Download finished"
 
End Sub
 
 
Private Sub File_Download_Click_Save()
    
    Dim hWnd As Long
    Dim timeout As Date
    
    Debug.Print "File_Download_Click_Save"
    
    'Find the File Download window, waiting a maximum of 30 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:30")
    Do
        hWnd = FindWindow("#32770", "File Download")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout
    
    Debug.Print "   File Download window "; Hex(hWnd)
    
    If hWnd Then
 
        'Find the child Save button
        
        hWnd = FindWindowEx(hWnd, 0, "Button", "&Save")
        Debug.Print "   Save button "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Click the Save button
        
        SetForegroundWindow hWnd
        Sleep 600  'this sleep is required and 600 milliseconds seems to be the minimum that works
        SendMessage hWnd, BM_CLICK, 0, 0
    End If
 
End Sub
 
 
Private Sub Save_As_Set_Filename(folder As String, filename As String)
 
    'Populate the 'File name:' edit window in the Save As dialogue with the specified folder and/or filename.
    'If folder = "" a folder path is not prepended to the filename and therefore the default save folder is used.
    'If filename = "" the default file name (already populated) is used.
    
    'The Save As window has the following child window hierarchy:
    
    '   "Save As", #32770 Dialog
    '       "FileName", ComboBoxEx32        (FileName is the default File name value in combobox)
    '           "", ComboBox
    '               "FileName", Edit        (FileName is the default File name value in combobox's edit box)
    
    Dim hWnd As Long
    Dim timeout As Date
    Dim fullFilename As String
    
    Debug.Print "Save_As_Set_Filename"
    Debug.Print "folder   = " & folder
    Debug.Print "filename = " & filename
    
    'Find the Save As window, waiting a maximum of 10 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:10")
    Do
        hWnd = FindWindow("#32770", "Save As")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout
 
    If hWnd Then
    
        SetForegroundWindow hWnd
        
        'Find the child ComboBoxEx32 window
        
        hWnd = FindWindowEx(hWnd, 0, "ComboBoxEx32", vbNullString)
        Debug.Print "   ComboBoxEx32 "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Find the child ComboBox window
        
        hWnd = FindWindowEx(hWnd, 0, "ComboBox", "")
        Debug.Print "   ComboBox "; Hex(hWnd)
    End If
                 
    If hWnd Then
        
        SetForegroundWindow hWnd
 
        'Find the child Edit window
        
        hWnd = FindWindowEx(hWnd, 0, "Edit", "")
        Debug.Print "   Edit "; Hex(hWnd)
    End If
    
    If hWnd Then
            
        If filename = "" Then
            'Get default filename (already populated in Edit window)
            filename = Get_Window_Text(hWnd)
        End If
       
        'If specified, ensure folder ends with \
        If folder <> "" And Right(folder, 1) <> "\" Then folder = folder & "\"
        
        fullFilename = folder & filename
        Debug.Print "Full filename " & fullFilename
        
        'Populate the Edit window with the full file name
        
        Sleep 200
        SetForegroundWindow hWnd
        SendMessageByString hWnd, WM_SETTEXT, Len(fullFilename), fullFilename
    End If
    
End Sub
 
 
Private Function Get_Window_Text(hWnd As Long) As String
 
    'Returns the text in the specified window
    
    Dim Buffer As String
    Dim length As Long
    Dim result As Long
    
    SetForegroundWindow hWnd
    length = SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0)
    Buffer = Space(length + 1)  '+1 for the null terminator
    result = SendMessage(hWnd, WM_GETTEXT, Len(Buffer), ByVal Buffer)
    Debug.Print "Edit File name = " & Left(Buffer, length)
    Debug.Print "        length = " & length
    
    Get_Window_Text = Left(Buffer, length)
    
End Function
 
 
Private Function Save_As_Click_Save() As Boolean
 
    'Click the Save button in the Save As dialogue, returning True if the ' already exists'
    'window appears, otherwise False
    
    Dim hWnd As Long, hWndSaveAs As Long
    Dim timeout As Date
    
    Debug.Print "Save_As_Click_Save"
 
    'Find the Save As window, waiting a maximum of 10 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:10")
    Do
        hWnd = FindWindow(vbNullString, "Save As")
        hWndSaveAs = hWnd
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout
    Debug.Print "   Save As window "; Hex(hWnd)
 
    If hWnd Then
    
        SetForegroundWindow hWnd
            
        'Get the child Save button
        
        hWnd = FindWindowEx(hWnd, 0, "Button", "&Save")
        Debug.Print "   Save button "; Hex(hWnd)
    End If
    
    If hWnd Then
        
        'Click the Save button
        
        'This can cause the ' already exists' popup window to be displayed.  The button click is sent with PostMessage
        'because SendMessage doesn't return until the window is closed (by clicking Yes or No)
        
        'PostMessage - [url=http://msdn.microsoft.com/en-us/library/ms644944%28v=VS.85%29.aspx]PostMessage function (Windows)[/url]
        'Places (posts) a message in the message queue associated with the thread that created the specified window and returns
        'without waiting for the thread to process the message.
        
        'SendMessage - [url=http://msdn.microsoft.com/en-us/library/ms644950%28VS.85%29.aspx]SendMessage function (Windows)[/url]
        'The SendMessage function calls the window procedure for the specified window and does not return until the
        'window procedure has processed the message.
        
        'SendMessage hWnd, BM_CLICK, 0, 0
        Sleep 100
        SetForegroundWindow hWnd
        PostMessage hWnd, BM_CLICK, 0, 0
        Debug.Print "   Clicked Save button"
    End If
        
    If hWnd Then
    
        'Set function return value depending on whether or not the ' already exists' popup window exists
        
        'Note - the popup window is a modal dialogue box and a child of the main Save As window.  Both windows have the
        'same class (#32770) and caption (Save As).  This may present a problem in finding the popup window, however in all tests
        'FindWindow has correctly found the popup window.  Therefore the additional FindWindowEx, which looks for the Yes button
        'as a child of the popup window is not necessary
        
        Sleep 500
        hWnd = FindWindow("#32770", "Save As")
        
        'This alternative FindWindowEx call, which looks for the popup window as a child of the main Save As window, doesn't find it,
        'returning 0 for hWnd
        'hWnd = FindWindowEx(hWndSaveAs, 0, "#32770", "Save As")
        
        Debug.Print "   Save As -  already exists popup window "; Hex(hWnd)
        'hWnd = FindWindowEx(hWnd, 0, "Button", "&Yes")
        
        If hWnd Then
            Save_As_Click_Save = True
        Else
            Save_As_Click_Save = False
        End If
        
    End If
        
End Function
 
 
Private Sub File_Already_Exists(Replace As Boolean)
 
    'Click Yes or No in the ' already exists. Do you want to replace it?' window
    
    Dim hWnd As Long
    
    Debug.Print "File_Already_Exists("; Replace; ")"
 
    hWnd = FindWindow("#32770", "Save As")
    Debug.Print "   Save As popup window "; Hex(hWnd)
    
    If hWnd Then
        If Replace Then
            hWnd = FindWindowEx(hWnd, 0, "Button", "&Yes")
            Debug.Print "   Yes button "; Hex(hWnd)
        Else
            hWnd = FindWindowEx(hWnd, 0, "Button", "&No")
            Debug.Print "   No button "; Hex(hWnd)
        End If
    End If
    
    If hWnd Then
        SendMessage hWnd, BM_CLICK, 0, 0
    End If
 
End Sub
 
 
Private Sub Download_complete_Click_Close()
    
    Dim hWnd As Long
    Dim timeout As Date
    
    Debug.Print "Download_complete_Click_Close"
        
    'Find the Download complete window, waiting a maximum of 30 seconds for it to appear.  Timeout value is
    'dependent on the size of the download, so make it longer for larger files.
    
    timeout = Now + TimeValue("00:00:30")
    Do
        hWnd = FindWindow("#32770", "Download complete")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout
 
    Debug.Print "   Download complete window "; Hex(hWnd)
    
    If hWnd Then
 
        'Find the child Close button
        
        hWnd = FindWindowEx(hWnd, 0, "Button", "Close")
        Debug.Print "   Close button "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Click the Close button
        
        SetForegroundWindow hWnd
        Sleep 600  'this sleep is required and 600 milliseconds seems to be the minimum that works
        SendMessage hWnd, BM_CLICK, 0, 0
    End If
 
End Sub
 
 
Private Function Get_IE_Window() As Object
 
    'Look for an IE browser window and, if found, return that browser as an InternetExplorer object.  Otherwise return Nothing
 
    Dim Shell As Object
    Dim IE As Object
    Dim i As Variant 'Integer
    
    Set Shell = CreateObject("Shell.Application")
    
    i = 0
    Set Get_IE_Window = Nothing
    While i < Shell.Windows.Count And Get_IE_Window Is Nothing
        Set IE = Shell.Windows.Item(i)
        If Not IE Is Nothing Then
            If TypeName(IE.Document) = "HTMLDocument" Then
                Set Get_IE_Window = IE
            
                'Activate this tab (the first tab) by pressing Ctrl+1
                
                SetForegroundWindow Get_IE_Window.hWnd
                PressKeys VK_CONTROL, Asc("1")
            
            End If
        End If
        i = i + 1
    Wend
    
End Function
 
 
Private Sub PressKeys(vKey1 As Long, vKey2 As Long)
    KeyEvent vKey1, True, False     'key1 down
    Sleep 10
    KeyEvent vKey2, True, True      'key2 down and up
    Sleep 10
    KeyEvent vKey1, False, True     'key1 up
End Sub
 
 
Private Sub KeyEvent(ByVal vKey As Long, ByVal keyDown As Boolean, ByVal keyUp As Boolean)
    If keyDown Then keybd_event vKey, 0, VK_KEYDOWN, -11
    If keyUp Then keybd_event vKey, 0, VK_KEYUP, -11
End Sub
 
 
'---------- Testing and debugging ---------
 
Private Sub Test_Save_As_Set_Filename()
    
    'Set the folder and filename in the Save As window.  The Save As window must be already displayed
    
    Dim folder As String, filename As String
    
    folder = ""     'use IE's default download folder
    filename = "test " & Format(Now, "hh_mm_ss") & ".xls"
    Save_As_Set_Filename folder, filename
End Sub
 
 
Private Sub Test_Save_As_Click_Save()
 
    'Click Save in the Save As window and replace file if it already exists.  The Save As window must be already displayed
    
    Dim fileExists As Boolean
    fileExists = Save_As_Click_Save
    If fileExists Then
        File_Already_Exists True
    End If
    Download_complete_Click_Close
End Sub
 
Upvote 0
Hi - posting this for future reference for Windows 7 users. Save as dialogue box hierarchy has changed therefore code above wasn't working when filename specified. With some additional levels the following appears to fix;

Code:
Private Sub Save_As_Set_Filename(folder As String, filename As String)

    'Populate the 'File name:' edit window in the Save As dialogue with the specified folder and/or filename.
    'If folder = "" a folder path is not prepended to the filename and therefore the default save folder is used.
    'If filename = "" the default file name (already populated) is used.
    
    'The Save As window has the following child window hierarchy:
    
    '   "Save As", #32770 Dialog
    '       "FileName", ComboBoxEx32        (FileName is the default File name value in combobox)
    '           "", ComboBox
    '               "FileName", Edit        (FileName is the default File name value in combobox's edit box)
    
    Dim hWnd As Long
    Dim timeout As Date
    Dim fullFilename As String
    
    Debug.Print "Save_As_Set_Filename"
    Debug.Print "folder   = " & folder
    Debug.Print "filename = " & filename
    
    'Find the Save As window, waiting a maximum of 10 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:10")
    Do
        hWnd = FindWindow("#32770", "Save As")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout


    If hWnd Then
    
        SetForegroundWindow hWnd
        
        'Find the child DUIViewWndClassName window
        
       hWnd = FindWindowEx(hWnd, 0, "DUIViewWndClassName", vbNullString)
        Debug.Print "   DUIViewWndClassName "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Find the child DirectUIHWND window
        
        hWnd = FindWindowEx(hWnd, 0, "DirectUIHWND", "")
        Debug.Print "   DirectUIHWND "; Hex(hWnd)
    End If
                 
    If hWnd Then
    
        'Find the child FloatNotifySink window
        
        hWnd = FindWindowEx(hWnd, 0, "FloatNotifySink", "")
        Debug.Print "   FloatNotifySink "; Hex(hWnd)
    End If
                 
    If hWnd Then
    
        'Find the child ComboBox window
        
        hWnd = FindWindowEx(hWnd, 0, "ComboBox", "")
        Debug.Print "   ComboBox "; Hex(hWnd)
    End If
                        
    If hWnd Then
        
        SetForegroundWindow hWnd


        'Find the child Edit window
        
        hWnd = FindWindowEx(hWnd, 0, "Edit", "")
        Debug.Print "   Edit "; Hex(hWnd)
    End If
    
    If hWnd Then
            
        If filename = "" Then
    '        'Get default filename (already populated in Edit window)
            filename = Get_Window_Text(hWnd)
        End If
       
        'If specified, ensure folder ends with \
        If folder <> "" And Right(folder, 1) <> "\" Then folder = folder & "\"
        
        fullFilename = folder & filename
        Debug.Print "Full filename " & fullFilename
        
        'Populate the Edit window with the full file name
        
        Sleep 200
        SetForegroundWindow hWnd
        SendMessageByString hWnd, WM_SETTEXT, Len(fullFilename), fullFilename
    End If
    
End Sub
 
Upvote 0
I am using the above code which opens the link, but I get a prompt window to save the file. How do I use the above code to save the file?
 
Upvote 0
I just used the code below and it didn't work. It puts the new filename in the saveas window but when I clicked "save", it prompts to save as the original file name (default file name from IE) instead of the new file name that is shown in the window. Could someone please help?

Hi - posting this for future reference for Windows 7 users. Save as dialogue box hierarchy has changed therefore code above wasn't working when filename specified. With some additional levels the following appears to fix;

Code:
Private Sub Save_As_Set_Filename(folder As String, filename As String)

    'Populate the 'File name:' edit window in the Save As dialogue with the specified folder and/or filename.
    'If folder = "" a folder path is not prepended to the filename and therefore the default save folder is used.
    'If filename = "" the default file name (already populated) is used.
    
    'The Save As window has the following child window hierarchy:
    
    '   "Save As", #32770 Dialog
    '       "FileName", ComboBoxEx32        (FileName is the default File name value in combobox)
    '           "", ComboBox
    '               "FileName", Edit        (FileName is the default File name value in combobox's edit box)
    
    Dim hWnd As Long
    Dim timeout As Date
    Dim fullFilename As String
    
    Debug.Print "Save_As_Set_Filename"
    Debug.Print "folder   = " & folder
    Debug.Print "filename = " & filename
    
    'Find the Save As window, waiting a maximum of 10 seconds for it to appear
    
    timeout = Now + TimeValue("00:00:10")
    Do
        hWnd = FindWindow("#32770", "Save As")
        DoEvents
        Sleep 200
    Loop Until hWnd Or Now > timeout


    If hWnd Then
    
        SetForegroundWindow hWnd
        
        'Find the child DUIViewWndClassName window
        
       hWnd = FindWindowEx(hWnd, 0, "DUIViewWndClassName", vbNullString)
        Debug.Print "   DUIViewWndClassName "; Hex(hWnd)
    End If
    
    If hWnd Then
    
        'Find the child DirectUIHWND window
        
        hWnd = FindWindowEx(hWnd, 0, "DirectUIHWND", "")
        Debug.Print "   DirectUIHWND "; Hex(hWnd)
    End If
                 
    If hWnd Then
    
        'Find the child FloatNotifySink window
        
        hWnd = FindWindowEx(hWnd, 0, "FloatNotifySink", "")
        Debug.Print "   FloatNotifySink "; Hex(hWnd)
    End If
                 
    If hWnd Then
    
        'Find the child ComboBox window
        
        hWnd = FindWindowEx(hWnd, 0, "ComboBox", "")
        Debug.Print "   ComboBox "; Hex(hWnd)
    End If
                        
    If hWnd Then
        
        SetForegroundWindow hWnd


        'Find the child Edit window
        
        hWnd = FindWindowEx(hWnd, 0, "Edit", "")
        Debug.Print "   Edit "; Hex(hWnd)
    End If
    
    If hWnd Then
            
        If filename = "" Then
    '        'Get default filename (already populated in Edit window)
            filename = Get_Window_Text(hWnd)
        End If
       
        'If specified, ensure folder ends with \
        If folder <> "" And Right(folder, 1) <> "\" Then folder = folder & "\"
        
        fullFilename = folder & filename
        Debug.Print "Full filename " & fullFilename
        
        'Populate the Edit window with the full file name
        
        Sleep 200
        SetForegroundWindow hWnd
        SendMessageByString hWnd, WM_SETTEXT, Len(fullFilename), fullFilename
    End If
    
End Sub
 
Upvote 0
I just used the code below and it didn't work. It puts the new filename in the saveas window but when I clicked "save", it prompts to save as the original file name (default file name from IE) instead of the new file name that is shown in the window. Could someone please help?

Was anyone able to find this solution?

Thanks,

Excal
 
Upvote 0

Forum statistics

Threads
1,214,918
Messages
6,122,255
Members
449,075
Latest member
staticfluids

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