Excel VBA and HTML DOM: Can't Click Tab

无人久伴 提交于 2021-01-29 17:29:00

问题


In Excel 2003 VBA, I'm trying to browse to this web page...

https://www.google.com/finance?q=NYSE%3AWSO&fstype=ii&ei=cy30UrCEI8KKiALOPw

...and click these two tabs on it:
- "Balance Sheet"
- "Annual Data"

Here's what the HTML for those tabs looks like:
<a class=t><b class=t><b class=t>Balance Sheet</b></b></a>
and
<a id=annual class="id-annual nac">Annual Data</a>

Finding Annual Data with getElementById, and clicking on it, worked fine.

But Balance Sheet has no ID. Using getElementByClass would be ambiguous with more than one element that has classname "t". And there doesn't seem to be a getElementByInnerText or getElementByInnerHTML.

So I looped through all elements, looking for classname "t", and then looking for innerText "Balance Sheet". I'm able to find the element (three of them, which I guess is expected given its structure), BUT clicking it has no effect (I tried clicking all three).

But when I tried that method with Annual Data, it worked fine.

What do I need to do to be able to click the "Balance Sheet" tab? I'm pretty sure I'm finding it; just not successfully clicking on it.

Here's my code:

Option Explicit

Sub TestMain()

    Dim strURL As String

    strURL = "https://www.google.com/finance?q=NYSE%3AWSO&fstype=ii&ei=cy30UrCEI8KKiALOPw"

    Call Main(strURL)

End Sub


Function Main(url_string As String)

    Dim oIE As Object, oDoc As Object, oElem As Object

    Set oIE = CreateObject("InternetExplorer.Application")

    oIE.Visible = True

    oIE.Navigate url_string
        Do While oIE.Busy
            Application.Wait DateAdd("s", 1, Now)
        Loop

    Set oDoc = oIE.document

    'Annual Data tab:
    Set oElem = GetElementsByClassNameAndInnerText(oDoc, "id-annual", True, "Annual Data", False)
    oElem.Click 'this works.

    'Quarterly Data:
    Set oElem = GetElementsByClassNameAndInnerText(oDoc, "id-interim", True, "Quarterly Data", False)
    oElem.Click 'this works.

    'Balance Sheet:
    Set oElem = GetElementsByClassNameAndInnerText(oDoc, "t", False, "Balance Sheet", True)
    oElem.Click 'does NOT work.

    'Income Statement:
    Set oElem = GetElementsByClassNameAndInnerText(oDoc, "t", False, "Income Statement", True)
    oElem.Click 'does NOT work.

    oIE.Quit
    Set oIE = Nothing

End Function


Public Function GetElementsByClassNameAndInnerText(html_doc As Object, _
                                                   class_name As String, is_classname_partial As Boolean, _
                                                   inner_text As String, is_innertext_partial As Boolean) As Object
    Dim oElem As Object
    Dim bClassNameIsMatch As Boolean, bInnerTextIsMatch As Boolean


    For Each oElem In html_doc.All
'        Debug.Print oElem.GetAttribute("class"), oElem.innertext
        bClassNameIsMatch = False 'init for each oElem.

        If is_classname_partial Then
            If InStr(oElem.GetAttribute("class"), class_name) > 0 Then
                bClassNameIsMatch = True
            End If
        Else
            'classname is exact:
            If oElem.GetAttribute("class") = class_name Then
                bClassNameIsMatch = True
            End If
        End If

        If bClassNameIsMatch Then
            bInnerTextIsMatch = False 'init for each oElem.

            If is_innertext_partial Then
                If InStr(oElem.innertext, inner_text) > 0 Then
                    bInnerTextIsMatch = True
                End If
            Else
                'innertext is exact:
                If oElem.innertext = inner_text Then
                    bInnerTextIsMatch = True
                End If
            End If

            If bInnerTextIsMatch Then
                If oElem.innertext = inner_text Then
                    Set GetElementsByClassNameAndInnerText = oElem
                    Exit For
                End If
            End If

        End If

    Next oElem
End Function

Thanks,

Greg


回答1:


I can't find a way to click those tabs programatically. The data, at least the tables so far, can be downloaded though as the tabs are only used to select which division is visable, all the data is on the page. In the following function the 6 divisions are copied into a file (could be cleaned up by writing a function to do this). IE is then redirected to this file.

If this is the sort of thing you are looking to do you might be better off looking at Microsofts HTML Object Library or XML in stead of IE and using get ot post to get the data.

I have used references to microsoft HTML object library, Microsoft internet controls and Microsoft scripting runtime for this function.

Function main(url_string As String)

    Dim oIE As InternetExplorer
    Dim oDivElement As HTMLDivElement
    Dim fsoObject As Scripting.FileSystemObject
    Dim FileHandle As Scripting.TextStream


    Set oIE = CreateObject("InternetExplorer.Application")

    oIE.Visible = True

    oIE.navigate url_string
    Do While oIE.Busy
       Application.Wait DateAdd("s", 1, Now)
    Loop

    Set fsoObject = New FileSystemObject
    Set FileHandle = fsoObject.CreateTextFile((ThisWorkbook.Path & "\Output.html"), True)


    Set oDivElement = oIE.document.getElementById("incinterimdiv")
    FileHandle.WriteLine ("Quarterly income")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine (oDivElement.innerHTML)
    Set oDivElement = oIE.document.getElementById("incannualdiv")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine ("Annual income")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine (oDivElement.innerHTML)
    Set oDivElement = oIE.document.getElementById("balinterimdiv")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine ("Quarterly balance")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine (oDivElement.innerHTML)
    Set oDivElement = oIE.document.getElementById("balannualdiv")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine ("Annual balance")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine (oDivElement.innerHTML)
    Set oDivElement = oIE.document.getElementById("casinterimdiv")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine ("Quarterly cash flow")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine (oDivElement.innerHTML)
    Set oDivElement = oIE.document.getElementById("casannualdiv")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine ("Annual cash flow")
    FileHandle.WriteLine ("<BR>&nbsp;<BR>")
    FileHandle.WriteLine (oDivElement.innerHTML)

    FileHandle.Close
    Set FileHandle = Nothing
    Set fsoObject = Nothing
    Set oDivElement = Nothing
    Set oIE = Nothing

End Function



回答2:


This does the trick for me. Step through the code after the web page has loaded to see what is happening.

Sub test()
    URL = "https://www.google.com/finance?q=NYSE%3AWSO&fstype=ii&ei=cy30UrCEI8KKiALOPw"

    Set IE = CreateObject("InternetExplorer.Application")
        IE.Visible = True
        IE.navigate URL

    Do Until (IE.readyState = 4 And Not IE.Busy)
        DoEvents
    Loop

' This will 1) "unclick" "the Income Statement" sheet tab and 2) "click" the "Balance Sheet" tab;
' the data below doesn't change, just the tab
    IE.document.getElementbyID(":0").classname = "goog-tab"
    IE.document.getElementbyID(":1").classname = "goog-tab goog-tab-selected"

' This will change the data below the tabs
    IE.document.getElementbyID("incinterimdiv").setAttribute("Style") = "display: none;"
    IE.document.getElementbyID("balinterimdiv").setAttribute("Style") = ""

    IE.document.getElementbyID("balinterimdiv").setAttribute("Style") = "display: none;"
    IE.document.getElementbyID("casinterimdiv").setAttribute("Style") = ""

    IE.document.getElementbyID("incinterimdiv").setAttribute("Style") = ""
    IE.document.getElementbyID("casinterimdiv").setAttribute("Style") = "display: none;"
End Sub


来源:https://stackoverflow.com/questions/21660096/excel-vba-and-html-dom-cant-click-tab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!