I am writing code to automatically download a spreadsheet from a website, by simulating a series of button clicks. (Has to be done this way, winHTTP methods won't work for other reasons).
The code clicks a download button, then clicks the save and open buttons on a frame notification bar. However, the issue I am having is that occasionally, the download button will get stuck for whatever reason, or will be incredibly slow. In this situation the code I am using to wait for the download is being ignored, and the code continues to run up to the point where it should click save in the frame notification bar, where it inevitably throws an error.
My question is, how can I handle the situation where the button becomes stuck after having been clicked? Perhaps a timeout error message if the download button is stuck? Though in my current code I am not sure how this would work, as it seems to ignore my checks of whether the download has been completed or not.
Sub StartIE()
Dim appIE As Object
Dim URLString As String
Dim HTMLdoc, btn As Object
Dim eBrowser As IUIAutomationElement
Set appIE = CreateObject("internetexplorer.application") ' create an instance of internet explorer
With appIE
.Navigate "https://analytics.twitter.com/user/QinetiQ/tweets" 'go to this url
.Visible = True ' and show the IE
End With
apiShowWindow appIE.hwnd, SW_SHOWMINIMIZED ' minimise IE (wouldn't work with IE hidden for some reason)
Do While appIE.Busy Or (appIE.READYSTATE <> 4) ' wait until IE has finished loading
DoEvents
Loop
URLString = appIE.LocationURL
'Application.Wait (Now + TimeValue("0:00:04")) ' wait a little bit longer as waiting for IE.Busy to finish doesn't seem to work 100%
If InStr(URLString, "login") Then
UseCredentials appIE 'inputs login details for the site
Do While appIE.Busy Or (appIE.READYSTATE <> 4) ' wait until IE has finished loading
DoEvents
Loop
End If
'Application.Wait (Now + TimeValue("0:00:04"))
Set HTMLdoc = appIE.document
Set btn = HTMLdoc.getElementsByClassName("btn btn-default ladda-button")(0) 'finds the export data button
btn.Click 'clicks the export button
Do While appIE.Busy Or (appIE.READYSTATE <> 4) ' wait until IE has finished loading
DoEvents
Loop
Application.Wait (Now + TimeValue("0:00:07"))
Dim hwnd As LongPtr, h As LongPtr
Dim o As IUIAutomation ' The following steps are used to download a csv file from a webpage
Dim e As IUIAutomationElement
Set o = New CUIAutomation
Do While h = 0 'loops untill the frame notification window is avaliable, though THIS DOESN'T WORK FOR SOME REASON
h = appIE.hwnd ' handle of the current window
Set eBrowser = o.ElementFromHandle(ByVal h)
DoEvents
h = FindWindowEx(h, 0, "Frame Notification Bar", vbNullString) ' replaces the handle of the window with the frame bar, using h in the function
Set eFNB = FindFromAllElementsWithClassName(eBrowser, "Frame Notification Bar", 10)
If eFNB Is Nothing Then
h = 0
End If
Loop
' we must find the first frame notification handle
If h = 0 Then Exit Sub
Set e = o.ElementFromHandle(ByVal h) ' it was important to set h as a LongPtr, and using Option Explicit at the top
Dim iCnd As IUIAutomationCondition
Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "Save") ' click the save button
Dim Button As IUIAutomationElement
Set Button = e.FindFirst(TreeScope_Subtree, iCnd) ' finds the button we need to click in the subtree on the notification bar
Dim InvokePattern As IUIAutomationInvokePattern
Set InvokePattern = Button.GetCurrentPattern(UIA_InvokePatternId) 'clicks the button
InvokePattern.Invoke
Application.Wait (Now + TimeValue("0:00:07"))
h = appIE.hwnd
h = FindWindowEx(h, 0, "Frame Notification Bar", vbNullString) ' repeating the above for the second stage of open/save on the notification bar
If h = 0 Then Exit Sub
Set e = o.ElementFromHandle(ByVal h)
Dim iCnd2 As IUIAutomationCondition
Set iCnd2 = o.CreatePropertyCondition(UIA_NamePropertyId, "Open") ' similar to the above snippet, except for the second stage of the frame notification window
Dim Button2 As IUIAutomationElement
Set Button2 = e.FindFirst(TreeScope_Subtree, iCnd2)
Dim InvokePattern2 As IUIAutomationInvokePattern
Set InvokePattern2 = Button2.GetCurrentPattern(UIA_InvokePatternId)
InvokePattern2.Invoke
Application.Wait (Now + TimeValue("0:00:03"))
End Sub
I've included all code from the sub because I feel it gives good context as to the steps I am taking. The snippet from this which doesn't seem to work is:
Do While h = 0 'loops untill the frame notification window is avaliable, though THIS DOESN'T WORK FOR SOME REASON
h = appIE.hwnd ' handle of the current window
Set eBrowser = o.ElementFromHandle(ByVal h)
DoEvents
h = FindWindowEx(h, 0, "Frame Notification Bar", vbNullString) ' replaces the handle of the window with the frame bar, using h in the function
Set eFNB = FindFromAllElementsWithClassName(eBrowser, "Frame Notification Bar", 10)
If eFNB Is Nothing Then
h = 0
End If
Loop
Thankyou, hope this is clear.
Christian.