Events IE11 on change

13,466

The best way to select an option in a dropdown is to use the selectedIndex property or to set selected = True for one of the <option> elements. After that, you can fire the onchange event yourself. Since your page uses AJAX to initialize further lists based on your selection, you'll have to wait for it to complete before continuing.

I got bored and decided to build my own car. I just wrapped the functionality needed to select an option from the dropdown and fire the onchange event into a SelectOption() function. There are probably more sophisticated ways to wait until the event completes (like checking ie.busy or ie.readystate) but I'm just sleeping for a few seconds after I set each option.

Set d = ie.document

SelectOption d, "vehicleYearOfManufactureList", "2012"
SelectOption d, "vehicleMakeList", "Toyota"
SelectOption d, "vehicleModelList", "Camry"
SelectOption d, "vehicleTransmissionList", "Auto"
SelectOption d, "vehicleNumberOfCylindersList", "4"
SelectOption d, "vehicleBodyTypeList", "4D Sedan"

' If you want to click the button when you're done...
d.getElementById("findcar").Click

MsgBox "Completed selections"

Function SelectOption(doc, strID, strText)

    Dim e
    Set e = doc.getElementById(strID)

    If e Is Nothing Then
        MsgBox "Could not find ID = " & strText
        Exit Function
    End If

    ' Select the option that matches our text...
    Dim o
    For Each o In e.Options
        If StrComp(o.Text, strText, vbTextCompare) = 0 Then
            o.Selected = True
            Exit For
        End If
    Next

    If e.SelectedIndex = 0 Then
        MsgBox "Could not set value of " & strID & " to " & strText
        Exit Function
    End If

    ' Fire the onChange event...
    Dim objEvent
    Set objEvent = doc.createEvent("HTMLEvents")
    objEvent.initEvent "change", False, True
    e.dispatchEvent objEvent

    ' Wait a few seconds for the event to complete...
    WScript.Sleep 3000

    SelectOption = True

End Function

I did this in the Windows Script Host, so I had the luxury of using WScript.Sleep(). You'll just need to replace those calls with Application.Wait() for VBA.

Share:
13,466
chris
Author by

chris

Updated on June 04, 2022

Comments

  • chris
    chris almost 2 years

    My code launches an IE 11 page, clicks on a link and then attempts to fill in two dropdown lists. The first one is filled in successfully with the value "2012". But the second doesn't get filled in with the value "TOYOTA".

    Despite the fact that the second dropdown list no longer shows the command "select", it just doesn't show "TOYOTA". In other words, it goes from the command "select" to a blank. Whereas the first dropdown correctly goes from the command "select" to "2012".

    I thought it was probably to do with the fact that second dropdown will show values which are dependent on the first dropdown's actual selection. And that some onchange or fireevent command is required.

    I've been searching a lot online and I've found similar problems which I've tried to sponge off of. In general there have been two main variations of code I've tried. As always I would be thoroughly grateful if someone could possibly run this code and/ or advise me. The first is like this:

    Sub GetQuote()
    
    Dim IE As Object
    
    Set IE = CreateObject("InternetExplorer.Application")
    
    IE.navigate ("website")
    
    IE.Visible = True
    
    Do
    DoEvents
    Loop Until IE.readystate = 4
    
    Dim e
    Set e = IE.document.getElementsByClassname("id name of button")(1)
    e.Click
    
    Application.Wait (Now + TimeValue("00:00:02"))
    
    Do
    DoEvents
    Loop Until IE.readystate = 4
    
    
    Dim z As Object
    Set z = IE.document.getElementbyid("vehicleYearOfManufactureList")
    z.Focus
    z.SelectedIndex = 4
    z.FireEvent ("onchange")
    
    Application.Wait (Now + TimeValue("00:00:02"))
    
    Dim y As Object
    Set y = IE.document.getElementbyid("vehicleMakeList")
    y.Focus
    y.Value = "TOYOTA"
    y.FireEvent ("onchange")
    
    
    End Sub
    

    And the second is like this:

    Sub GetQuote()
    
    Dim IE As Object
    
    Set IE = CreateObject("InternetExplorer.Application")
    
    IE.navigate ("website")
    
    IE.Visible = True
    
    Do
    DoEvents
    Loop Until IE.readystate = 4
    
    Dim e
    Set e = IE.document.getElementsByClassname("sg-Btn sg-Btn--primary")(1)
    e.Click
    
    Application.Wait (Now + TimeValue("00:00:02"))
    
    Do
    DoEvents
    Loop Until IE.readystate = 4
    
    
    Dim z As Object
    
    Set evt = IE.document.createEvent("HTMLEvents")
    
    evt.initEvent "change", True, False
    
    Set z = IE.document.getElementbyid("vehicleYearOfManufactureList")
    
    z.SelectedIndex = 4
    z.dispatchEvent evt
    
    Application.Wait (Now + TimeValue("00:00:02"))
    
    Dim y As Object
    
    Set evt = IE.document.createEvent("HTMLEvents")
    
    evt.initEvent "change", True, False
    
    Set y = IE.document.getElementbyid("vehicleMakeList")
    
    y.Value = "TOYOTA"
    y.dispatchEvent evt
    
    End Sub
    

    And here is the source code for the second dropdown list which I want to fill in with "TOYOTA" (one thing I noticed when I hovered over the second dropdown list was that instead of having the usual arrow for my cursor it now displays a hand with a small black circle that has a strike through it, which seems in line with the fact that the second dropdown list seems to not be able to be selected):

                       <option value="">Select</option><optgroup label="Common Makes" id="commonVehicleMakeOptionGroup"><option value="AUDI">Audi</option><option value="BMW">BMW</option><option value="FORD">Ford</option><option value="HOLDEN">Holden</option><option value="HONDA">Honda</option><option value="HYUNDAI">Hyundai</option><option value="KIA">Kia</option><option value="MAZDA">Mazda</option><option value="MERCEDES-BENZ">Mercedes-Benz</option><option value="MITSUBISHI">Mitsubishi</option><option value="NISSAN">Nissan</option><option value="SUBARU">Subaru</option><option value="TOYOTA">Toyota</option><option value="VOLKSWAGEN">Volkswagen</option><option disabled="disabled"></option></optgroup><optgroup label="All Makes" id="allVehicleMakeOptionGroup"><option value="ABARTH">Abarth</option><option value="ALFA ROMEO">Alfa Romeo</option><option value="ASTON MARTIN">Aston Martin</option><option value="AUDI">Audi</option><option value="BENTLEY">Bentley</option><option value="BMW">BMW</option><option value="CHERY">Chery</option><option value="CHRYSLER">Chrysler</option><option value="CITROEN">Citroen</option><option value="DODGE">Dodge</option><option value="FIAT">Fiat</option><option value="FORD">Ford</option><option value="FOTON">Foton</option><option value="GEELY">Geely</option><option value="GREAT WALL MOTORS">Great Wall Motors</option><option value="HOLDEN">Holden</option><option value="HONDA">Honda</option><option value="HSV">HSV</option><option value="HYUNDAI">Hyundai</option><option value="INFINITI">Infiniti</option><option value="ISUZU">Isuzu</option><option value="IVECO">Iveco</option><option value="JAGUAR">Jaguar</option><option value="JEEP">Jeep</option><option value="KIA">Kia</option><option value="LAND ROVER">Land Rover</option><option value="LEXUS">Lexus</option><option value="LOTUS">Lotus</option><option value="MAHINDRA">Mahindra</option><option value="MAZDA">Mazda</option><option value="MERCEDES-BENZ">Mercedes-Benz</option><option value="MINI">Mini</option><option value="MITSUBISHI">Mitsubishi</option><option value="NISSAN">Nissan</option><option value="OPEL">Opel</option><option value="PEUGEOT">Peugeot</option><option value="PORSCHE">Porsche</option><option value="PROTON">Proton</option><option value="RANGE ROVER">Range Rover</option><option value="RENAULT">Renault</option><option value="SAAB">Saab</option><option value="SKODA">Skoda</option><option value="SMART">Smart</option><option value="SSANGYONG">Ssangyong</option><option value="SUBARU">Subaru</option><option value="SUZUKI">Suzuki</option><option value="TATA">Tata</option><option value="TOYOTA">Toyota</option><option value="VOLKSWAGEN">Volkswagen</option><option value="VOLVO">Volvo</option></optgroup></select>
    
  • chris
    chris over 8 years
    Bond, thank you very much for persisting with me! I really appreciate it. I wish I knew even 1% of what I imagine you know. If I could just take a step back though (before I start trying to understand and paste in your new code), I've run into another problem which I thought was 'history'- I've edited my previous question as a result
  • chris
    chris over 8 years
    Bond, I just want to say thanks very much again for this code! It's taken me a couple hours to understand the different parts of the function and read up on StrComp(), createEvent() and initEvent() and I finally see why and how this basically works and links to the other code outside of the function. I was wondering though, what does the last line of the function do or why is it necessary (i.e. SelectOption = True). And one other thing I'm still trying to understand is the arguments of initEvent () - specifically how "change" is linked to any other bit of the code and why false, true
  • chris
    chris over 8 years
    I can't believe how awesome this is though, despite any difficulties you might face to compile the code for it!
  • Bond
    Bond over 8 years
    I'm just returning SelectOption = True to indicate success. I'm not using the return value above but you could write: If Not SelectOption(d, "someControl", "someText") Then ... to perform some operation of the function call failed, for example. By default, all variant/boolean functions will return a "falsy" value if you don't explicitly set them to True. So when I check for errors earlier on and then do an Exit Function, it's actually returning a "falsy" value (one that would fail an If test).
  • Bond
    Bond over 8 years
    As for initEvent, it takes 3 params. The second indicates whether the event (in this case, the "change" event) should notify its parent and its parent, etc, all the way up the event chain. That's not necessary. We just need it to fire for our dropdown. And don't worry about the 3rd param. It doesn't play a factor here. To fire an event, you need to create a standalone event, which we do with the doc.createEvent() function. Then define it. Then tell a control (in this case e, our dropdown) to fire it: e.dispatchEvent().
  • chris
    chris over 8 years
    If I wanted to change the hardcoded value of "2012" to rather reference an Excel spreadsheet cell (A1, say) that has the value 2012, how would I modify the line: SelectOption d, "vehicleYearOfManufactureList", "2012"? Now that a single quote can be automated, what I would really like to do is loop through a bunch of profiles that I want to randomise on a spreadsheet.
  • chris
    chris over 8 years
    It's easy enough for some of the other fields which are not dependent dropdowns. For example, for the address field I just "33 Bull Street" to Range("A1").Value, where cell A1 contained "33 Bull Street". I'm just not sure how to do that where there's a linking function that has text strings in its arguments
  • Bond
    Bond over 8 years
    Should be the same. SelectOption is expecting a text string. So you should be able to do something like: SelectOption d, "someID", Range("A1").Value, assuming A1 contains some text.
  • chris
    chris over 8 years
    Ah, wow, how cool! I see why it didn't work the first time round. I had my value of 2012 stored as a number and not as text! And I've got the bot to loop and, within each loop, hit the back button several times to create variation on each case! :) Bond, I can't thank you enough for your help! I couldn't have done it without you and your patience. I'm getting addicted to this stuff now
  • chris
    chris over 8 years
    Mostly the vehicles I've built are accepted. But sometimes one causes the programme to crash. For example, 2003, Ford, F250, M, DT6, C/chas (the values of the elements for this vehicle). I've checked these against the source code to make sure they are available values for this vehicles and the spelling is correct with no spaces etc. I've also manually checked that I can input these and complete a quote. I've also increased the delay in the fire-event function and then changed the values of the elements to slightly different combinations but to no avail. Any idea why this is happening?
  • Bond
    Bond over 8 years
    @chris - Probably best to accept the answer to this question and then open a new one with your new issue. Paste your updated code into your new question and describe your specific issue (as you did in your comment above). You'll get more answers and it'll keep things cleaner for future users struggling with the same issues you are. Thanks.
  • John Muggins
    John Muggins about 5 years
    Totally awesome! Thank you so very much. Late to the game but I just spent two days looking for a way to change a select option and a user event to refresh the element. This works like a charm! Changing the <option> by value was easy. But i tried everything under the sun to get the select element to accept the change. When I plugged in your code it was like I heard angels singing! Thank you, thank, thank you