Метод 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