Метод VBA GetElementsById "Переменная объекта не установлена"

Я пытаюсь выбрать идентификатор главного меню этой страницы http://greyhoundstats.co.uk/index.php надписью ("menu_wholesome") чтобы получить их гиперссылки позже. В HTML-документе есть два тега с этим идентификатором: <div> и его дочерний элемент <ul>, но когда я ищу их с кодом ниже, я получаю ошибку "переменная объекта не установлена".

Option Explicit

Public Const MenuPage As String = "http://greyhoundstats.co.uk/index.php"

Sub BrowseMenus()

Dim XMLHTTPReq As New MSXML2.XMLHTTP60
Dim HTMLDoc As New MSHTML.HTMLDocument

Dim MainMenuList As MSHTML.IHTMLElement
Dim aElement As MSHTML.IHTMLElementCollection
Dim ulElement As MSHTML.IHTMLUListElement
Dim liElement As MSHTML.IHTMLLIElement

XMLHTTPReq.Open "GET", MenuPage, False
XMLHTTPReq.send

HTMLDoc.body.innerText = XMLHTTPReq.responseText

    Set MainMenuList = HTMLDoc.getElementById("menu_wholesome")(0) '<-- error happens here

End Sub

Кто-нибудь знает, почему getElementsById не может найти указанный идентификатор, хотя он является частью набора документов HTML? Я знаю, что этот метод должен возвращать уникальный идентификатор, но когда у нас есть тот же самый, на который ссылаются другие теги, я также знаю, что я верну первый найденный идентификатор, который должен быть <div id="menu_wholesome"> часть запрашиваемой HTML-страницы.

2 ответа

Решение

Во-первых: вы хотите работать и установить innerHTML, когда вы собираетесь проходить документ DOM.

Во-вторых: эта строка

Set MainMenuList = HTMLDoc.getElementById("menu_wholesome")(0)

Это неверно. getElementById возвращает один элемент, который вы не можете проиндексировать. Вы индексируете в коллекцию.

Обратите внимание: и div, и ul ведут к одному и тому же контенту.

Если вы хотите выбрать их отдельно, используйте querySelector

HTMLDoc.querySelector("div#menu_wholesome")
HTMLDoc.querySelector("ul#menu_wholesome")

Вышеуказанная цель сначала по имени тега, а затем по атрибуту id.

Если вы хотите коллекцию идентификаторов, используйте querySelectorAll вернуть нодлист из соответствующих элементов. Идентификаторы должны быть уникальными для страницы, но иногда это не так!

HTMLDoc.querySelectorAll("#menu_wholesome")

Затем вы можете индексировать в nodeList, например,

HTMLDoc.querySelectorAll("#menu_wholesome").item(0)

VBA:

Option Explicit

Public Const MenuPage As String = "http://greyhoundstats.co.uk/index.php"
Sub BrowseMenus()
    Dim sResponse As String, HTMLDoc As New MSHTML.HTMLDocument
    Dim MainMenuList As Object, div As Object, ul As Object

    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", MenuPage, False
        .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
        .send
        sResponse = StrConv(.responseBody, vbUnicode)
    End With

    sResponse = Mid$(sResponse, InStr(1, sResponse, "<!DOCTYPE "))
    HTMLDoc.body.innerHTML = sResponse

    Set MainMenuList = HTMLDoc.querySelectorAll("#menu_wholesome")

    Debug.Print MainMenuList.Length

    Set div = HTMLDoc.querySelector("div#menu_wholesome")
    Set ul = HTMLDoc.querySelector("ul#menu_wholesome")

    Debug.Print div.outerHTML
    Debug.Print ul.outerHTML

End Sub

Неясно, чего вы пытаетесь достичь. Я только что исправил текущую проблему, с которой вы столкнулись в данный момент. .getElementById () имеет дело с отдельным элементом, поэтому, когда вы рассматриваете его как коллекцию элементов, он выдаст эту ошибку. Если вы заметили эту часть getElementBy и getElementsBy, вы можете увидеть вариацию относительно того, какой из них является набором элементов (не забывайте про s). Вы можете использовать только (0) или что-то подобное, когда вы используете getElementsBy.

Вы должны правильно сделать отступ в своем коде, чтобы другие могли прочитать его без проблем:

Sub BrowseMenus()
    Const MenuPage$ = "http://greyhoundstats.co.uk/index.php"
    Dim HTTPReq As New XMLHTTP60, HTMLDoc As New HTMLDocument
    Dim MainMenuList As Object

    With HTTPReq
        .Open "GET", MenuPage, False
        .send
        HTMLDoc.body.innerHTML = .responseText
    End With

    Set MainMenuList = HTMLDoc.getElementById("menu_wholesome")
End Sub
Другие вопросы по тегам