javascript not working wen invoking IE using VBA - vba

I am trying to click on a dropdown Options list via VBA programmatically. But the selection of the option works but the JavaScript associated to the click doesn't work.
I tried the both options - .click & .focus.
But both these doesn't invoke the associated javascript.
See below the code
Set ElementCol = appIE.Document.getElementsByTagName("option")
For Each obj In ElementCol
If obj.innerHTML = "abc" Then
obj.Selected = True
obj.Focus
obj.click
Exit For
End If
Next obj
in IE it's:
<select>
<option value="abc">abc </option>
<option value="def">def</option>
</select>

How about this:
Sub DOM_SetSelect()
Dim oIE As Object
Dim oBody As Variant
Dim oSelect As Variant
Set oIE = CreateObject("InternetExplorer.Application")
oIE.Visible = True
oIE.Navigate ("http://www.tizag.com/htmlT/htmlselect.php")
While oIE.ReadyState <> 4
DoEvents
Wend
Set oBody = oIE.Document.body
Set oSelect = oBody.GetElementsByTagName("select")(0)
oSelect.selectedindex = 2
End Sub
If you want to set by value, then use
oSelect.value = "CA" 'in the demo website that I've added

FireEvent is used to trigger the javascript event attached to any element.
Try this
obj.FireEvent("onclick")
You may even try this
obj.execScript "onclick()", "JavaScript"

Related

Object variable or block variable not set when processing HTMLSelectElement

I'm trying to run the below user defined function, but I receive the following error:
object variable or with block variable not set
Private Function Find_Select_Option(selectElement As HTMLSelectElement, optionText As String) As Integer
Dim i As Integer
Find_Select_Option = -1
i = 0
While i < selectElement.Options.length And Find_Select_Option = -1 ' ### error occurs on this line
DoEvents
If LCase(Trim(selectElement.Item(i).Text)) = LCase(Trim(optionText)) Then Find_Select_Option = i
i = i + 1
Wend
End Function
I have attached the VBA code below (source). Please go through it and let me know, what's wrong in this code.
Public Sub IE1()
Dim URL As String
Dim IE As InternetExplorer
Dim HTMLdoc As HTMLDocument
URL = "http://douglasne.mapping-online.com/DouglasCoNe/static/valuation.jsp"
Set IE = New InternetExplorer
With IE
.Visible = True
.navigate URL
While .Busy Or .readyState <> READYSTATE_COMPLETE
DoEvents
Wend
Set HTMLdoc = .document
End With
'<select name="StreetDir">
Dim optionIndex As Integer
Dim dirSelect As HTMLSelectElement
Set dirSelect = HTMLdoc.getElementsByName("StreetDir")(0)
'dirSelect.selectedIndex = 2 'set option index directly
optionIndex = Find_Select_Option(dirSelect, "E")
If optionIndex >= 0 Then
dirSelect.selectedIndex = optionIndex
End If
'<select name="StreetSfx">
Dim suffixSelect As HTMLSelectElement
Set suffixSelect = HTMLdoc.getElementsByName("StreetSfx")(0)
optionIndex = Find_Select_Option(suffixSelect, "PLAZA")
If optionIndex >= 0 Then
suffixSelect.selectedIndex = optionIndex
End If
End Sub
How can I fix this?
When I was poking around I also saw the OzGrid post you're pulling from. The problem is that the test URL, http://douglasne.mapping-online.com/DouglasCoNe/static/valuation.jsp, no longer has the elements you are looking for! For example, it does not have <select name="StreetDir">. So dirSelect is Nothing at the time you call Find_Select_Option.
I recommend testing with a local file. For example, create c:\users\prashant\foo.htm (or wherever you want to put it) with the following contents (modified from w3schools):
<!DOCTYPE html>
<html>
<body>
<select name="Car">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
</body>
</html>
Then the following code should work (it does for me):
Public Sub IE1()
Dim URL As String
Dim IE As SHDocVw.InternetExplorer
Dim HTMLdoc As MSHTML.HTMLDocument
URL = "c:\users\prashant\foo.htm" ' *** Read from a local file
Set IE = New InternetExplorer
With IE
.Visible = True
.navigate URL
While .Busy Or .ReadyState <> READYSTATE_COMPLETE
DoEvents
Wend
Set HTMLdoc = .document
End With
'<select name="Car">
Dim optionIndex As Integer
Dim dirSelect As HTMLSelectElement
Dim message As String
Set dirSelect = Nothing ' *** Set up for the error checking below
On Error Resume Next
'Set dirSelect = HTMLdoc.getElementsByTagName("select").Item(0) ' This is OK, too
Set dirSelect = HTMLdoc.getElementsByName("Car").Item(0) ' *** It exists!
' *** Here's some error-checking code you can use
If Err.Number <> 0 Then ' Report errors
message = "Error " & CStr(Err.Number) & vbCrLf & Err.Description
ElseIf dirSelect Is Nothing Then
message = "No element found"
Else
message = "OK" & vbCrLf & dirSelect.textContent
End If
On Error GoTo 0 ' *** Back to normal
MsgBox message
End Sub
When the parameter to getElementsByName is "Car", I get an OK response. When I change that parameter to "Nonexistent", I get No element found. This confirms that dirSelect is Nothing in your code at the point you call Find_Select_Option.

Using VBA to click a button

I am trying to pull information from a website, but cannot for the life of me figure out how to click the button. I've got the code to input the information. This is the html for the website . Any help would be appreciated.
<p role="button" tabindex="0" class="fmtbutton" onkeypress="finddistancebetweenaandb(document.forms['inp']['pointa'].value,document.forms['inp']['pointb'].value);" onclick="finddistancebetweenaandb(document.forms['inp']['pointa'].value,document.forms['inp']['pointb'].value);"> Show </p>
Here is the full code that I have so far.
Sub RoundedRectangle1_Click()
Dim eRow As Long
Dim ele As Object
Dim objIE As Object
Set objIE = CreateObject("InternetExplorer.Application")
FranchiseAddress = Range("B2").Value
Movefrom = Range("B3").Value
moveto = Range("B4").Value
With objIE
.Visible = True
.navigate "https://www.freemaptools.com/how-far-is-it-between.htm"
Do While .Busy Or _
.readyState <> 4
DoEvents
Loop
Set d = .Document.getElementsByName("onoffswitch")
d.Item(0).Click
Set f = .Document.getElementsByName("pointa")
f.Item(0).Value = FranchiseAddress
Set a = .Document.getElementsByName("pointb")
a.Item(0).Value = Movefrom
' This is where I'm Stuck'
End With
End Sub
I have tried multiple solutions found on this site for many questions, but none of them seem to work.
Thank you.
add this to your code
Dim aaa As Object
Set aaa = .Document.getElementsByClassName("fmtbutton") ' this returns 4 objects, your button is the first one
aaa(0).Click
You can be a little more elegant and target the attribute with a CSS selector:
.document.querySelector("[role=button]").Click
The attribute = value selector, [role=button], looks for an element with attribute role whose value is button. There is only one on the page so no loop needed.

VBA code not selecting a value from a dropdown that has a class but no id

I have some code which is meant to open an IE page and fill in the first drop-down to show "caravan". However my code is not selecting caravan from the drop-down.
The website is:
https://insurance.qbe.com.au/portal/caravan/form/estimate
When I right-click to inspect the source code of the drop-down I get directed to the following:
When I expand the source code below this, I see the following:
As you can see, the values associated with the drop-down are well below the source code I was initially directed to.
Here is the code I've been using to try and select 'caravan':
Sub GetQuote()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.navigate ("https://insurance.qbe.com.au/portal/caravan/form/estimate")
IE.Visible = True
Do
DoEvents
Loop Until IE.readystate = 4
Dim lists, l
Set lists = IE.document.getElementsByTagName("select")(0)
For Each l In lists
If InStr(1, l.className, "form-control ng-pristine ng-untouched ng-valid", 1) Then
l.SelectedIndex = 0
End If
Next
Application.Wait (Now + TimeValue("00:00:03"))
End Sub
With the above code I was trying to select 'caravan' by referencing the very last bit of the source code I pasted above (i.e. by getting all select tags and then checking all items within the tag until an item whose class name contains "form-control ng-pristine ng-untouched ng-valid" is found, and then selecting index 0 for the value associated with this item. And this obviously didn't work - so here's other code I have tried, again with no luck (it's a slight modification of the code above, by simply referencing the source code that I was initially directed to when I inspected the drop-down, and that would be the very first source code I pasted):
For Each l In lists
If InStr(1, l.className, "ui-select-search ui-select-toggle ng-pristine ng-valid ng-touched", 1) Then
l.SelectedIndex = 0
Does this offer any help, not sure if it's your solution, but added here for formatting.
Sub test()
Dim ie As SHDocVw.InternetExplorer
Dim htmlDoc As MSHTML.HTMLDocument
Dim inputCollection As MSHTML.IHTMLElementCollection
Dim inputElement As MSHTML.HTMLInputElement
Set ie = New SHDocVw.InternetExplorer
ie.navigate ("https://insurance.qbe.com.au/portal/caravan/form/estimate")
Do While ie.Busy Or ie.readyState <> READYSTATE_COMPLETE
DoEvents
Loop
ie.Visible = 1
Set htmlDoc = ie.document
Set inputCollection = htmlDoc.getElementsByTagName("INput")
For Each inputElement In inputCollection
Debug.Print inputElement.className
Next inputElement
' or like this
Set inputElement = htmlDoc.getElementsByClassName("ui-select-search ui-select-toggle ng-pristine ng-valid ng-touched")(0)
End Sub

VBA - Addressing Internet Explorer tabs

Strangely enough I didn't find any information on the topic and I'm currently stuck at the point where I managed to open a new tab in an instance of IE by programmatically clicking a button, but I haven't the faintest clue of how to address the new tab in order to get information from there (the button basically brings up a new tab with the result of a search).
This is basically a straightforward question, but I'm including my code anyway:
Sub AddInfoFromIntranet()
Dim Ie As SHDocVw.InternetExplorer
Dim URL As String
Dim iFrames As MSHTML.IHTMLElementCollection
Dim iFrame As MSHTML.HTMLFrameElement
Dim Doc As MSHTML.HTMLDocument
Dim InputBox As MSHTML.IHTMLElementCollection, htmlButton, allTags, Tag
' Opens Intranet - yeah, sadly it's not a public web page
URL = "{My intranet website}"
Set Ie = New SHDocVw.InternetExplorer
With Ie
.navigate URL
.Visible = True
While .Busy Or .readyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set Doc = .document
End With
' Gets top_window frame and navigates to it, then inserts the name to search
Set iFrames = Doc.getElementsByName("top_window")
If Not iFrames Is Nothing Then
Set iFrame = iFrames(0)
Ie.navigate URL & iFrame.src
While Ie.Busy Or Ie.readyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set InputBox = Doc.getElementsByName("Nachnamevalue")
If Not InputBox Is Nothing Then InputBox(0).Value = "test"
' Clicks on "search"
Set allTags = Doc.getElementsByTagName("input")
For Each Tag In allTags
If Tag.Value = "suchen" Then
Tag.Click
Exit For
End If
Next
' Here a new tab is opened, must find info in this tab
While Ie.Busy Or Ie.readyState <> READYSTATE_COMPLETE: DoEvents: Wend
' HERE I HAVE NO CLUE WHAT TO WRITE. THE CODE ABOVE WORKS FLAWLESSLY
End If
Set Doc = Nothing
Set iFrames = Nothing
Set iFrame = Nothing
Set InputBox = Nothing
Set allTags = Nothing
Set Ie = Nothing
Ie.Quit
End Sub
Now, is there a way to address a tab by: 1) its name (and where do I find it) 2) its position in browser 3) the status (if it is "active") ?
Bonus questions: since I am new to VBA and Internet Explorer interaction, what exactly are the variables: htmlButton, allTags, Tag ? Also, could anyone explain if I need to set all the variables at the end to nothing, or I just need to set the Internet Explorer to nothing?
Thanks in advance!
See below for a function you can use to get an open IE document window - I don't think IE exposes any simple (VBA-accessible) API for working directly with tabs or determining whether a specific tab is active.
allTags is a collection of DOM elements with type "" , and Tag is a single memeber of that collection.
You do not have to set objects to Nothing before exiting a Sub (though some people still do that) - the VBA runtime will take care of that for you.
Sub TestGetIE()
Dim IE As Object
Set IE = GetIE("http://stackoverflow.com")
If Not IE Is Nothing Then
IE.document.execCommand "Print", False, 0
End If
End Sub
'Get a reference to an open IE window based on its URL
Function GetIE(sLocation As String) As Object
Dim objShell As Object, objShellWindows As Object, o As Object
Dim sURL As String
Dim retVal As Object
Set retVal = Nothing
Set objShell = CreateObject("Shell.Application")
Set objShellWindows = objShell.Windows
For Each o In objShellWindows
sURL = ""
On Error Resume Next
'check the URL and if it's the one you want then
' assign it to the return value
sURL = o.document.Location
On Error GoTo 0
'Debug.Print sURL
If sURL Like sLocation & "*" Then
Set retVal = o
Exit For
End If
Next o
Set GetIE = retVal
End Function

I need to find and press a button on a webpage using VBA

I have written a macro that will open a webpage, find the spots I need to put the data into, and then I want the macro to hit a prefill button, then hit Ok.
The page source code for the button is:
<input type="text" size="30" maxlength="40" name="name" id="name">
<input type="button" value="Prefill" onclick="prefill()">
I've been searching for answers all week and I think I have a basic understanding of how this is supposed to work by running a loop to search for it, but I'm having no luck in my endeavor of actually getting this to work.
Can someone show me the loop that will search my page for this button?
Thank you in advance.
Requested code so far
Private Sub Populate_Click()
Dim i As Long
Dim IE As Object
Dim objElement As Object
Dim objCollection As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "website" 'make sure you've logged into the page
Do
DoEvents
Loop Until IE.READYSTATE = 3
Do
DoEvents
Loop Until IE.READYSTATE = 4
ActiveSheet.EnableCalculation = False
ActiveSheet.EnableCalculation = True
Call IE.document.getelementbyid("name").SetAttribute("value", ActiveSheet.Range("b2").Value)
Call IE.document.getelementbyid("aw_login").SetAttribute("value", ActiveSheet.Range("a2").Value)
Set objCollection = IE.document.getElementsByTagName("input")
i = 0
While i < objCollection.Length
If objCollection(i).Type = "button" And _
objCollection(i).Name = "Prefill" Then
Set objElement = objCollection(i)
End If
i = i + 1
Wend
objElement.Click
End Sub
Looks like you are pretty close, this is what I have used to do something similiar
With ie.document
Set elems = .getelementsbytagname("input")
For Each e In elems
If (e.getattribute("className") = "saveComment") Then
e.Click
Exit For
End If
Next e
End With
You will probably just have to change the if statement.
I also notice that your code refers to .Name = "Prefill" but your html snippet refers to .value = "Prefill"