简体   繁体   中英

Why isn't "get Elements By Name" working?

I'm pretty new to programming. Can someone help me with this? It always crashes at the getElementsByName line, can't work out why..

Option Explicit
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr) 'For 64 Bit Systems


Sub getVerb()
    Dim IE As Object ', objShellWindows As Object
    Dim verb As String, strWebPath As String

    strWebPath = "http://www.conjugation.org/"

    verb = "querer"

    'Navigate to page
    '----------------
    Set IE = CreateObject("InternetExplorer.Application")
    With IE
        .Visible = True
        .Navigate strWebPath
    End With

    'Wait for page
    Do While IE.Busy
        Sleep 250
        DoEvents
    Loop

    'Fill out
    '---------
    'Enter verb
    '<input type="text" size="25" name="word">
    IE.document.getElementsByName("word")(0).Value = verb

    'Set to List
    '<input type="radio" name="rb1" value="list">
    IE.document.getElementsByName("rb1")(0).Value = "list"

    'Press Button Conjugate
    '<input type="submit" name="B1" value="Conjugate">
    IE.document.getElementByName("B1").Click

    'TODO: extract info

    'Exit IE
    '--------
    IE.Quit
    Set IE = Nothing

End Sub

This is an optimized script that makes use of proper page load wait and then css selectors. CSS selectors are a faster, more flexible, way of matching on elements. I think it makes for nice clean reading as well.

The [x=y] eg [value=list] are attribute = value selectors . The input is atype selector . These selectors are applied via querySelector method of HTMLDocument object and return the first match in the DOM for the specified css selector.

Option Explicit

'VBE > Tools > References:
' Microsoft Internet Controls
Public Sub EnterInfo()
    Dim ie As New InternetExplorer
    Const VERB As String = "querer"

    With ie
        .Visible = True
        .Navigate2 "http://www.conjugation.org/"

        While .Busy Or .readyState < 4: DoEvents: Wend

        With .document
            .querySelector("input").Value = VERB 'first input tag element
            .querySelector("[value=list]").Click '<  first element with value attribute having value of list
            .querySelector("[value=Conjugate]").Click '<  first element with value attribute having value of Conjugate
        End With

        Stop '<= delete me later
        .Quit
    End With
End Sub

Exploring css selectors in your browser (Chrome shown):

在此处输入图片说明


Practicing css selectors:

https://flukeout.github.io/

When I'm working with a hierarchical data structure such as HTML (or JSON for that matter) I find myself getting easily confused by assuming which data element I'm working on. This is especially true if I start stacking up multi-level references as you've done (and I've seen and done much deeper levels that this).

So I most often turn on early binding: in this case go to Tools-->References and make sure the Microsoft HTML Object Library is checked.

Then, I unpack the levels into intermediate objects:

Dim nodeList As IHTMLElementCollection
Set nodeList = IE.document.getElementsByName("word")
nodeList.Item(0).Value = verb

This way I can use the VBE debugger and examine the data structures and build my confidence that I'm working with the exact data element and list item (and sub-element, etc) that I wanted.

I was able to make the following changes to your code and make it work for me:

Option Explicit

Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr) 'For 64 Bit Systems

Sub getVerb()
    Dim IE As Object                             ', objShellWindows As Object
    Dim verb As String, strWebPath As String

    strWebPath = "http://www.conjugation.org/"

    verb = "querer"

    'Navigate to page
    '----------------
    Set IE = CreateObject("InternetExplorer.Application")
    With IE
        .Visible = True
        .Navigate strWebPath
    End With

    'Wait for page
    Do While IE.Busy
        Sleep 250
        DoEvents
    Loop

    'Fill out
    '---------
    'Enter verb
    '<input type="text" size="25" name="word">
    Dim nodeList As IHTMLElementCollection
    Set nodeList = IE.document.getElementsByName("word")
    nodeList.Item(0).Value = verb

    'Set to List
    '<input type="radio" name="rb1" value="list">
    Set nodeList = IE.document.getElementsByName("rb1")
    nodeList.Item(0).Value = "list"

    'Press Button Conjugate
    '<input type="submit" name="B1" value="Conjugate">
    Set nodeList = IE.document.getElementsByName("B1")
    nodeList.Item(0).Click

    'TODO: extract info

    'Exit IE
    '--------
    IE.Quit
    Set IE = Nothing

End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM