stefanpantu
asked on
Finding out if instance of IE is busy/ready with InternetExplorer Automation
Using VBA, trying to find out if IE has stopped downloading a web page with two frames.
This question is very similar to the question/answer at
https://www.experts-exchange.com/questions/20529021/Internet-Explorer-ActiveX-Control-busy-property-doesn't-work-in-do-loop.html?query=.busy&topics=93
in which the .busy and .ReadyState attributes of the WebBrowser control do not work and therefore the busy/readystate status of IE must be monitored with the IE_DownloadComplete event. I am experiencing the EXACT problem described in Q_20529021.
I have two questions regarding this issue :
1. On a page with frames, could it be possible that each frame has a .busy or .readystate attribute, something like
IE.Document.frames(1).Docu ment.forms (0).busy
and therefore you would have to check the .busy/.readystate attribute of each frame instead of the usual IE.busy ?
2. If frames do not have their own .busy/.readystate attributes then the IE_DownloadComplete event must be used to check the status of the IE instance.
For compatibility reasons I can not use the WebBrowser control. I can check the status of the IE instance using the IE_DownloadComplete event. The code for the event is:
Private Sub IE_DownloadComplete(ByVal pDisp As Object, URL As Variant)
Debug.Print "Download Is Complete"
End Sub
but the event is not linked to an object. How can I link this event to the IE instance given that I am not using a WebBrowserControl? Are there any other ways to check if the IE instance has stopped processing a web page?
This question is very similar to the question/answer at
https://www.experts-exchange.com/questions/20529021/Internet-Explorer-ActiveX-Control-busy-property-doesn't-work-in-do-loop.html?query=.busy&topics=93
in which the .busy and .ReadyState attributes of the WebBrowser control do not work and therefore the busy/readystate status of IE must be monitored with the IE_DownloadComplete event. I am experiencing the EXACT problem described in Q_20529021.
I have two questions regarding this issue :
1. On a page with frames, could it be possible that each frame has a .busy or .readystate attribute, something like
IE.Document.frames(1).Docu
and therefore you would have to check the .busy/.readystate attribute of each frame instead of the usual IE.busy ?
2. If frames do not have their own .busy/.readystate attributes then the IE_DownloadComplete event must be used to check the status of the IE instance.
For compatibility reasons I can not use the WebBrowser control. I can check the status of the IE instance using the IE_DownloadComplete event. The code for the event is:
Private Sub IE_DownloadComplete(ByVal pDisp As Object, URL As Variant)
Debug.Print "Download Is Complete"
End Sub
but the event is not linked to an object. How can I link this event to the IE instance given that I am not using a WebBrowserControl? Are there any other ways to check if the IE instance has stopped processing a web page?
Perhaps you could also tell us what you want to do with the IE control... I use it in an application to extract some elements of the HTML for example.
tm
tm
ASKER
If anyone knows how to use the IE_DownloadComplete outside of the WebBrowser control, I'm sure this is the correct way to solve this problem. I can't use WebBrowser for compatibility reasons (my app needs to check for the presence of IE 6)
My code and Debug output is below. In all my experience with READYSTATE_COMPLETE, it is only different from 4 when a new instance of a browser is first opened. After a browser is opened READYSTATE_COMPLETE is always 4 (see debug output below).
I was only able to check for specific HTML text after loading this page to make sure a page had completely loaded. That's clumsy, but not as clumsy as adding a statement like
Application.Wait (Now + TimeValue("0:00:01"))
It's the only way I was able to get a button click to work to open the final page. And if the server is slow, then I'm sure this code will break.
Function TestLogonIE() As Boolean
'test to autologon into quote website
Dim IE As Object
Dim form0 As Object
Dim document1 As Object
Dim hwnd As Long
Dim oForm As Object
Dim ieClipboard As Object
Dim clipboardContents As String
Static errorStartTime As Date
On Error GoTo ErrorHandler
Set IE = New InternetExplorer
With IE
.Navigate "http://www.alaron.ranweb.com/login/alr.asp"
.Visible = False 'show/hide browser
.Silent = True 'suppress dialog boxes
End With
Call WaitIE(IE) 'wait to load link, ReadyState seems to be set
'to a value other than 4 only when browser is opened
Set form0 = IE.document.frames(1).docu ment.forms (0)
Set document1 = IE.document.frames(1).docu ment
form0.elements("Username") .Value = Username
form0.elements("Password") .Value = Password
document1.images("ImageLog On").Click
Call WaitIEHTML(IE, "Quote")
Debug.Print "Quote Request Page Loaded, " & "ReadyState: " & CStr(IE.ReadyState)
Set form0 = IE.document.frames(1).docu ment.forms (0) 'repoint to new webpage
form0.elements("O_QC").Val ue = "spx4 c1190" 'goto error 91 if page not loaded
Application.Wait (Now + TimeValue("0:00:01")) 'don't like Waiting a second here,
'but it's the only way to get the next .Click to work
Debug.Print "Quote Set, " & "ReadyState: " & CStr(IE.ReadyState)
document1.images("QC_G").C lick 'Click Go button to display quote page
Call WaitIEHTML(IE, "Key:Real-time QuoteDelayed QuoteInvalid Contract") 'wait for this text
Debug.Print "Quote Go Button Clicked, " & "ReadyState: " & CStr(IE.ReadyState)
form0.elements("O_QC").Cli ck 'select the right frame
Debug.Print "Select the right frame button click, " & "ReadyState: " & CStr(IE.ReadyState)
IE.ExecWB OLECMDID_SELECTALL, OLECMDEXECOPT_DODEFAULT
IE.ExecWB OLECMDID_COPY, OLECMDEXECOPT_DODEFAULT
Debug.Print "Quote Page Copied To Clipboard," & "ReadyState: " & CStr(IE.ReadyState)
Set ieClipboard = New DataObject
ieClipboard.GetFromClipboa rd
clipboardContents = ieClipboard.GetText(1)
'clipboardContents = document1.Selection.create Range.Text 'this works if text is selected, but no delimitors
'clipboardContents = document1.body.innertext ' this also works, but again no delimitors!
Set ieClipboard = Nothing
Set form0 = Nothing
Set document1 = Nothing
Set IE = Nothing
errorStartTime = #12:00:00 AM#
Exit Function
ErrorHandler:
Select Case Err.Number
Case 91 'Object Variable or With Block Not Set (IE DOM error)
If errorStartTime = #12:00:00 AM# Then
errorStartTime = Time
End If
If errorStartTime <> #12:00:00 AM# Then
If Time > TimeSerial(Hour(errorStart Time), Minute(errorStartTime) + 1, Second(errorStartTime)) Then Exit Function
End If
Debug.Print "Ran Error Handler"
DoEvents
Resume
Case Else
Debug.Print CStr(Err.Number) & ": " & Err.Description
End Select
End Function
Private Sub WaitIE(IE As Object)
Do
DoEvents 'wait until IE is done loading page.
Debug.Print "Waiting..."
Loop Until IE.ReadyState = READYSTATE_COMPLETE
End Sub
Private Sub WaitIEHTML(IE As Object, HTMLSearchText As String)
'wait for some specific HTML text to be displayed on the page
Do
DoEvents 'wait until IE is done loading page.
Debug.Print "Waiting IEHTML..."
Loop Until CBool(InStr(1, IE.document.frames(1).docu ment.body. innertext, HTMLSearchText))
End Sub
-------------------------- ---------- ------
Output:
.
.
.
Waiting...
Waiting...
.
.
.
Waiting IEHTML...
Quote Request Page Loaded, ReadyState: 4
Quote Set, ReadyState: 4
.
.
.
Waiting IEHTML...
Waiting IEHTML...
Waiting IEHTML...
Quote Go Button Clicked, ReadyState: 4
Select the right frame button click, ReadyState: 4
Quote Page Copied To Clipboard,ReadyState: 4
My code and Debug output is below. In all my experience with READYSTATE_COMPLETE, it is only different from 4 when a new instance of a browser is first opened. After a browser is opened READYSTATE_COMPLETE is always 4 (see debug output below).
I was only able to check for specific HTML text after loading this page to make sure a page had completely loaded. That's clumsy, but not as clumsy as adding a statement like
Application.Wait (Now + TimeValue("0:00:01"))
It's the only way I was able to get a button click to work to open the final page. And if the server is slow, then I'm sure this code will break.
Function TestLogonIE() As Boolean
'test to autologon into quote website
Dim IE As Object
Dim form0 As Object
Dim document1 As Object
Dim hwnd As Long
Dim oForm As Object
Dim ieClipboard As Object
Dim clipboardContents As String
Static errorStartTime As Date
On Error GoTo ErrorHandler
Set IE = New InternetExplorer
With IE
.Navigate "http://www.alaron.ranweb.com/login/alr.asp"
.Visible = False 'show/hide browser
.Silent = True 'suppress dialog boxes
End With
Call WaitIE(IE) 'wait to load link, ReadyState seems to be set
'to a value other than 4 only when browser is opened
Set form0 = IE.document.frames(1).docu
Set document1 = IE.document.frames(1).docu
form0.elements("Username")
form0.elements("Password")
document1.images("ImageLog
Call WaitIEHTML(IE, "Quote")
Debug.Print "Quote Request Page Loaded, " & "ReadyState: " & CStr(IE.ReadyState)
Set form0 = IE.document.frames(1).docu
form0.elements("O_QC").Val
Application.Wait (Now + TimeValue("0:00:01")) 'don't like Waiting a second here,
'but it's the only way to get the next .Click to work
Debug.Print "Quote Set, " & "ReadyState: " & CStr(IE.ReadyState)
document1.images("QC_G").C
Call WaitIEHTML(IE, "Key:Real-time QuoteDelayed QuoteInvalid Contract") 'wait for this text
Debug.Print "Quote Go Button Clicked, " & "ReadyState: " & CStr(IE.ReadyState)
form0.elements("O_QC").Cli
Debug.Print "Select the right frame button click, " & "ReadyState: " & CStr(IE.ReadyState)
IE.ExecWB OLECMDID_SELECTALL, OLECMDEXECOPT_DODEFAULT
IE.ExecWB OLECMDID_COPY, OLECMDEXECOPT_DODEFAULT
Debug.Print "Quote Page Copied To Clipboard," & "ReadyState: " & CStr(IE.ReadyState)
Set ieClipboard = New DataObject
ieClipboard.GetFromClipboa
clipboardContents = ieClipboard.GetText(1)
'clipboardContents = document1.Selection.create
'clipboardContents = document1.body.innertext ' this also works, but again no delimitors!
Set ieClipboard = Nothing
Set form0 = Nothing
Set document1 = Nothing
Set IE = Nothing
errorStartTime = #12:00:00 AM#
Exit Function
ErrorHandler:
Select Case Err.Number
Case 91 'Object Variable or With Block Not Set (IE DOM error)
If errorStartTime = #12:00:00 AM# Then
errorStartTime = Time
End If
If errorStartTime <> #12:00:00 AM# Then
If Time > TimeSerial(Hour(errorStart
End If
Debug.Print "Ran Error Handler"
DoEvents
Resume
Case Else
Debug.Print CStr(Err.Number) & ": " & Err.Description
End Select
End Function
Private Sub WaitIE(IE As Object)
Do
DoEvents 'wait until IE is done loading page.
Debug.Print "Waiting..."
Loop Until IE.ReadyState = READYSTATE_COMPLETE
End Sub
Private Sub WaitIEHTML(IE As Object, HTMLSearchText As String)
'wait for some specific HTML text to be displayed on the page
Do
DoEvents 'wait until IE is done loading page.
Debug.Print "Waiting IEHTML..."
Loop Until CBool(InStr(1, IE.document.frames(1).docu
End Sub
--------------------------
Output:
.
.
.
Waiting...
Waiting...
.
.
.
Waiting IEHTML...
Quote Request Page Loaded, ReadyState: 4
Quote Set, ReadyState: 4
.
.
.
Waiting IEHTML...
Waiting IEHTML...
Waiting IEHTML...
Quote Go Button Clicked, ReadyState: 4
Select the right frame button click, ReadyState: 4
Quote Page Copied To Clipboard,ReadyState: 4
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I don't quit understand your question. Why you cannot tie up to the event
just declare on the top of your form as
dim WithEvents IE as New InternetExplorer
check with this
http://www.angelfire.com/realm/vb-shared/IEDOM_Tip01.htm
just declare on the top of your form as
dim WithEvents IE as New InternetExplorer
check with this
http://www.angelfire.com/realm/vb-shared/IEDOM_Tip01.htm
I don't think each frame has it's own readystate. I think the entire webpage is treated as one entity. I had the same problem as you, but changed my code to the following, it works fine for me:
Set oIE = New InternetExplorer
oIE.navigate ("http://www.website.com")
Do Until oIE.readyState = READYSTATE_COMPLETE
DoEvents
Loop
Ofcourse if you want to physically see the browser work, you'll have to add oIE.visible = true.
I hope this helps,
tm