How to select multiple items in a list box on website with VBA?

Viewed 105

I log into a website and I'm attempting to select all items in a list.

The login works, but the items are not being highlighted or selected prior to submitting.

Sub BrowseToSite() 'Login to site

    'set ie = internetexplorer for reference
    Dim ie As New SHDocVw.InternetExplorer
    Dim htmldoc As MSHTML.HTMLDocument
    Dim htmlinput As MSHTML.IHTMLElement
    Dim htmlbuttons As MSHTML.IHTMLElementCollection
    Dim objIE As Object
      
    'see window and navigate to website (HOURLY VOLUME ENERGY COMPOSITION - HVEC)
    ie.Visible = True
    ie.navigate "www.website.com"
        
    'wait for brower to load
    Do While ie.readyState <> READYSTATE_COMPLETE
    Loop
        
    'Enters username and password
    Set htmldoc = ie.document
    Set htmlinput = htmldoc.getElementById("USER")
    htmlinput.Value = "LoginUsername"
    Set htmlinput = htmldoc.getElementById("PASSWORD")
    htmlinput.Value = "Password1"
    
    'finds form > submit button (under class = "LoginSubmit")
    htmldoc.forms(0).submit
    
    'select all Locations
    ie.document.getElementsByName("ctl00$contentPlaceHolder$ctl00$availableLocations").Value = "1297"
    ie.document.getElementsByName("ctl00$contentPlaceHolder$ctl00$availableLocations").Value = "3216"
    ie.document.getElementsByName("ctl00$contentPlaceHolder$ctl00$availableLocations").Value = "3135"
    objIE.document.getElementsByName("ctl00$contentPlaceHolder$ctl00$availableLocations")(0).Click

End Sub

Here is the HTML Code:

<tr>
    <td class="fieldLabel">Location:</td>
    <td class="fieldData" colspan="3">
        
        
        <select size="12" name="ctl00$contentPlaceHolder$ctl00$availableLocations" multiple="multiple" id="contentPlaceHolder_ctl00_availableLocations" tabindex="8" class="fullWidth" onFocus="resetList(&#39;operatorList&#39;);">
<option value="1297">1297 - Test1</option>
<option value="3216">3216 - Test2</option>
<option value="3135">3135 - Test3</option>
1 Answers

Current code:

By attempting to set the value of a collection (which is what getElementsByName returns) you should be getting an error telling you that .value is not available. It is a property of nodes within your collection and would require indexing into your collection. As you don't mention an error I have to wonder if in your actual code you are masking errors with an On Error Resume Next?

@TimWilliams makes an important point in the comment about leaving enough time for the webpage to update after actions like .Submit, .Click, .Refresh.

Also, use a proper page load wait of:

While ie.Busy Or ie.ReadyState<>4:DoEvents:Wend

You could update the loop syntax (I'm old!)


What you can try:

Assuming the parent select is multi-select enabled then I would gather a nodeList of all the options using querySelectorAll and loop that list setting .Selected = True on each node.

You can gather the nodeList by using the id of the parent select with child combinator and the type selector option for the children within

Dim nodes As Object, i As Long

Set nodes = htmlDoc.querySelectorAll("#contentPlaceHolder_ctl00_availableLocations > option")

For i  = 0 To nodes.Length - 1
    nodes.item(i).Selected = True
Next

This will allow you to select without having to specify each node by either its index in the select options list, or by using the value attribute value etc. E.g. Setting individually using value attribute would look like:

htmlDoc.querySelector("[value='1297']").Selected =True

etc...


Read about css selectors used by querySelectorAll here:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors

Related