GetElementsbyClassname: методы Open IE и MSXML2

Следующий макрос работает просто отлично. Он открывает экземпляр IE и использует метод «getelementsbyclassname», чтобы вернуть ожидаемое значение для «my_rate». Однако, когда я запускаю второй макрос, использующий метод «MSXML2», макрос завершается сбоем в отмеченной строке и возникает ошибка «Ошибка времени выполнения 438: объект не поддерживает это свойство или метод». Почему метод «Открыть IE» работает, а метод «MSXML2» не работает с моим кодом? Я работаю с IE 11. У меня также есть ссылка на библиотеку объектов Microsoft HTML для второго макроса, но, похоже, это не имеет значения. Заранее спасибо, что объяснили мне это.

Sub BankRate_Rate_Retrieval()
    my_url = "http://www.bankrate.com/funnel/mortgages/mortgage-results.aspx?market=321&loan=150000&perc=20&prods=2&points=0"   
    Set ie = CreateObject("InternetExplorer.Application")

    With ie
        .Visible = True
        .Navigate my_url
        .Top = 50
        .Left = 530
        .Height = 400
        .Width = 400
    End With

    Do Until Not ie.Busy And ie.readyState = 4
        DoEvents
    Loop

    my_rate = ie.Document.getelementsbyclassname("br-col-2 br-apr")(1).getElementsByTagName("div")(0).innertext
End Sub


Sub BankRate_Rate_Retrieval()
    my_url = "http://www.bankrate.com/funnel/mortgages/mortgage-results.aspx?market=321&loan=150000&perc=20&prods=2&points=0"
    Set html_doc = CreateObject("htmlfile")
    Set xml_obj = CreateObject("MSXML2.XMLHTTP")

    xml_obj.Open "GET", my_url, False
    xml_obj.send
    html_doc.body.innerhtml = xml_obj.responseText
    Set xml_obj = Nothing

    my_rate = html_doc.body.getelementsbyclassname("br-col-2 br-apr")(1).getElementsByTagName("div")(0).innertext

' Ошибка выполнения 438: объект не поддерживает это свойство или метод встречается в строке выше

Конец сабвуфера

Редактировать: Скриншот библиотеки для Д. Земенса

введите здесь описание изображения


person ron    schedule 05.05.2014    source источник
comment
Библиотека объектов HTML должна работать, пока у вас есть IE9+. Например, Dim doc As HTMLDocument, а затем в коде Set doc = New HTMLDocument: doc.body.innerHTML = xml_obj.responseText. Тогда Set el = doc.getelementsbyclassname("br-col-2 br-apr") должно работать нормально?   -  person    schedule 05.05.2014
comment
Бинго, это работает! Я провел дальнейшие поиски и обнаружил, что это известная проблема раннего и позднего связывания с getElementsByClassName и MSXML2. Мой макрос включает позднее связывание, ваш подход предполагает раннее связывание; работы только по переплету   -  person ron    schedule 06.05.2014
comment
Я обновил свой IE с IE7 до IE11. Теперь работает getElementsByClassName.   -  person Harsh Goyal    schedule 16.03.2016


Ответы (1)


Сообщение об ошибке довольно простое:

GetElementsByClassName не является методом, доступным в библиотеке Microsoft XML версии 6.0.

Вы можете просмотреть доступные методы здесь:

http://msdn.microsoft.com/en-us/library/aa926433.aspx

И хотя я не могу найти аналогичную ссылку на документацию, если вы включите ссылку на библиотеку MSHTML, вы можете просмотреть ее, чтобы подтвердить, что нет метода GetElementsByClassName. Этот метод доступен для автоматизации IE, но не для HTML или DOMDocument.

введите здесь описание изображения

ОБНОВЛЕНО

Хотя это может не решить вашу проблему, я поместил это здесь на случай, если это поможет другим пользователям IE8. Кажется, он работает для этой цели, но, возможно, его нужно доработать.

Option Explicit

Sub BankRate_Rate_Retrieval()
Dim my_url As String
Dim html_doc As Object 'HTMLDocument
Dim xml_obj As Object 'MSXML2.DOMDocument
Dim my_rate As String

my_url = "http://www.bankrate.com/funnel/mortgages/mortgage-results.aspx?market=321&loan=150000&perc=20&prods=2&points=0"

Set html_doc = CreateObject("htmlfile")
Set xml_obj = CreateObject("MSXML2.XMLHTTP")

xml_obj.Open "GET", my_url, False
xml_obj.send
html_doc.body.innerhtml = xml_obj.responseText

'attempt to replicate the GetElementsByClassName for IE8

my_rate = IE8_GetElementsByClassName(html_doc.body, "br-col-2 br-apr", 1).GetElementsByTagName("div")(0).InnerText

MsgBox my_rate


Set xml_obj = Nothing
Set html_doc = Nothing


End Sub

Function IE8_GetElementsByClassName(html As Object, className As String, Optional Position As Integer)
'Function to return an array of matching classname elements
' or if specified will return a single HTMLElement by Position index

Dim eleDict As Object
Dim ele as Variant
Set eleDict = CreateObject("Scripting.Dictionary")
For x = 0 To html.all.Length - 1
    Set ele = html.all(x)
    If ele.className = className Then
        'Debug.Print i & vbTab & x & vbTab & ele.InnerText
        Set eleDict(i) = ele
        i = i + 1
    End If
Next

If Position = Empty Then
    IE8_GetElementsByClassName = eleDict.Items
Else
    Set IE8_GetElementsByClassName = eleDict(Position)
End If
Set eleDict = Nothing
End Function
person David Zemens    schedule 05.05.2014
comment
В моем классе HTML-документа getElementsByClassName указан как член. - person ron; 05.05.2014
comment
Хмммм... ну, у меня не та же версия/система, что и у вас, поэтому я не смогу больше помочь. Я считаю, что они добавили GetElementsByClassName с IE9+. (Я использую 8, поэтому я не могу это подтвердить). Даже стандарт w3 для HTMLDocument не предоставляет метод GetElementsByClassName: w3schools.com/jsref/dom_obj_document. asp Я добавил новый снимок экрана с дополнительной информацией, ваш такой же (мне интересно, есть ли у вас HTMLDocument, который является членом другой библиотеки, чем MSHTML). - person David Zemens; 05.05.2014
comment
Да, я думаю, что это одна и та же библиотека. Я отредактировал свой вопрос и поместил снимок экрана внизу - person ron; 05.05.2014
comment
Извините, я не опубликовал обновленный скриншот. Он должен быть там сейчас. Убедитесь, что вы видите этот член класса HTMLDocument MSHTML. - person David Zemens; 05.05.2014
comment
да, это одна и та же библиотека - person ron; 05.05.2014
comment
возможно, поздняя привязка подбирает более старую версию? - person ; 05.05.2014
comment
Не могу сказать наверняка. Я сделал функцию, которая пытается воспроизвести метод GetElementsByClassName, я обновлю свой ответ, и вы можете попробовать это. - person David Zemens; 05.05.2014
comment
ОК, я обновил свою функцию. Кажется, это работает, но будет медленнее, так как по сути это метод грубой силы. - person David Zemens; 05.05.2014