VBA IE Automation issue with Angularjs input text

JDLd500

New Member
Joined
Jul 30, 2019
Messages
4
Hi

I am automating the inputting of text and date/time fields using VBA and IE. The site concerned has AngularJS java scripts running behind the HTML.

I have triggered events to handle the date and time picker by clicking on buttons navigating the calendar if the month/year does not match what I want etc. and the updates work great.

However I have an issue with simple plain text fields on the page. I can:-
  • use the getelementbyid("text0").value = "xxxx" and .innertext = "xxxxx" to populate the input field on the web page (so I can see what I expect to see)
  • use the.classname = "xxx" to change the class (using DOM I can see that when I work manually on the page the class name changes to indicate that the field is "dirty" which the java must use to tell that a field has changed)
  • click the save button automatically

But I cannot get the necessary scripts to run so that the variable data that I have added is recognised and is actually saved (when I recall the record the text data is as it was).

The following is the HTML code:

HTML:
<input type="text" ng-model="feedbackItem.textValue" id="text0" ng-disabled="!feedbackIsEditable || feedbackItem.notApplicable" maxlength="255" class="ng-valid ng-valid-maxlength ng-dirty ng-valid-parse ng-touched" name="" tabindex="0" aria-disabled="false" aria-invalid="false" style="">

There are the following events associated with the field - blur, change, compositionend, compositionstart, input

I have tried to use fireevent to trigger "blur" "change" and "input" but get an error message in debug saying object required.

the code I am using is as follows (I have kept the commented out lines so that you can see the variations I have tried and have failed:

IE.document.getElementById("text0").Focus = True
IE.document.getElementById("text0").Click
strSub = Left("text to enter", Len("text to enter") - 1)
strKey = Right("text to enter", 1)


IE.document.getElementById("text0").Value = strSub
Application.SendKeys strKey
'IE.document.getElementById("text0").className = "ng-valid ng-valid-maxlength ng-dirty ng-valid-parse ng-touched"
'IE.document.getElementById("text0").Value = "text to enter"
'IE.document.getElementById("text0").innerText = "text to enter"
'IE.document.getElementById("text0").className = "ng-valid ng-valid-maxlength ng-dirty ng-valid-parse ng-touched"
'IE.document.getElementById("text0").feedbackItem.textValue = "text to enter"
IE.document.getElementById("text0").className = "ng-valid ng-valid-maxlength ng-dirty ng-valid-parse ng-touched"
'Elements.FireEvent ("change")

IE.document.getElementById("text0").Focus = False
IE.document.getElementById("date1").Focus = True 'this is the next field to populate


I am assuming that I need to either trigger the JS event(s) and/or somehow change the value of "feedbackItem.textValue"?

Anyone see the obvious mistake I'm making or step(s) I've missed?

Thanks in advance
John
 

Excel Facts

How can you automate Excel?
Press Alt+F11 from Windows Excel to open the Visual Basic for Applications (VBA) editor.
What is the URL? It's very difficult to help without knowing that.

You could try dispatchEvent on the text input element instead of FireEvent. The example code below requires a reference to the MS HTML Object Library (set via Tools->References in the VBA editor). It populates the text input element character by character, sending a keydown event and input event for each character and a change event at the end. You might need to send a different event or events (e.g. keypress, mousedown, etc.) - I have shown how to define these events.

Also make sure the events are created (by the createEvent lines) after the page (HTMLdoc) is completely loaded, otherwise the dispatchEvent calls might not have any effect. Also, you might need to trigger other event(s) - within the For Next loop, or maybe before or after it - which are assigned to parent elements of the text input element. Use the browser's DOM inspector to go up the DOM hierarchy to each parent element, looking to see if any events are assigned to that element, until you reach the body element. You might find that a keypress, keydown, etc. event is assigned to one these elements - hence why I have included a dispatchEvent keydown in the For Next loop below.

Code:
Public Sub DispatchEvent_Code_Example()

    Dim IE As InternetExplorer
    Dim HTMLdoc As HTMLDocument
    Dim textInput As HTMLInputElement
    
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
        Dim keyupEvent As DOMKeyboardEvent
        Dim keydownEvent As DOMKeyboardEvent
        Dim inputEvent As DOMEvent
        Dim changeEvent As DOMEvent
        Dim clickEvent As DOMMouseEvent
        Dim mouseMoveEvent As DOMMouseEvent
        Dim mouseDownEvent As DOMMouseEvent
        Dim mouseUpEvent As DOMMouseEvent
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL] 
        Dim keyupEvent As Object
        Dim keydownEvent As Object
        Dim inputEvent As Object
        Dim changeEvent As Object
        Dim clickEvent As Object
        Dim mouseMoveEvent As Object
        Dim mouseDownEvent As Object
        Dim mouseUpEvent As Object
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If
    
    Dim inputString As String
    Dim i As Long
    
    'After IE navigation and page has completely loaded
    
    Set HTMLdoc = IE.document

    With HTMLdoc
        Set keyupEvent = .createEvent("KeyboardEvent")
        Set keydownEvent = .createEvent("KeyboardEvent")
        Set inputEvent = .createEvent("HTMLEvents")
        Set changeEvent = .createEvent("HTMLEvents")
        Set clickEvent = .createEvent("HTMLEvents")
        Set mouseMoveEvent = .createEvent("MouseEvents")
        Set mouseDownEvent = .createEvent("MouseEvents")
        Set mouseUpEvent = .createEvent("MouseEvents")
    End With
        
    keyupEvent.initEvent "keyup", True, False
    keydownEvent.initEvent "keydown", True, False
    inputEvent.initEvent "input", True, False
    changeEvent.initEvent "change", True, False
    clickEvent.initEvent "click", True, False
    mouseMoveEvent.initEvent "mousemove", True, False
    mouseDownEvent.initEvent "mousedown", True, False
    mouseUpEvent.initEvent "mouseup", True, False
    
    inputString = "My text input string"
    Set textInput = HTMLdoc.getElementById("text0")
    textInput.Focus
    textInput.Value = ""
    For i = 1 To Len(inputString)
        textInput.Value = textInput.Value & Mid(inputString, i, 1)
        textInput.dispatchEvent keydownEvent
        DoEvents
        textInput.dispatchEvent inputEvent
        DoEvents
    Next
    textInput.dispatchEvent changeEvent

End Sub
 
Last edited:
Upvote 0
Hi John W

Thanks for your detailed reply which I will try out - much appreciated!

Unfortunately I cannot disclose the URL due to NDA considerations with the end client.

I did find a solution to the problem using sendkeys

IE.document.getElementById("text0").Focus = True
IE.document.getElementById("text0").Select 'This selects any data already present allowing sendkeys to overwrite it


sFieldInput = "text to be input into the field" For s = 1 To Len(sFieldInput)
Application.SendKeys Mid(sFieldInput, s, 1)
While IE.READYSTATE < 4 Or IE.Busy
Application.Wait DateAdd("s", LoopSeconds, Now)
Wend
Next s

IE.document.getElementById("text0").Focus = False 'De-focus the field and cause change event to trigger
IE.document.getElementById("date1").Focus = True 'Next field to populate

This pumps single characters into the field and trigger the necessary events when focusing and de-focusing the field. When the "Save" button is clicked the data is saved.

FYI - The issue I came across with this solution was that I had to allow a delay after each sendkey to allow the JS time to do its thing. If I did not then the field got partially completed. Hence the application.wait statement

Thanks again John
 
Upvote 0
Hi Vrsharma

A further refinement to speed up the use of Sendkeys is as follows. This pushes all but the last character into the field, positions the cursor at the end of the field then adds the last character using Sendkeys to trigger the event. Hope this helps.

Code:
                sFieldInput = "The text to be input here"
                IE.document.getElementById("text0").Value = Left(sFieldInput, Len(sFieldInput) - 1)
                DoEvents
                Application.SendKeys "{END}", 1  
                Application.SendKeys Right(sFieldInput, 1), 1   '",1 waits for the processing to complete (saves using DoEvents)
 
Upvote 0
What is the URL? It's very difficult to help without knowing that.

You could try dispatchEvent on the text input element instead of FireEvent. The example code below requires a reference to the MS HTML Object Library (set via Tools->References in the VBA editor). It populates the text input element character by character, sending a keydown event and input event for each character and a change event at the end. You might need to send a different event or events (e.g. keypress, mousedown, etc.) - I have shown how to define these events.

Also make sure the events are created (by the createEvent lines) after the page (HTMLdoc) is completely loaded, otherwise the dispatchEvent calls might not have any effect. Also, you might need to trigger other event(s) - within the For Next loop, or maybe before or after it - which are assigned to parent elements of the text input element. Use the browser's DOM inspector to go up the DOM hierarchy to each parent element, looking to see if any events are assigned to that element, until you reach the body element. You might find that a keypress, keydown, etc. event is assigned to one these elements - hence why I have included a dispatchEvent keydown in the For Next loop below.

Code:
Public Sub DispatchEvent_Code_Example()

    Dim IE As InternetExplorer
    Dim HTMLdoc As HTMLDocument
    Dim textInput As HTMLInputElement
   
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If"]#If[/URL]  VBA7 Then
        Dim keyupEvent As DOMKeyboardEvent
        Dim keydownEvent As DOMKeyboardEvent
        Dim inputEvent As DOMEvent
        Dim changeEvent As DOMEvent
        Dim clickEvent As DOMMouseEvent
        Dim mouseMoveEvent As DOMMouseEvent
        Dim mouseDownEvent As DOMMouseEvent
        Dim mouseUpEvent As DOMMouseEvent
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else"]#Else[/URL]
        Dim keyupEvent As Object
        Dim keydownEvent As Object
        Dim inputEvent As Object
        Dim changeEvent As Object
        Dim clickEvent As Object
        Dim mouseMoveEvent As Object
        Dim mouseDownEvent As Object
        Dim mouseUpEvent As Object
    [URL="https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End"]#End[/URL]  If
   
    Dim inputString As String
    Dim i As Long
   
    'After IE navigation and page has completely loaded
   
    Set HTMLdoc = IE.document

    With HTMLdoc
        Set keyupEvent = .createEvent("KeyboardEvent")
        Set keydownEvent = .createEvent("KeyboardEvent")
        Set inputEvent = .createEvent("HTMLEvents")
        Set changeEvent = .createEvent("HTMLEvents")
        Set clickEvent = .createEvent("HTMLEvents")
        Set mouseMoveEvent = .createEvent("MouseEvents")
        Set mouseDownEvent = .createEvent("MouseEvents")
        Set mouseUpEvent = .createEvent("MouseEvents")
    End With
       
    keyupEvent.initEvent "keyup", True, False
    keydownEvent.initEvent "keydown", True, False
    inputEvent.initEvent "input", True, False
    changeEvent.initEvent "change", True, False
    clickEvent.initEvent "click", True, False
    mouseMoveEvent.initEvent "mousemove", True, False
    mouseDownEvent.initEvent "mousedown", True, False
    mouseUpEvent.initEvent "mouseup", True, False
   
    inputString = "My text input string"
    Set textInput = HTMLdoc.getElementById("text0")
    textInput.Focus
    textInput.Value = ""
    For i = 1 To Len(inputString)
        textInput.Value = textInput.Value & Mid(inputString, i, 1)
        textInput.dispatchEvent keydownEvent
        DoEvents
        textInput.dispatchEvent inputEvent
        DoEvents
    Next
    textInput.dispatchEvent changeEvent

End Sub


Thank you for the code.
However, it does not work for my case.
I have a HTML form with multiple tabs, and when I use your code or any other methods I've found so far, I can successfully enter the values into the input box.
But when I click on a different tab and come back (or save the form), the input values are gone and it's replaced with the default values.
Do you know what might be the problem?
 
Upvote 0
Difficult to help without seeing the web page. Maybe you aren't sending the correct events. Use the DOM inspector to see the event(s) on the elements in question and their parent elements. Maybe try fireEvent instead of dispatchEvent - there are examples on the forum.
 
  • Like
Reactions: kyu
Upvote 0
Difficult to help without seeing the web page. Maybe you aren't sending the correct events. Use the DOM inspector to see the event(s) on the elements in question and their parent elements. Maybe try fireEvent instead of dispatchEvent - there are examples on the forum.

What I do is:
F12 on Internet explorer -> which opens up a DOM Explorer.
If I do select element (Ctrl B) and click on the input box I wish to use, it shows the HTML code(?). For example, one of the codes I'm having trouble with is the following:
<input name="ucclientPage$panelFirstInsured$ucInsured$txtFirstName" class="SectionValidationControl" id="ucclientPage_panelFirstInsured_ucInsured_txtFirstName" style="width: 200px; color: black;" type="text" maxlength="35" value="Valued">
If I follow your code, on the website (form) the input value is changed appropriately, but it seems like in the code, the value variable is not changed and stays as "Valued". Therefore when I save, the default value "Valued" is saved.

I have tried one version of fireEvent but will look into it on this forum.
Thank you
 
Upvote 0

Forum statistics

Threads
1,223,908
Messages
6,175,304
Members
452,633
Latest member
DougMo

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