2016-11-10 41 views
3

标题可能会令人困惑,但它不仅仅是一种印象。 我对此有一个previous post,但核心问题实际上比这更深。访问网页的框架文档,无需导航到此网页

基本上我有一个很大的代码,我从我的公司导航到一个Intranet网页(让我们把这个网页称为开始网页)。

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

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

此处的第一个挑战是“启动”或“选择”主页面,因为“开始”页面仍处于激活状态。主网页显然有一个URL,但是不可能直接导航到这个网址,所以这就是为什么我要谈论网页的“激活”或“选择”。我设法做到这一点的帮助下,forum's post

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

所以在主网页激活的情况下,我想单击一个元素来显示更多信息。该元素嵌入在框架postfachcontent中。 见Main Page HTML document OverviewZoom on part to click on

在我之前提到的文章中,我试图做到这一点,但熟悉使嵌入式任务变得更加困难的元素。

与其他成员的帮助下,我想通了,可能有2种方式在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 
    

但是,这里的问题是,一旦我访问框架,我很困惑如何真正选择表格的元素,并点击它

  • 所谓“导航”到一个新的网页,其将主网页的缩减版本仅聚焦我对如此导航到主网页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 
    

    感谢您接触到此行,并欢迎任何帮助!

    回答

    1

    解决方案:对于那些可能会感兴趣,我发现与DEE的帮助和蒂姆·威廉姆斯对here的方式asnwer点击含有“点击”属性中的多种可能因素之一。

    对于贪心的孩子,这里的直于一身的行解决方案其中列出了可点击元素:

    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) 
      
    2. 我注意到,在某些时候VBA的智能感知赢得不再帮助你了解可用的属性/方法,所以这就是为什么我必须通过几个测试
    3. 似乎不可能以某种方式做所有这一步一步,因为即使typename返回一个有效的类型,我可以'把它存储在一个相同类型的变量中。
    4. 我没有最终选择一个确切的元素,但是因为(就像你在图片上看到的)有几个可点击的,我没有做“finition”。
    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 
    
    +0

    感谢您的长期投资!我正在经历这个,但当我尝试访问contentframe时,我遇到了使用queryselector的问题。返回的错误描述是_object不支持此属性或method_。到目前为止,我已经创建了一个新的模块来处理这部分,但即使通过更改可变框架的类型或在查询选择器中添加更多信息,我仍然遇到错误_运行时错误91:对象变量或With块变量不是set_.我可能需要添加一个特殊的引用来扩展属性/方法。如果我设法解决这个问题,我会告诉你。 – Seb

    +0

    检查编辑后的答案(NavigateToFrame函数)。 – dee

    +0

    噢好吧,我看到它的工作方式。我之前曾尝试将doc作为整个模块的私有变量声明失败,但未考虑此解决方案。不幸的是,我最怕发生的下一个错误。再次,不可能导航到主页面,当然会打开一个新页面,但是这个页面会显示一条错误消息... – Seb