PDA

View Full Version : Solved: Controlling IE pop-ups via DHTML



stanl
07-18-2008, 12:03 PM
I have a web-scraping application that involves a setting where several controls are populated from a pop-up. Currently I use sendkeys to (1) select dropdown values (2) fill in TEXTAREAS (3) check/uncheck boxes (4) click the submit button.

Because of issues with simultaneous access to the underlying data the pop-up references, I would like a DHTML solution.

If have tried the VBS code below from both a .wsc and converting to VBA - the function accepts 2 parameters, (1) a newly instantiated IE Object (2) partial title of the popup window. The thought is the function either returns 0 or 1 [False/True] but I cannot get consistent results with the line oIE1 = obj

Has anyone used a method such as this to connect to a pop-up? :dunno Stan


function getpopup(oIE1,ttle)
Dim nvar,objShell
nvar=0
Set objShell = CreateObject("Shell.Application")
For Each obj In objShell.Windows
If TypeName(obj.Document) = "HTMLDocument" Then
text = obj.document.title
If InStr(1,text,ttle,1) Then
Set oIE1 = obj
nvar=1
Exit For
End if
End if
Next
Set objShell = Nothing
getpopup = nvar
end function

TomSchreiner
07-19-2008, 07:31 PM
Hi Stan.

A more dependable method using the IE new window event...

Paste this code in a module that will support WithEvents. Run it...


Option Explicit

'provide a reference to Microsoft Internet Controls
'if this is not an available option, browse for ieframe.dll in your sys folder
Private WithEvents ie As InternetExplorer
Private WithEvents iePopup As InternetExplorer

Sub Example()

Set ie = Nothing: Set iePopup = Nothing
Set ie = New InternetExplorer
ie.Visible = True

ie.Navigate "http://mar.anomy.net/files/2004/02/popupdemo/"
Do Until ie.ReadyState = READYSTATE_COMPLETE And Not ie.Busy
'provide a timeout here
DoEvents
Loop

'click the first anchor element
ie.Document.getElementsByTagName("A")(0).Click
Do Until ie.ReadyState = READYSTATE_COMPLETE And Not ie.Busy And (Not iePopup Is Nothing)
'provide a timeout here
DoEvents
Loop

MsgBox "You now have a reference to the popup window. The locationURL = " & iePopup.LocationURL

End Sub

Private Sub ie_NewWindow2(ppDisp As Object, Cancel As Boolean)
Set iePopup = New InternetExplorer
Set ppDisp = iePopup
End Sub

stanl
07-20-2008, 03:58 AM
Paste this code in a module that will support WithEvents. Run it...


Thanks;

I think I need to have the code recognized as an 'object module', otherwise it errors out in the Private declarations. How do I accomplish this.

I can put the code in as a class module, but cannot call the sub, so do I need to initialize the class?
Stan

TomSchreiner
07-20-2008, 05:57 AM
Hi Stan. No need to instantiate it if you place it in a public class such as ThisWorkbook, one of your worksheets, or a custom class with its instancing property assigned with PublicNotCreatable. For example, if you place it in ThisWorkbook, you can call it directly like:

Call ThisWorkBook.Example

Download Example... (http://home.fuse.net/tstom/0720080851.www.vbaexpress.com.152541.zip)

stanl
07-20-2008, 07:18 AM
Thanks again;

downloaded and ran the workbook, and it was able to report the LocationURL. However, my real goal is to perform DHTML on the popup.

If I substitute

MsgBox "You now have a reference to the popup window. The locationURL = " & iePopup.LocationURL

which works

with
MsgBox "You now have a reference to the popup window. The HTML = " & iePopup.Document.InnerHTML

I get

TomSchreiner
07-20-2008, 08:43 AM
Hi Stan. The reference is there...

Option Explicit

Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long


'provide a reference to Microsoft Internet Controls
'if this is not an available option, browse for ieframe.dll in your sys folder
Private WithEvents ie As InternetExplorer
Private WithEvents iePopup As InternetExplorer

Sub Example()

Set ie = Nothing: Set iePopup = Nothing
Set ie = New InternetExplorer
ie.Visible = True

ie.Navigate "http://mar.anomy.net/files/2004/02/popupdemo/"
Do Until ie.ReadyState = READYSTATE_COMPLETE And Not ie.Busy
'provide a timeout here
DoEvents
Loop

'click the first anchor element
ie.Document.getelementsbytagname("A")(0).Click
Do Until ie.ReadyState = READYSTATE_COMPLETE And Not ie.Busy And (Not iePopup Is Nothing)
'provide a timeout here
DoEvents
Loop

SetForegroundWindow Application.hwnd

' MsgBox "You now have a reference to the popup window. The locationURL = " & iePopup.LocationURL
'
' SetForegroundWindow ie.hwnd
' SetForegroundWindow iePopup.hwnd

Do Until iePopup.Document.ReadyState = "complete"
'provide a timeout here
DoEvents
Loop

MsgBox "You now have a reference to the popup window. The HTML = " & iePopup.Document.body.parentelement.InnerHTML
End Sub

Private Sub ie_NewWindow2(ppDisp As Object, Cancel As Boolean)
Set iePopup = New InternetExplorer
Set ppDisp = iePopup
End Sub

stanl
07-20-2008, 10:57 AM
Hi Stan. The reference is there...


Thanks
Stan

stanl
07-20-2008, 11:11 AM
I'm marking this thread close, but this is the sort of help that a good article could/should be written about.

I had previously tried document.ParentWindow rather than document.parentelement and kept getting Object Error messages -

Tom, it is obvious you have a great understanding of the IE object hierarchy - :clap: Stan

TomSchreiner
07-21-2008, 12:25 AM
Hi Stan. A big help is to early bind to MS HTML Object Library and use a more verbose syntax. Getting the benefit of intellisense with this extremely large library is must for me... Also, open your object browser and take a look at the typical offering for the run of the mill element. Select the HTMLGenericElement class and look at the list of properties and methods as compared to your average MSForms control. You can create some really spiffy userforms using HTML in a browser control.


Option Explicit

Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long


'provide a reference to Microsoft Internet Controls
'if this is not an available option, browse for ieframe.dll in your sys folder
'add a reference to Microsoft HTML Object Library as well :)
Private WithEvents ie As InternetExplorer
Private WithEvents iePopup As InternetExplorer

Sub Example()
Dim Doc As HTMLDocument
Dim Anchor As HTMLAnchorElement

Set ie = Nothing: Set iePopup = Nothing
Set ie = New InternetExplorer
ie.Visible = True

ie.Navigate "http://mar.anomy.net/files/2004/02/popupdemo/"
Do Until ie.ReadyState = READYSTATE_COMPLETE And Not ie.Busy
'provide a timeout here
DoEvents
Loop

'click the first anchor element
Set Doc = ie.Document
Set Anchor = Doc.getElementsByTagName("A").Item(0)
Anchor.Click

Do Until ie.ReadyState = READYSTATE_COMPLETE And Not ie.Busy And (Not iePopup Is Nothing)
'provide a timeout here
DoEvents
Loop

SetForegroundWindow Application.hwnd

' MsgBox "You now have a reference to the popup window. The locationURL = " & iePopup.LocationURL
'
' SetForegroundWindow ie.hwnd
' SetForegroundWindow iePopup.hwnd

Do Until iePopup.Document.ReadyState = "complete"
'provide a timeout here
DoEvents
Loop

MsgBox "You now have a reference to the popup window. The HTML = " & iePopup.Document.body.parentelement.InnerHTML
End Sub

Private Sub ie_NewWindow2(ppDisp As Object, Cancel As Boolean)
Set iePopup = New InternetExplorer
Set ppDisp = iePopup
End Sub

stanl
07-21-2008, 11:30 AM
You are right on. I initialize my Object directly and found that

oIE = CreateObject("InternetExplorer.Application.1") is more reliable; and there are some interesting threads on how it differs from ("InternetExplorer.Application")

Stan