Reputation: 520
The title might be confusing, but it's not just an impression. I had a previous post about this but the core problem is actually deeper than this.
Basically I have a big code in which I navigate to an intranet webpage from my company ( let's call this webpage the Start webpage).
I then provide username and password information and click on the "login" button. Clicking on the login button will create a new webpage in a NEW window. We will call this new webpage the Main webpage.
The Main webpage contains all the important information I want to get while the Start webpage is now useless to me.
First challenge here was then to "activate" or "select" the Main webpage since the Start webpage was still activated. The Main webpage has obviously a URL but it's impossible to directly navigate to it, so that's why I talk about "activation" or "selection" of the webpage. I managed to do this with the help of that forum's post
If you have any questions about it let me know, but it's not the problem of this post.
So with the Main webpage activated, I want to click on an element to display more information. This element is embedded in the frame postfachcontent. See Main Page HTML document Overview and Zoom on part to click on.
In my previous post mentioned above, I tried to do this but got familiar with "embedded" elements who made the task harder.
With the help of other members, I figured out there could be 2 ways to get in the postfachcontent frame :
By selecting child by child the frames :
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
But the problem here is that once I accessed to the frame I got confused on how to actually select the element of the table and click on it
But the problem here, as I said above, is that I can't navigate to the Main webpage directly so I thought I could try to declare a New InternetExplorer window and give it a location without actually navigating to the page ( but it doesn't work unfortunately). Attempt below :
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
Thanks for reaching that line and any help is welcome !
Upvotes: 3
Views: 1450
Reputation: 520
SOLUTION : For those it might interest, I found with the help of dee and the asnwer of Tim Williams on here a way to click on one of the multiple possible elements containing a "onclick" property.
For the greedy ones, here's the straight in-one-line solution which lists the clickable elements :
IEDoc.frames(1).frames(1).document.getElementById("notPrintable").document.getElementsByName("result")(0).document.getElementsByTagName("td")
where IEDoc is the HTML document of the Main webpage.
Remarks :
In order to get this final solution, I had to do some tests to see which type I was dealing with to make sure I knew what I was doing. You can see these tests steps in the following code sample as well as their displayed result in the MsgBox in comment :
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)
Upvotes: 1
Reputation: 14053
Here my idea in code (this code is untested). First navigate to start page to login. Then find the main page. From the main page navigate to first frame and then to second. After that the dom element should contain the target button which can be now clicked. 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
Upvotes: 1