【问题标题】:Access to a webpage's frame document without navigating to this webpage无需导航到该网页即可访问网页的框架文档
【发布时间】:2016-11-10 14:06:46
【问题描述】:

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

基本上,我有一个大代码,我在其中导航到我公司的 Intranet 网页(我们将此网页称为 Start 网页)。

然后我提供用户名和密码信息并单击“登录”按钮。单击登录按钮将在新窗口中创建一个新网页。我们将这个新网页称为主网页。

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

这里的第一个挑战是“激活”或“选择”主网页,因为“开始”网页仍处于激活状态。主网页显然有一个 URL,但无法直接导航到它,所以这就是我谈论网页的“激活”或“选择”的原因。在forum's post的帮助下,我设法做到了这一点

如果您对此有任何疑问,请告诉我,但这不是这篇文章的问题。

因此,激活主网页后,我想单击一个元素以显示更多信息。该元素嵌入在框架postfachcontent 中。 请参阅Main Page HTML document Overview 和Zoom 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
    

但这里的问题是,一旦我访问了框架,我就对如何实际选择表格元素并单击它感到困惑

  1. 通过“导航”到一个新网页,该网页将是主网页的简化版本,仅关注我感兴趣的框架,因此导航到主网页 URL 和 contentframe.src(或 postfachcontent.src)。

但是,正如我上面所说,这里的问题是我无法直接导航到主网页,所以我想我可以尝试声明一个新 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

感谢您到达那条线,欢迎任何帮助!

【问题讨论】:

    标签: html windows vba internet-explorer


    【解决方案1】:

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

    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
    

    【讨论】:

    • 感谢您的长期投资!我正在经历这个,但是当我尝试访问内容框架时,我遇到了使用查询选择器的问题。返回的错误描述是对象不支持该属性或方法。到目前为止,我已经创建了一个新模块来处理这部分,但即使通过更改变量框架的类型或在查询选择器中添加更多信息,我仍然收到错误 Run-time error 91 : Object variable 或没有设置块变量。我可能需要添加一个特殊的引用来扩展属性/方法。如果我能解决这个问题,我会告诉你的。
    • 哦,好吧,我看到它是这样工作的。我之前尝试将 doc 声明为整个模块的私有变量,但没有成功,但没有考虑这个解决方案。不幸的是,我最害怕的下一个错误发生了。同样,导航到主页是不可能的,它当然会打开一个新页面,但这会显示一条错误消息......
    • 我的理解是否正确:函数IEWindowFromTitle没有找到主页?因此你得到 Err 91?
    • 不不,我在主页上。但是当代码第一次通过 NavigateToFrame 以选择 contentframe 时,我们有 ie.navigate MainUrl 和 frame.src 并且此行导航到一个没有任何信息的网页,除了一条错误消息说这个网页无效
    • 网页无效?还是找不到错误 404 页面?
    【解决方案2】:

    解决方案:对于那些可能感兴趣的人,我在 dee 和 Tim Williams 在here 上的帮助下找到了一种单击包含“onclick”属性的多个可能元素之一的方法。

    对于贪心的人,这里是直接的解决方案,它列出了可点击的元素:

    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. 似乎不可能一步一步完成所有这些,因为即使类型名返回一个有效类型,我也无法将其存储在同一类型的变量中。
      3. 我最终没有选择一个确切的元素,但由于(如图所示)有几个可点击的,我没有做“finition”。

    【讨论】:

      猜你喜欢
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-23
      • 1970-01-01
      • 2015-07-01
      相关资源
      最近更新 更多