html – How to click on the save button when pop-up appears?-ThrowExceptions

Exception or error:

I am using Internet Explorer to click on a file.

I get to a point where an Internet Explorer pop-up appears saying “Do you want to open or save the file?”:
enter image description here

I want to write a VBA code that clicks on the save button.

I realized it is not possible to right click and “inspect element” in order to show the HTML page because the pop-up is not part of the internet explorer webpage.

So I tried the sendKeys method even though it is not reliable. I tried different options such as :

Application.SendKeys "%S"
Application.SendKeys "%s"
Application.SendKeys "%{S}"
Application.SendKeys "%{s}"
SendKeys ("%S")
SendKeys ("%s")
SendKeys ("%{S}")
SendKeys ("%{s}")

Application.SendKeys "%{S}"

When I run the code, none of them save the file.

Where is my error?

Are there other propositions to click on that “Save” button?

Maybe the object to which I am applying SendKeys should not be “Application”?

How to solve:

If you wish to use the UIAutomationCore.dll and reference it, you can do something like:

Public Function AutoSave() As Boolean
On Error Goto handler
    Dim sysAuto As New UIAutomationClient.CUIAutomation
    Dim ieWindow As UIAutomationClient.IUIAutomationElement
    Dim cond As IUIAutomationCondition
    Set cond = sysAuto.CreateAndCondition(sysAuto.CreatePropertyCondition(UIA_NamePropertyId, "Notification"), _
                                      sysAuto.CreatePropertyCondition(UIA_PropertyIds.UIA_ControlTypePropertyId, UIA_ToolBarControlTypeId))
    Set ieWindow = sysAuto.GetRootElement.FindFirst(TreeScope_Descendants, cond)

    Dim tField As UIAutomationClient.IUIAutomationElement
    Dim tFieldCond As IUIAutomationCondition
    Set tFieldCond = sysAuto.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_SplitButtonControlTypeId)
    Set tField = ieWindow.FindFirst(TreeScope_Descendants, tFieldCond)

    Dim invPattern As UIAutomationClient.IUIAutomationInvokePattern
    Set invPattern = tField.GetCurrentPattern(UIA_InvokePatternId)
    invPattern.Invoke  
    AutoSave = True 

Exit Function
handler:

End Function

And call that routine after clicking on the item – perhaps give it a Hard Wait to allow the Notification bar to show.

EDIT

To invoke the Close Button:

Set cond = sysAuto.CreateAndCondition(sysAuto.CreatePropertyCondition(UIA_NamePropertyId, "Close"), _
                                      sysAuto.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_ButtonControlTypeId))
Dim closeButton As IUIAutomationElement
Set closeButton = WaitForElement(ieWindow, cond, 10)
If closeButton Is Nothing Then Exit Sub

Dim clickButtonPattern As IUIAutomationInvokePattern
Set clickButtonPattern = closeButton.GetCurrentPattern(UIA_InvokePatternId)
clickButtonPattern.Invoke
........

Helper function:

Function WaitForElement(rootElement As IUIAutomationElement, condition As IUIAutomationCondition, timeout As Long) As IUIAutomationElement
    Dim startTime As Date
    startTime = Now

    Dim element As IUIAutomationElement
    Set element = rootElement.FindFirst(TreeScope_Descendants, condition)
    While element Is Nothing And 100000 * (Now - startTime) < timeout
        Application.Wait Now + TimeValue("00:00:01")
        Set element = rootElement.FindFirst(TreeScope_Descendants, condition)
    Wend

    Set WaitForElement = element
End Function

You would typically wait until the ‘Notification bar Text’ element text had changed to have “download has completed” at the end.

This can be done with a couple of helper functions:

Function WaitForTextValue(textElement As IUIAutomationElement, text As String, timeout As Long, Optional exactMatch As Boolean = False) As Boolean
Dim startTime As Date
startTime = Now

Dim result As String
result = ReadValue(textElement)
Dim isMatch As Boolean
If exactMatch Then
    isMatch = result = text
Else
    isMatch = InStr(1, result, text, vbTextCompare) > 0
End If

'keep reading the element until we have a match, or the timeout has expired
While Not isMatch And 100000 * (Now - startTime) < timeout
    Application.Wait Now + TimeValue("00:00:01")
    result = ReadValue(textElement)
    If exactMatch Then
        isMatch = result = text
    Else
        isMatch = InStr(1, result, text, vbTextCompare) > 0
    End If
Wend

WaitForTextValue = isMatch
End Function

Function ReadValue(element As IUIAutomationElement) As String
Dim valPattern As IUIAutomationValuePattern
Set valPattern = element.GetCurrentPattern(UIA_ValuePatternId)

If Not valPattern Is Nothing Then
    ReadValue = element.GetCurrentPropertyValue(UIA_ValueValuePropertyId)
Else
    ' raise error here if element's value cannot be read - err.Raise
End If

End Function

And you would call this check after clicking the ‘Save’ button like so:

Set cond = sysAuto.CreateAndCondition(sysAuto.CreatePropertyCondition(UIA_NamePropertyId, "Notification bar Text"), _
                                      sysAuto.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_TextControlTypeId))
Dim barText As IUIAutomationElement
Set barText = WaitForElement(ieWindow, cond, 10)
If barText Is Nothing Then Exit Sub

If Not WaitForTextValue(barText, "download has completed", 30, False) Then Exit Sub
'if we get to here, then text has changed, and we can go ahead and click close button

###

Reproduce your problem on my side, it seems that before clicking the Save button, we need time to display the popup file download prompt. So, please try to use the Application.Wait method to wait the prompt display.

Code like this:

Sub Test()
    Dim ie As Object
    Dim Rank As Object
    Set ie = CreateObject("InternetExplorer.application")
    ie.Visible = True
    ie.Navigate ("http://localhost:54382/HtmlPage47.html")
    Do
        If ie.ReadyState = 4 Then
            Exit Do
        Else
        End If
    Loop

    Set doc = ie.document

    doc.getElementsByTagName("tr")(1).getElementsByTagName("td")(5).getElementsByTagName("a")(0).Click

    Application.Wait (Now + TimeValue("0:00:02"))
    Application.SendKeys "%{S}"

End Sub

The screenshot as below:

enter image description here

Leave a Reply

Your email address will not be published. Required fields are marked *