Excel-VBA How to access the contentDocumment using WebBrowser - excel

I'm trying to access the document object of a frame with JS using WebBrowser. The code below works perfectly, but I need to use WebBrowser instead.
This is the error I've got:
Run-time error '438'
Object doesn't support this property or method
Any guidance please?
Sub GrabWorkerId1()
Dim objIE As InternetExplorerMedium
Set objIE = New InternetExplorerMedium
objIE.Visible = True
objIE.Navigate "my url"
Do While objIE.Busy = True Or objIE.ReadyState <> 4: DoEvents: Loop
Open "c:\temp\GrabWorkerId2.log" For Output As #3
Write #3, objIE.Document.getElementsbyTagName("iframe")(1).contentDocument.getElementsbyTagName("select")(0).innerhtml
Close 3
Set objIE = Nothing
End Sub

Object doesn't support this property or method
Perhaps the issue is related the Close method and the related method to access the html elements.
First, please try to use F12 developer tools to check whether the website contains the iframe tag and the select element, and check the account. According to your code, the page should contain at least two iframe tag and the iframe content page will contains at least one select element, please verify it. Also, you could add a debugger from the VBA script, and check the innerhtml value, make sure you could get the value.
Second, about the Close method, try to modify the code as below:
Close #3
Besides, please check the following code, I have tested it on my side, it works well (the website contains one iframe tag, and the iframe content page just contains one select element):
Sub GrabWorkerId1()
Dim objIE As Object
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
objIE.Navigate "<website url>"
While objIE.ReadyState <> 4
DoEvents
Wend
Open "d:\temp\test.log" For Output As #3
Write #3, objIE.Document.getElementsbyTagName("iframe")(0).contentDocument.getElementsbyTagName("select")(0).innerhtml
Close #3
Set objIE = Nothing
End Sub

Related

Login to web page and scraping data using VBA

I'm coding a macro that will load a web page, login in it and get the datas from a table.
Thanks to several topics here I've done that:
Sub sail2()
Dim ie As Object
Set ie = New(InternetExplorer.Application")
ie.Visible = True
ie.Navigate "http://pfrwtekref/websail/"
With ie
Dim oLogin As Object, oPassword As Object
Set oLogin = .document.getElementById("txtPwd")(0)
Set oPassword = .document.getElementById("txtPwd")(0)
oLogin.Value = test
oPassword.Value = test
.document.forms(0).submit
End With
End Sub
But I have two type of errors "automation error" if I launch the macro and "error 462 - server not available"
Can anyone help me ?
Thanks for reading and have a good day !
The first issue seems to be that you have a mismatched comma on the third line; however, seeing as you're are complaining about an automation error I think that may be just a typo on this site.
I can't see your internal website so I'm just guessing but I suspect the next issue is that there is no element with ID "txtPwd". You can check to confirm by pressing Ctrl-Shift-C and then selecting the username and password entry boxes.
Finally, depending on how the site is set up your .document.forms(0).submit may not work. You may need to find the ID for the submit button class submit. Below is a function I created a while back for such a task:
Function logIn(userName As String, password As String) As Boolean
'This routine logs into the grade book using given credentials
Dim ie As New InternetExplorer
Dim doc As HTMLDocument
On Error GoTo loginFail
ie.Navigate "[website here]"
'ie.Visible = True
Do While ie.ReadyState <> READYSTATE_COMPLETE Or ie.Busy: DoEvents: Loop 'Wait server to respond
Set doc = ie.Document
doc.getElementsByName("u_name").Item(0).Value = userName 'These may be different for you
doc.getElementsByName("u_pass").Item(0).Value = password
doc.getElementsByClassName("btn").Item(0).Click
Do While ie.ReadyState <> READYSTATE_COMPLETE Or ie.Busy: DoEvents: Loop 'Wait server to respond
Set doc = ie.Document
'Add a check to confirm you aren't on the same page
ie.Quit
Set ie = Nothing
LogIn = True
Exit Function
loginFail:
MsgBox "There was an issue logging in. Please try again."
logIntoGradeBook = False
End Function
Note that the site I was dealing with was set up poorly and so I needed to switch to GetElementsByName and GetElementsByClassName to get access to what I needed. You may be fine with IDs.
Why don't you try to use the Excel PowerQuery to get your data from the tables you need? When your desired columns are done, you just click in close and load, select data model e now you can use a macro to perform a PivotTable whenever you load the document or just use a PivotTable and the data will be refreshed when you use the refresh data in data ribbon.

IE click on a button that has no link associated to it (using Excel VBA)

I want to click on a "button" on a web page, but my problem is that this button doesn't seem to have link attach to it. By the way I'm phrasing this you can see I'm not familiar at all with the language of web browser.
Anyway I most use internet explorer and here's the code I have so far
Sub click_button_no_hlink()
Dim i As Long
Dim IE As Object
Dim Doc As Object
Dim objElement As Object
Dim objCollection As Object
Set IE = CreateObject("InternetExplorer.Application") 'create IE instance
IE.Visible = True
IE.Navigate "https://apex.xyz.qc.ca/apex/prd1/f?p=135:LOGIN_DESKTOP::::::" ' Adress of web page
Do While IE.Busy 'loading page
Application.Wait DateAdd("s", 1, Now)
Loop
'-------------Usually I would do something like that and it would works well.-----------------
Set link = IE.document.getElementsByTagName("a")
For Each l In link
a = l.innerText
If l.innerText = "Créer" Then '
l.Click
Exit For
End If
Next
'-------------That method works fine on other type of hlink to the page by the way------------
'-----------------------I also tried various methods around this with no luck------------------------------
Set objCollection = IE.document.getElementsByClassName("rc-content-buttons") 'recherche du bouton "Créer"
'---------------------------------
'--------------------or this also doesn't work-------------------------------
For Each btn In IE.document.getElementsByClassName("rc-content-buttons")
If btn.getAttribute("id") = "B91938241817236808" Then
btn.Click
Exit For
End If
Next btn
End Sub
For sake of clarity here's the code of the web page around the "button" I'm trying to interact with.
I've made many research but I'm in a dead end right now. Any help will be greatly appreciate.
Tx in advance.
SOLVED FINAL CODE: With help from DOMENIC and QHARR and Yu Zhou
Sub click_button_no_hlink()
Dim i As Long
Dim IE As Object
Dim Doc As Object
Dim objElement As Object
Dim objCollection As Object
Set IE = CreateObject("InternetExplorer.Application") 'create IE instance
IE.Visible = True
IE.Navigate "https://apex.xyz.qc.ca/apex/prd1/f?p=135:LOGIN_DESKTOP::::::" ' Adress of web page
While IE.Busy: DoEvents: Wend 'loading page
IE.document.querySelector("[value='Créer']").FireEvent "onclick" 'works like a charm
' IE.document.querySelector("div.rc-content-buttons input").Click
'also works but speaks less by itself when reading code
' IE.document.getElementById("B91938241817236808").Click
'also works
End Sub
It is within an input not a tag element so gathering a tags will not capture what you want. Using the id, as suggested in comments is one way to go. If you get element not found then check whether your element is within a parent frame or iframe which needs to be negotiated. General syntax for that is
ie.document.getElementsByTagName("frame")(appropriateIndexHere).contentDocument.getElementById("B91938241817236808")
ie.document.getElementsByTagName("iframe")(appropriateIndexHere).contentDocument.getElementById("B91938241817236808")
If the id is dynamic you can use the value attribute
ie.document.querySelector("[value='Créer']")
ie.document.getElementsByTagName("frame")(appropriateIndexHere).contentDocument.querySelector("[value='Créer']") 'etc
As there is an event, you may need to fire it.
ie.document.querySelector("[value='Créer']").FireEvent "onclick"
ie.document.getElementsByTagName("frame")(appropriateIndexHere).contentDocument.querySelector("[value='Créer']").FireEvent "onclick" 'etc
And use a proper page load wait. So this,
Do While IE.Busy 'loading page
Application.Wait DateAdd("s", 1, Now)
Loop
Should be
While ie.Busy Or ie.ReadyState <> 4: DoEvents:Wend
getElementsByClassName returns an array-like object of all child elements which have all of the given class names, so I think it should be IE.document.getElementsByClassName("rc-content-buttons")(0).Click if it is the first element with the classname.
You could also try: IE.document.querySelector("div.rc-content-buttons input").Click.
And I think IE.document.getElementById("B91938241817236808").Click is also right.

getElementById won't work in VBA, error 438

I am relatively new at VBA (I know the basics, but not much else) and I am trying to get some code set up that will fill out online forms for me, but when I run my code I get a 438 error:
object doesnt support this property or method
when it gets to
ie.document.getElementById ("q")
I have added the HTML object library and Microsoft internet controls to my references. I have looked at tons of online forums. I have even copied and pasted an entire script directly into VBA. Nothing will make it use getElementById(). Here is my code:
Sub internetstuff()
Dim ie As Object
Set ie = CreateObject("internetexplorer.application")
ie.Visible = True
ie.navigate ("https://www.google.com/")
Set searchbx = ie.document.getElementById("q")
searchbx.Value = "Howdy!"
End Sub
What should happen is that it should open InternetExplorer, go to Google, and populate the search bar with "Howdy!".
Instead, It only opens google, then I get the error message and it stops running.
Because "q" is not an ID, it's a Name.
You have to use GetElementsByName and select the 1st Element
try this:
Sub internetstuff()
Dim ie As Object
Set ie = CreateObject("internetexplorer.application")
ie.Visible = True
ie.Navigate ("https://www.google.com/")
Do Until ie.ReadyState >= 4
DoEvents
Loop
Set searchbx = ie.document.getElementsByName("q")(0)
searchbx.Value = "Howdy!"
End Sub
I have also added a waiting Event, in case it takes time to load Google.
Result:
A more concise and efficient way is to use querySelector to return first match for the name attribute
Option Explicit
Public Sub internetstuff()
Dim ie As Object
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.Navigate2 "https://www.google.com/"
While .Busy Or .readyState < 4: DoEvents: Wend
.document.querySelector("[name=q]").Value = "Howdy"
Stop '<delete me later
.Quit
End With
End Sub

VBA in Excel - Internet Explorer download XML - Save As Dialog

I am downloading Climate XML data into Excel 2013. I need to automate the process and I can navigate immediately to the correct page preloaded with the correct parameters. I can click on the OK button but then the Internet Explorer - Open/Save/Cancel dialogue box comes up.
I have tried various option in Windows 7 to trap the Windows event 32770 (??) but am I unsure how to code this. I just want to save the file as c:\temp.xml.
I don't want to use the SendKeys method as it is too unreliable. Can anyone suggest a way to handle the dialog ?
Dim htm As Object
Dim IE As Object
Dim Doc As Object
Set IE = CreateObject("internetexplorer.application")
IE.Visible = True
IE.navigate "http://ec.europa.eu/environment/ets/exportEntry.do?form=transaction&destinationAccountHolder=&startDate=01%2F06%2F2009&destinationRegistry=-1&originatingAccountType=-1&endDate=01%2F05%2F2010&transactionID=&suppTransactionType=-1&originatingAccountHolder=&transactionType=-1&languageCode=en&destinationAccountNumber=&destinationAccountType=-1&toCompletionDate=&originatingRegistry=-1&destinationAccountIdentifier=&fromCompletionDate=&originatingAccountIdentifier=&transactionStatus=4&originatingAccountNumber=8&currentSortSettings="
Do While IE.readystate <> 4: DoEvents: Loop
Set Doc = CreateObject("htmlfile")
Set Doc = IE.document
Doc.getelementbyID("btnOK").Click
Set IE = Nothing

Controlling Internet Explorer local intranet using Excel VBA

I am using Excel VBA code to click a button on our website. I know this isn't the best of things to be doing, but it is the least objectionable option available to me.
I can using this code, successfully load imdb.com, google, etc. But when I load our local site, I lose control of the ie object, I can't check readyState, I can't Quit.
Here is the error I get.
Run-time error '-2147023179 (800706b5)':
Automation error
The interface is unknown
Every so often I instead get this message:
Run-time error '-2147417848 (80010108)':
Automation error
The object invoked has disconnected from its clients.
Clicking Debug indicates the ie.readyState, I commented that out and then it points to ie.Quit
Sub dothestuff()
Dim ie As InternetExplorer
Set ie = New InternetExplorer
ie.Visible = True
ie.Navigate "http://www.google.com/"
anerror = webload(ie)
ie.Quit
Set ie = Nothing
End Sub
Function webload(ie)
Do Until ie.ReadyState = READYSTATE_COMPLETE
DoEvents
Loop
End Function
Here is a quick and easy solution for this issue:
Instead of:
set IE = createobject("internetexplorer.application")
Use:
Set IE = New InternetExplorerMedium
No need to tweak the IE settings
Here's what's happening. When your browser internally "jumps" to a different security zone - from say a local address to an inTRAnet address or to an inTERnet address - IE closes/drops the current process of IE and opens another one with tighter security. The old and new IE processes are IE child processes to the parent IE task so you don't see it happen either by watching the browser or watching the process in Task Manager. If you use Process Explorer (free from Microsoft), you can see this happen.
What you need to do in this type of environment is use Anup Upadhyay's solution above. His code snippet looks at all IE tasks (parent and child doesn't make a difference) and finds the new IE process that is pointing to the web address that the original process was given. As long as you don't have multiple browsers open to the same address, it will find the new process reliably and carry on like you would expect it to.
Note: You might also need to use the InternetExplorerMedium object as opposed to the InternetExplorer object. It is also better at "holding on" to a session.
Here's my version which is almost the same thing as Anup's.
References for MS Office VBA:
Microsoft Internet Controls
Microsoft Shell Controls and Automation
n
Dim IE As InternetExplorerMedium ' This object (the "medium" variety as opposed to "InternetExplorer") is necessary in our security climate
Dim targetURL As String
Dim webContent As String
Dim sh
Dim eachIE
targetURL = "[your URL here]"
Set IE = New InternetExplorerMedium
IE.Visible = False ' Set to true to watch what's happening
IE.Navigate targetURL
While IE.Busy
DoEvents
Wend
Do
Set sh = New Shell32.Shell
For Each eachIE In sh.Windows
If InStr(1, eachIE.LocationURL, targetURL) Then
Set IE = eachIE
'IE.Visible = False 'This is here because in some environments, the new process defaults to Visible.
Exit Do
End If
Next eachIE
Loop
Set eachIE = Nothing
Set sh = Nothing
While IE.Busy ' The new process may still be busy even after you find it
DoEvents
Wend
Try this one:
Set IE = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")
We had this problem using IE9. It arises because of security settings. There is a setting called "Enable Protected Mode" on the "Security" tab of the "Internet Options" dialog box (tools...internet options). Each "zone" can have a different setting for "enable protected mode" We unchecked "enable protected mode" and this solved our problem. I think what is happening is that when switch to a zone that is in protected mode, IE starts a new process to handle traffic in that zone (maybe killing the old process). When this happens your IE object variable in VBA gets disconnected from Internet Explorer.
Alright, just found a solution, decided out of desperation to try loading 127.0.0.1 instead of localhost, sure enough, no problems, so resolved the ip address of the local intranet server, and now I am good to go.
I don't really understand why, but this has solved my issue.
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
IE.Navigate "C:\abc.html"
'We are getting error here , I have found a small tricky alternate solution for this as below
'Take reference for Microsoft Shell Controls And Automation
'Use below code to reassign IE object for the lost connection issue
Dim sh
Dim eachIE
Do
Set sh = New Shell32.Shell
For Each eachIE In sh.Windows
' Check if this is the desired URL
' Here you can use your condition except .html
' If you want to use your URL , then put the URL below in the code for condition check.
' This code will reassign your IE object with the same reference for navigation and your issue will resolve.
'
If InStr(1, eachIE.locationurl, ".html") Then
Set IE = eachIE
Exit Do
End If
Next eachIE
Loop
For me, the following worked:
Open Internet explorer
Go to tools
Goto Internet options
Switch to Security tab
Click Trusted sites
Click sites
You will see the site url, select it
Click Remove
Click close, apply and Ok
Ps. I tested these steps on IE 8 browser.
Maybe you're having a problem with binding? That's a strange error to get for this.
Try this code (adapted from http://www.excely.com/excel-vba/ie-automation.shtml). Hopefully it helps:
Option Explicit
' lasts for the life of Excel being open
Dim ie As Object
Sub dothestuff()
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.Navigate "http://www.google.com/"
Do While ie.Busy
DoEvents
Loop
ie.Quit
Set ie = Nothing
End Sub
I am having the exact same issue working with a website that is inside our company intranet and is also included in my trusted sites. Disabling protected mode allows me to check ReadyState, but only if I disable for the internet zone in addition to intranet and trusted sites.
Why would enabling protected mode for the internet zone cause the automation error when checking ReadyState on a trusted site? Is there a way around this without disabling protected mode for the internet zone?
Another solution..
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate ("http://URLOnMyIntranet/site.html")
IE.Visible = True
Set IE = nothing
Set objShellApp = CreateObject("Shell.Application")
For Each objWindow In objShellApp.Windows
Debug.Print objWindow.LocationName
If LCase(objWindow.LocationName) = LCase("Your windows name, use debug to find out") Then
Set IE = objWindow
End If
Next
Note, using InternetExplorerMedium (see other answers) usually all you need, FYI also you could use Url property obj.LocationURL instead of window name which would be more accurate. See other answers.
Dim IE As InternetExplorer
Set IE = New InternetExplorerMedium
IE.Navigate "yousite.org"
IE.Visible = True
Do While IE.Busy
DoEvents
Loop
Set HTML = IE.document
Do
var8 = HTML.DocumentElement.innerHTML
v3 = var8
v4 = InStrRev(v3, "the class or ID you are looking for when the _
page final loads", -1)
Loop While v4 = 0
Do While IE.Busy
DoEvents
Loop
'Your in the new page look for elements and click rinse and repeat
'the Do loop. This method works with my intranet corporate site

Resources