无需导航到此网页即可访问网页的框架文档

时间:2016-11-10 14:06:46

标签: html windows vba internet-explorer

标题可能令人困惑,但它不仅仅是一种印象。 我有一个previous post,但核心问题实际上比这更深。

基本上我有一个很大的代码,我可以从我的公司导航到内部网页面(让我们将此网页称为开始网页)。

然后我提供用户名和密码信息,然后点击"登录"按钮。单击登录按钮将在新窗口中创建新网页。我们将此新网页称为主要网页。

主要网页包含我想要获取的所有重要信息,而“开始”网页现在对我来说毫无用处。

这里的第一个挑战是"激活"或"选择"自“开始”网页以来的主网页仍处于激活状态。主网页显然有一个URL,但直接导航到它是不可能的,这就是为什么我谈论"激活"或"选择"的网页。我设法在forum's post

的帮助下完成了这项工作

如果您对此有任何疑问,请与我联系,但这不是此帖的问题。

因此,在激活主网页的情况下,我想点击一个元素来显示更多信息。此元素嵌入在框架 postfachcontent 中。 请参阅Main Page HTML document OverviewZoom on part to click on

在我上面提到的上一篇文章中,我试图这样做,但熟悉"嵌入式"使任务更难的元素。

在其他成员的帮助下,我发现有两种方法可以进入 postfachcontent 框架:

  1. 通过选择孩子的框架:

       Set w = IEWindowFromLocation(path)
    
        Dim IEDoc As HTMLDocument
        Set IEDoc = w.document ' w is the so called Main webpage that I selected peviously in the code
    
      Dim SubFramesCollection As HTMLWindow2
      Dim GoodFrame As HTMLWindow2
      Dim Postfachcontent_Frame As HTMLWindow2
    
    
         Set SubFramesCollection = IEDoc.frames ' the length of this is 3 since it contains the 3 main frames
         Set GoodFrame = SubFramesCollection(1).frames ' this  contains the 2 frames of the "contentframe" frame so length = 2
         Set Postfachcontent_Frame = GoodFrame(1)
    
         Doc2 = Postfachcontent_Frame.document
    
  2. 但问题是,一旦我访问了框架,我就如何实际选择表格元素并点击它感到困惑

    1. 通过"导航"到一个新的网页,这将是主要网页的简化版本,只关注我感兴趣的框架,以便导航到主网页URL& contentframe .src(或 postfachcontent .src)。
    2. 但是,正如我上面所说,问题在于我无法直接导航到主网页,所以我想我可以尝试声明一个新的InternetExplorer窗口并给它一个位置而不实际导航到该页面(但不幸的是它没有工作)。尝试下面:

       Set w = IEWindowFromLocation(path)
      
          Dim IEDoc As HTMLDocument
          Dim IEDok As HTMLDocument
          Set IEDoc = w.document
      
      
       Dim ContentFramesCollection As IHTMLElementCollection
       Dim ContentFrame As HTMLFrameElement
       Dim PostFachContentFramesCollection As IHTMLElementCollection
      
        Set ContentFramesCollection = IEDoc.getElementsByName("contentframe") ' this works and returns 1 item which is the frame called contentframe, so it s a collection of element containing 1 element only
          ' MsgBox ContentFramesCollection.Length ' returns 1
      
      
        If Not ContentFramesCollection Is Nothing Then
      
             Set ContentFrame = ContentFramesCollection(0) ' Here we isolate the unique item contained in MainFramesCollection and store it in a single element called ContentFrame
             MsgBox w.document.Location & ContentFrame.src
            'On Error Resume Next
             Set w2.document.Location = w.document.Location & ContentFrame.src
            'MsgBox Err.Description ' returns automation error unspecified error
      
             Set IEDok = w2.document
             Set PostFachContentFramesCollection = IEDok.getElementsByName("postfachcontent")
             MsgBox PostFachContentFramesCollection.Length ' returns 0...oops
      
        End If
      

      感谢您的支持,欢迎任何帮助!

2 个答案:

答案 0 :(得分:1)

这是我在代码中的想法(此代码是未经测试的)。首先导航到开始登录页面。然后找到主页面。从主页面导航到第一帧然后到第二帧。之后,dom元素应该包含现在可以单击的目标按钮。 HTH

Option Explicit

' Add reference to Microsoft Internet Controls (SHDocVw)
' Add reference to Microsoft HTML Object Library
' Add reference to Microsoft Shall Controls And Automation

' e.g. http://192.168.51.52:9999/SomeApp/Login
Private Const StartUrl As String = "Your start URL" 

' e.g. http://192.168.51.52:9999/SomeApp/Content
Private Const MainUrl As String = "Your main URL" 

Sub ClickInsideOfFrame()

    Dim ie As SHDocVw.InternetExplorer
    Dim doc As MSHTML.HTMLDocument

    On Error GoTo error_handler

    ' Navigate to start page
    Set ie = New SHDocVw.InternetExplorer
    ie.Visible = True
    ie.navigate StartUrl
    WaitWhileBusy ie

    ' Enter user name and password and login
    Login

    ' Switch to Main page
    Set ie = IEWindowFromTitle(MainUrl)
    Set doc = ie.document

    ' First find content frame and navige to url of this frame
    NavigateToFrame ie, "frame[name='contentframe']"

    ' Find postfachcontent frame and navige to url of this frame next
    NavigateToFrame ie, "frame[name='postfachcontent']"

    ' Dom document should now contain the button which is inside of the 
    ' postfachcontent frame
    doc.querySelector("input[type='button'][name='some-button']").Click

error_handler:
    If Err.Number <> 0 Then MsgBox Err.Description, vbCritical, "Error"
    ie.Quit
    Set ie = Nothing
End Sub

Private Sub WaitWhileBusy(ie As SHDocVw.InternetExplorer)
    While ie.Busy Or ie.readyState <> READYSTATE_COMPLETE
        DoEvents
    Wend
End Sub

Function IEWindowFromTitle(sTitle As String) As SHDocVw.InternetExplorer
    ' ...
End Function

Private Sub NavigateToFrame(ie As SHDocVw.InternetExplorer, selector As String)
    Dim frame As MSHTML.HTMLFrameElement
    Dim doc As MSHTML.HTMLDocument
    Set doc = ie.document
    Set frame = doc.querySelector(selector)
    If Not frame Is Nothing Then
        ie.navigate MainUrl & frame.src
        WaitWhileBusy ie
        Exit Sub
    End If
    Err.Raise vbObjectError + 513, "NavigateToFrame", "Frame not found for selector '" & selector & "'."
End Sub


Private Sub Login()
    ' ...
End Sub

答案 1 :(得分:1)

解决方案:对于那些可能感兴趣的人,我在蒂姆·威廉姆斯的帮助下找到了here的一个方法来点击包含&#34; onclick&#34的多个可能元素之一;属性。

对于贪婪的人来说,这里是直接的一行解决方案,其中列出了可点击的元素:

IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td")

其中IEDoc是主网页的HTML文档。

备注:

  1. 为了获得最终解决方案,我必须做一些测试,看看我正在处理哪种类型,以确保我知道自己在做什么。您可以在以下代码示例中看到这些测试步骤,以及它们在注释中的MsgBox中的显示结果:

    MsgBox TypeName(IEDoc.getElementsByName("contentframe")(0)) ' returns HTMLFrameElement
        MsgBox IEDoc.getElementsByName("contentframe")(0).document.getElementsByName("postfachcontent").Length ' 0
        MsgBox IEDoc.frames(1).frames.Length ' returns 2
        MsgBox TypeName(IEDoc.frames(1).frames(1)) ' HTMLWindow2
        MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable")) ' HTMLDivElement
        MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").getElementsByName("result")) ' error
        MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")) 'DispElementcollection
         MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById
    
    ("notPrintable").document.getElementsByName("result")(0)) ' HTMLFormElement
     MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).getElementsByClassName("resultRow")) ' error
      MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByClassName("resultRow")) ' error
    MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document) ' HTMLDocument
    Result_Form_Doc = IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document ' error
    IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).Click ' works...but no click
    MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("tr")) ' DispHTMLElementCollection
    MsgBox IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("tr").Length ' 12...weird...I counted 2
    IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.querySelector("td[onclick='cView(62972172,'0', viewButton, '' );']").Click ' error
    MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.querySelector("td[onclick='cView(62972172,'0', viewButton, '' );']")) 'error
     MsgBox IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td").Length '42...counted 34
    MsgBox IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("table").Length ' 4...counted 1
    IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td")(30).Click ' WORKSSSSS
    MsgBox IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td").querySelectorAll("td[onclick='cView(62972172,'0', viewButton, '' );']").Length ' error
    MsgBox IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td").querySelectorAll("td[rowSpan='1']").Length ' error
    MsgBox TypeName(IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td")) ' DispHTMLElementCollection
    Dim Elem_td As IHTMLElement
    Dim el As Integer, ind As Integer
    Dim align_center_collection()
    el = 0
    ind = 0
    For Each Elem_td In IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td")
    el = el + 1
        If Elem_td.Align = "center" Then
            ind = ind + 1
    
            End If
    
    Next
    
    MsgBox el & " and " & ind   ' if onclick : 42 and 0 (expected 34 and 16)
                                   ' if rowspan : 42 and 42(expected 34 and 34)
                                ' if align = center : 42 and 2 (expected 34 and 2) - > good
                                ' if align = left : 42 and 14 (expected 34 and 14) - > good
                                ' if rowSpan : 42 and 42 (expected 34 and 34)
    
    1. 我注意到,在某些时候,VBA的Intellisense不再帮助你了解可用的属性/方法,这就是我必须经历一些测试的原因
    2. 似乎不可能以某种方式逐步完成所有这一切,因为即使typename返回有效类型,我也无法将其存储在同一类型的变量中。
    3. 我最终没有选择一个确切的元素,但是因为(正如你在图片中看到的那样)有一些可点击的,我没有做过#34;结果&#34;。 / LI>