I need to navigate to a page using VBA. I created the code bellow and it worked just fine until I reinstalled Windows. I don't know if this is the cause, but it is not working anymore.
There are tho cases:
If I'm not logged in before running the macro
The first part, for logging onto the page is working, but when I try to navigate to "http://cltd.ro/catalogsearch/result/?q=60041", I get an error "Method 'Navigate' of object 'IWebBrowser 2' failed".
If I'm already logged on to the site
On the other hand, if I'm already logged in before running the macro, the code is working and I get to the desired page, but the code gets stuccked in to the loop "Do/DoEvents/Loop Until ie.readystate = 4" forever and I cannot continue
Please help!
Thanks!
Sub xx()
Dim ie As Object
Set ie = CreateObject("internetexplorer.application")
ie.Visible = True
AppActivate ie
apiShowWindow ie.hwnd, 3
ie.Visible = True
ie.navigate "http://cltd.ro/customer/account/login/"
Do
DoEvents
Loop Until ie.readystate = 4
On Error Resume Next 'in case I'm already loggen in
Call ie.Document.getElementById("email").setattribute("value", "dfgsdfg") 'not real value ;-)
Call ie.Document.getElementById("pass").setattribute("value", "dfgsdfg") 'not real value ;-)
Call ie.Document.getElementById("send2").Click
Do
DoEvents
Loop Until ie.readystate = 4
On Error GoTo 0 'cancels the resume next
Application.Wait (Now() + TimeValue("0:00:02"))
link = "http://cltd.ro/catalogsearch/resuilt/?q=60041"
ie.navigate link
Do
DoEvents
Loop Until ie.readystate = 4
'Other lines of code ...............
End Sub
This doesn't answer your actual question, but:
(1) You should always have a timeout in your "wait until document ready" loops. Otherwise, those loops can wait forever if the page does not go ready. In fact when I tried navigating manually (via the IE URL bar) to "http://cltd.ro/customer/account/login/", it sat there spinning for quite some time, until I gave up and hit stop. Your code should detect cases where the document takes too ling to go ready, and reply with something like "Website hasn't responded for 60 seconds, do you want to keep waiting? [yes] [No]".
(2) You don't allow for the case where the page does go ready, but it's not the page you wanted. For example, if the website returns an error, or IE decides to time it out, you'll get a page with a URL of the form "res://..." - not the page you actually asked for. You can't just assume that you actually got the right page.
So your existing code is ok for a 1-off script, but not sufficiently robust for proper production use.
Related
First I'm very new to trying to automate IE via Excel VBA.
That being said, I'm working to automate a login to a company-specific webpage (only accessible to our employees). The goal is to automate the login (employee number, password and click Login). I find Firefox to be particularly helpful in identifying fields so that's what I'm using in the screenshot.
I found some code online to navigate to a webpage and enter something into a search box. I've modified that as follows (the included link is not real).
Finally to the issue. If I enter a webpage like www.google.com for example, all will execute fine. But when I change to my company link, the code freezes at the Do While and I get the error shown. So my question is why it works for a general webpage but not for my company specific one? If I comment-out that line, I still get the disconnected error when debugging. Assuming that issue is an easy one to resolve, have I also properly identified the field?
Hopefully I've included enough info for you. If not, please let me know what else may be required. Thanks in advance for your help!
Error
'start a new subroutine called SearchBot
Sub SearchBot()
'dimension (declare or set aside memory for) our variables
Dim objIE As InternetExplorer 'special object variable representing the IE browser
'initiating a new instance of Internet Explorer and asigning it to objIE
Set objIE = New InternetExplorer
'make IE browser visible (False would allow IE to run in the background)
objIE.Visible = True
'navigate IE to this web page (a pretty neat search engine really)
objIE.navigate "http://sampletext.asp"
'wait here a few seconds while the browser is busy
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
'enter value in the employee number box
objIE.document.getElementByName("txtEmployeeNum").Value = "123456"
Employee Number
Correct name of the method is getElementsByName.
You also want to operate on element of collection returned by this method, not whole collection. Using (0) index will allow to work on 1st element of collection.
Change:
objIE.document.getElementByName("txtEmployeeNum").Value = "123456"
to:
objIE.document.getElementsByName("txtEmployeeNum")(0).Value = "123456"
With such corrected code, you should step through code with F8 in VB Editor. For example by hovering over, see if objIE.Busy ever gets FALSE and especially if objIE.readyState ever reaches 4 - if only 3, try objIE.readyState < 3 instead.
EDIT:
Try replacing:
Dim objIE As InternetExplorer
Set objIE = New InternetExplorer
with:
Dim objIE As Object
Set objIE = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")
You may also need to change objIE.Navigate with objIE.Navigate2
My macro uses Internet Explorer to open PeopleSoft Financials and then run a public query. It has been working for a long time until recently. I'm aware of an update to Internet Explorer on our machines in early July and am wondering if that has caused this issue.
The macro is throwing an "Object has disconnected from its clients" error message.
Here is how the variable for Internet Explorer is defined:
Public ExpApp As InternetExplorer
Here is the code where the error is thown:
Set ExpApp = CreateObject("InternetExplorer.Application")
ExpApp.Visible = True
ExpApp.navigate vLogin
Do Until ExpApp.readyState = READYSTATE_COMPLETE ' ERROR IS THROWN HERE
MyTimer
Loop
Do Until ExpApp.document.Title <> "PeopleSoft 8 Sign-in"
MyTimer
Loop
Do Until ExpApp.readyState = READYSTATE_COMPLETE
MyTimer
Loop
vLogin is a string with the URL to the PeopleSoft login screen
MyTimer is a little function that waits 1 second each time it is kicked off
This macro has been around a while so I imagine that this is pretty old code. I'm hoping there are a few minor changes I could make instead of re-writing this macro.
Any suggestions would be greatly appreciated. Thanks for the help......
I have a simple VBA code (see below), that goes to a webpage, selects some value, clicks the “Begin download” button, and then saves the file. The problem is I am stuck at the “clicking the download button” part. Can someone help?
Here is the code:
Sub Treasury_Auc_Notes()
Dim IE As Object
Set IE = Nothing
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "http://www.treasurydirect.gov/RI/OFAuctions?form=ndnld&typesec=notes"
While IE.Busy
DoEvents
Wend
IE.Document.All.Item("begYr").Value = "2012"
With IE.Document.getElementsByName("cols")
.Item(0).Checked = True
End With
'Click "Begin download" button (this is where I am stuck)
'Choose Save Open or Cancel (I haven’t got to this part yet)
ActiveWorkbook.SaveAs Filename
End Sub
This one's tricky, and due to restrictive security on my laptop, I'm not able to verify this 100%, but try:
While IE.ReadyState <> 4
DoEvents
Wend
IE.Document.All.Item("begYr").Value = "2012"
With IE.Document.getElementsByName("cols")
.Item(0).Checked = True
End With
Dim ele As Object
For Each ele In IE.Document.Forms
If ele.Action = "/RI/OFAuctions" Then
ele.Submit
Exit For
End If
Next
You may have to use SendKeys (I think Application.SendKeys "o") method to open the file then use VBA to save the ActiveWorkbook to the desired location. I'm not able to test SendKeys for reasons mentioned below.
Or, I'm pretty sure there is a WinAPI functions that can do this more reliably than SendKeys. You'll need to get the hWnd of the Save dialog and do some other stuff to force it to open/save. This is fairly advanced VBA that I probably have a reference to somewhere, but rarely need to use it. If you have trouble with this particular part, I would urge you to ask a separate question "How to get the hWnd of File Save dialog and download file from IE" or something like that.
NOTE: I can't test the SendKeys method. When I use the above code, I am fairly certain the file is being downloaded, but it is going to a temporary folder that is hidden, and difficult to find. In any case, it does appear to be downloading with some manual intervention. I get this warning:
I click to ignore that (I have no idea how to automate this part, I'm just trying to validate that the form .Submit method actually worked), and after some creative searching (temporary internet files get dumped in a strange/hidden folder usually) I verify the file is downloaded, although it is showing as a TXT extension instead of CSV.
If instead of using VBA, I click on the button manually, and I choose to "open" the file opens as CSV and has the same path to that temporary internet location.
I am writing a macro that will scrape my company's internal SAP site for vendor information. For several reasons I have to use VBA to do so. However, I cannot figure out why I keep getting these three errors when I attempt to scrape the page. Is it possible that this has something to do with the UAC integrity model? Or is there something wrong with my code? Is it possible for a webpage using http can be handled differently in internet explorer? I am able to go to any webpage, even other internal webpages, and can scrape each of those just fine. But when i attempt to scrape the SAP page, i get these errors. The error descriptions and when they occur are:
800706B5 - The interface is unknown (occurs when I place breakpoints before running the offending code)
80004005 - Unspecified error (occurs when I don't place any errors and just let the macro run)
80010108 - The Object invoked has disconnected from its clients. (I can't seem to get a consistent occurrence of this error, it seems to happen around the time that something in excel is so corrupted that no page will load and i have to reinstall excel)
I have absolutely no idea what is going on. The Integrity page didn't make much sense to me, and all the research I found on this talked about connecting to databases and using ADO and COM references. However I am doing everything through Internet Explorer. Here is my relevant code below:
Private Sub runTest_Click()
ie.visible = True
doScrape
End Sub
'The code to run the module
Private Sub doTest()
Dim result As String
result = PageScraper.scrapeSAPPage("<some num>")
End Sub
PageScraper Module
Public Function scrapeSAPPage(num As Long) As String
'Predefined URL that appends num onto end to navigate to specific record in SAP
Dim url As String: url = "<url here>"
Dim ie as InternetExplorer
set ie = CreateObject("internetexplorer.application")
Dim doc as HTMLDocument
ie.navigate url 'Will always sucessfully open page, regardless of SAP or other
'pauses the exection of the code until the webpage has loaded
Do
'Will always fail on next line when attempting SAP site with error
If Not ie.Busy And ie.ReadyState = 4 Then
Application.Wait (Now + TimeValue("00:00:01"))
If Not ie.Busy And ie.ReadyState = 4 Then
Exit Do
End If
End If
DoEvents
Loop
Set doc = ie.document 'After implementation of Tim Williams changes, breaks here
'Scraping code here, not relevant
End Function
I am using IE9 and Excel 2010 on a Windows 7 machine. Any help or insight you can provide would be greatly appreciated. Thank you.
I do this type of scraping frequently and have found it very difficult to make IE automation work 100% reliably with errors like those you have found. As they are often timing issues it can be very frustrating to debug as they don't appear when you step through, only during live runs To minimize the errors I do the following:
Introduce more delays; ie.busy and ie.ReadyState don't necessarily give valid answers IMMEDIATELY after an ie.navigate, so introduce a short delay after ie.navigate. For things I'm loading 1 to 2 seconds normally but anything over 500ms seems to work.
Make sure IE is in a clean state by going ie.navigate "about:blank" before going to the target url.
After that you should have a valid IE object and you'll have to look at it to see what you've got inside. Generally I avoid trying to access the entire ie.document and instead use IE.document.all.tags("x") where 'x' is a suitable thing I'm looking for such as td or a.
However after all these improvements although they have increased my success rate I still have errors at random.
My real solution has been to abandon IE and instead do my work using xmlhttp.
If you are parsing out your data using text operations on the document then it will be a no-brainer to swap over. The xmlhttp object is MUCH more reliable. and you just get the "responsetext" to access the entire html of the document.
Here is a simplified version of what I'm using in production now for scraping, it's so reliable it runs overnight generating millions of rows without error.
Public Sub Main()
Dim obj As MSXML2.ServerXMLHTTP
Dim strData As String
Dim errCount As Integer
' create an xmlhttp object - you will need to reference to the MS XML HTTP library, any version will do
' but I'm using Microsoft XML, v6.0 (c:\windows\system32\msxml6.dll)
Set obj = New MSXML2.ServerXMLHTTP
' Get the url - I set the last param to Async=true so that it returns right away then lets me wait in
' code rather than trust it, but on an internal network "false" might be better for you.
obj.Open "GET", "http://www.google.com", True
obj.send ' this line actually does the HTTP GET
' Wait for a completion up to 10 seconds
errCount = 0
While obj.readyState < 4 And errCount < 10
DoEvents
obj.waitForResponse 1 ' this is an up-to-one-second delay
errCount = errCount + 1
Wend
If obj.readyState = 4 Then ' I do these on two
If obj.Status = 200 Then ' different lines to avoid certain error cases
strData = obj.responseText
End If
End If
obj.abort ' in real code I use some on error resume next, so at this point it is possible I have a failed
' get and so best to abort it before I try again
Debug.Print strData
End Sub
Hope that helps.
I have a vbscript using the InternetExplorer object to navigate to a few pages and passing data to those pages. Recently since patching IE8 I've noticed that something is causing the creation of zombie iexplore.exe processes. While running my script and watching the process list in task manager I noticed that when my script creates the InternetExplorer.Application object, two processes appear in the process list. Is this normal behavior? Why does this happen? I'm wondering because even though during my testing it appears both of these processes get killed when I call the InternetExplorer object's quit method, I still suspect that these multiple processes are the root cause of the zombies.
Here is some sample code:
Set ie = CreateObject("InternetExplorer.Application")
ie.Navigate2 "Address"
ie.AddressBar = 1
ie.Toolbar = 1
ie.StatusBar = 1
ie.Width = 600
ie.Height = 400
ie.Left = 300
ie.Top = 150
ie.Visible = 1
Do While ie.Busy
WScript.Sleep 1
Loop
ie.Navigate2 "Address?variable=value"
Do While ie.Busy
WScript.Sleep 1
Loop
...rest of code...
ie.Quit
Set ie = Nothing
I would guess that IE is putting the tab and the browser window in separate processes.
I have a similar issue when using createobject to start MsAccess. Two processes appear in the task list and both go away with the quit command.
However if some problem occurs during the session that causes my program to crash only one of the processes gets shutdown.
This must be some Microsoft system feature.