VBA Clicking Button on IE - excel

I use VBA a lot, but I'm still a beginner when it comes to IE automation.
I need to create a code to click a "button" on a specific website for my company.
This button opens up a small menu where I need to select a few things (I'll deal with that later I guess). Thing is, the button doesn't show any ID or name, it's a span and I'm having trouble making it click it.
Below is the HTML when I press F12 and inspect the element over the button:
<span class="search_for_watchers">
Procurar por outros observadores para adiconar
</span>
I've tried so many suggestions that I found over the internet.. I've tried getting the element by ID, name, class name, etc, but no success.
Below is the code I'm using:
Sub Automate_IE_Load_Page()
Dim i As Long
Dim URL As String
Dim ie As Object
Dim objElement As Object
Dim objCollection As Object
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
URL = "Examplesite.com"
ie.Navigate URL
Application.StatusBar = URL & " is loading. Please wait..."
Do While ie.READYSTATE = 4: DoEvents: Loop
Do Until ie.READYSTATE = 4: DoEvents: Loop
Application.StatusBar = URL & " Loaded"
botao = ie.Document.getElementsByClassName("search_for_watchers")
botao.Click
End Sub
It doesn't show any error.. it just doesn't open up the sub-menu I want to, therefore the button isn't clicked.
Thanks!

getElementsByClassName is plural; i.e. it represents a collection. The following represents the first object with this class then clicks the first anchor tag within.
ie.Document.getElementsByClassName("search_for_watchers")(0).getElementsByTagName("a")(0).click
If you want to assign an object var to the element and then use the var to click, you need to Set the var.

You enter endless loop here twice:
Do While ie.READYSTATE = 4: DoEvents: Loop
Do Until ie.READYSTATE = 4: DoEvents: Loop
E.g., it looks like this:
Do While ie.READYSTATE = 4
DoEvents
Loop
but the : are instead of a new line in VBA.
Make sure to change a bit the loop, thus something like this:
Do While NOT ie.READYSTATE = 4: DoEvents: Loop

You could also loop through the tags and find the one you want to click, like so:
Set tags = ie.document.getElementsByTagName("a")
For Each tagx In tags
If tagx.innerText = "Procurar por outros observadores para adiconar" Then
tagx.Click
Exit For
End If
Next

Related

Filling Internet Explorer Forms from Excel

I want to fill information onto the site 'select picker' section on the left side of the picture.
SITE
There is an element name 'picker' but it won't work.
The search bar is being completed using jQuery auto-complete which submits a form that navigates to an associate from the auto-complete box has been selected
I tried
IE.Document.All("picker").Value = "Testing"
IE.Document.GetElementByID("pickerCtrl.currentPicker").Value = "Testing"
IE.Document.GetElementsByClassName("input-group input-group-sm").Item(0).Value = "Testing"
PS.
Is there way to just copy and paste the row at the current position where cursor is positioning at?
I can sendkeys tab 18 times to get to that specific search bar but do not know how to insert the entire row from my Excel sheet.
eg. IE.Document.all("picker").Value = ThisWorkbook.Sheets("Main_1").Range("B" & intRow).Value
I am completely new to this.
Try to make a test with example below may help to solve the issue.
Sub demo1()
Dim i As Long
Dim URL As String
Dim IE As Object
Dim HWNDSrc As Long
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
URL = "D:\Backup20190913\tests\367.html"
IE.Navigate URL
Do While IE.ReadyState = 4: DoEvents: Loop
Do Until IE.ReadyState = 4: DoEvents: Loop
IE.Document.querySelector("[name='picker']").Value = "test value"
Stop
Set IE = Nothing
End Sub
HTML
<input class="form-control ng-valid ng-isolate-scope ng-touched ng-dirty" ng-model="pickerCtrl.currentpicker" name="picker" type="text" typeahead="" typeahead-source="pickerCtrl.getpickerStrings()" ng-disabled="pickerCtrl.errorLoadingPickers || pickerCtrl.noPickerstrings" ng-hide="pickerCtrl.disableTypeahead" autocomplete="off">
Output:

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.

Automating a Report: Selecting from a drop down in IE using VBA

I'm trying to automate a report of mine using VBA. I was able to do the log in part and all but when it comes to navigating the next webpage with drop downs I can't seem to get a hold of it. I tried multiple ways to fill out the first drop down which is the report type and I can't find the correct code
All commented "'" are all the codes I've tried. I can't post the website since it's a client website.
html "inspect elemet" photo
Sub Get_RawFile()
Dim IE As New InternetExplorer
Dim HTMLDoc As HTMLDocument
Dim addressInput As HTMLInputElement
With IE
.Visible = True
.Navigate ("------------------------")
While IE.Busy Or IE.readyState <> 4: DoEvents: Wend
Set HTMLDoc = IE.document
HTMLDoc.all.UserName.Value = Sheets("Data Dump").Range("A1").Value
HTMLDoc.all.Password.Value = Sheets("Data Dump").Range("B1").Value
HTMLDoc.getElementById("login-btn").Click
While IE.Busy Or IE.readyState <> 4: DoEvents: Wend
'HTMLDoc.getElementByName("ddlReportType")(0).Value = "1"
'Set HTMLDoc = IE.document
'Set evtChange = HTMLDoc.createEvent("HTMLEvents")
'evtChange.initEvent "change", True, False
'Set selectElement = HTMLDoc.getElementById("ddlReportType")
'selectElement.Value = "1" 'Attendance
'selectElement.dispatchEvent evtChange
'Set htmlSelectElem = HTMLDoc.getElementsByTagName("ddlReportType")
'htmlSelectElem.selectedIndex = 1
'Set reporttype = IE.document.getElementById("ddlReportType")
'For i = 1 To reporttype.Options.Length
'If reporttype.Options(i).Text = "Attendance" Then
'reporttype.selectedIndex = i
'Exit For
'End If
'Next i
End With
Run-time error '438'
Object doesn't support this property or method
This method .getElementByName does not exist. It should be .getElementsByName("Something"), in which case the method returns a collection of elements whose Name attribute is Something.
The following would access the first element of the collection of elements whose Name attribute is ddlReportType and set its value to 1:
HTMLDoc.getElementsByName("ddlReportType")(0).Value = "1"
Having said that, you don't seem so sure as to what ddlReportType is.
If it's the id of an element then the element should look like so:
<tagName id="ddlReportType">Something</tagName>
In that case you should use the method .getElementByID()
If it's the Name of an element then the element should look like so:
<tagName Name="ddlReportType">Something</tagName>
In that case you should use the method .getElementsByName(), which returns a collection of elements.
If it's the Class of an element then the element should look like so:
<tagName Class="ddlReportType">Something</tagName>
In that case you should use the method .getElementsByClassName(), which returns a collection of elements.
Finally, I can tell you for sure that it's not a Tag Name so you definitely shouldn't use the .getElementsByTagName method.
EDIT
From the image you provided after editing your original post, it is clear that ddlReportType is the id of a <select></select> element. So you should do it this way:
Dim HTMLselect As HTMLSelectElement
Set HTMLselect = HTMLDoc.getElementById("ddlReportType")
HTMLselect.Value = "1"
References used: Microsoft HTML Object Library (VBE>Tools>References>...)
That's how to select one of the drop down options. To navigate further you would have to press some button I presume.

Cannot perform auto search on a specific website

Recently I am learning to use excel macro to search on a website. I've read several forum threads and I came up with the code below. However, error appears when I reach the row
SearchBox(0).Value = SearchString
I tried to remove the (0) but another error appears as well. The code works well on other websites. How should I change them to adapt to this site?
P.S. I would also like to know the way to click the search button.
Sub Searchstockcode()
Dim SearchString As String
SearchString = "700"
Set ie = CreateObject("InternetExplorer.Application")
With ie
ie.Visible = True
End With
ie.Navigate "http://www.hkexnews.hk/listedco/listconews/advancedsearch/search_active_main.aspx"
While ie.ReadyState <> 4
DoEvents
Wend
Dim SearchBox As Object
Set SearchBox = ie.Document.GetElementsByName("ct100$txt_stock_code")
SearchBox(0).Value = SearchString
Dim SearchButton As Object
Set SearchButton = ie.Document.GetElementsByName
End Sub
I don't know whether the problem with your name selection is due to the element having two name attributes but that seems possible.
You may use the following.
For the search box I use its id to target the element. This is normally unique on a document and the fastest selector method.
For the search button I use a CSS attribute + value selector of
[src*='/image/search.gif']
This targets the src attribute [] of the element by its value. * means contains. The selector looks for a src attribute containing /image/search.gif in its value.
You can observe the attribute here:
Option Explicit
Sub Searchstockcode()
Dim SearchString As String, SearchBox As Object, SearchButton As Object, ie As Object
SearchString = "700"
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.navigate "http://www.hkexnews.hk/listedco/listconews/advancedsearch/search_active_main.aspx"
While ie.Busy Or ie.readyState < 4: DoEvents: Wend
Set SearchBox = ie.document.getElementById("ctl00_txt_stock_code")
SearchBox.Value = SearchString
Set SearchButton = ie.document.querySelector("[src*='/image/search.gif']")
SearchButton.Click
While ie.Busy Or ie.readyState < 4: DoEvents: Wend
Stop '<==Delete me
'other code
ie.Quit
End Sub

Fill USPS webform dropdown using VBA EXCEL

I am trying to automatically fill a USPS webform, and it is working for street address, city and zipcode, but I can't make it fill the State dropdown. Any ideas?
Here's the code I currently have:
Sub USPS()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "https://tools.usps.com/go/ZipLookupAction!input.action?mode=1&refresh=true"
Do
DoEvents
Loop Until IE.READYSTATE = 4
Call IE.Document.getElementByID("tAddress").SetAttribute("value", "2 Peabody Terrace")
Call IE.Document.getElementByID("tCity").SetAttribute("value", "Cambridge")
Call IE.Document.getElementByID("sState").SetAttribute("value", "MA")
Call IE.Document.getElementByID("Zzip").SetAttribute("value", "02138")
Set AllHyperLinks = IE.Document.GetElementsByTagName("A")
For Each hyper_link In AllHyperLinks
If ID = "lookupZipFindBtn" Then
hyper_link.Click
Exit For
End If
Next
End Sub
Thank you very much for your help!
Make this change to your code:
'Call IE.Document.getElementByID("sState").SetAttribute("value", "MA")
With IE.Document.getElementByID("sState")
For i = 0 To .Length - 1
If .Item(i).Value = "MA" Then
.Item(i).Selected = True
Exit For
End If
Next
End With
This will work... but the web page will still show like the Select element has not changed. It's an illusion. I suspect there is some JavaScript in the page interfering with this element's display.
HOWEVER, if you do this in the Immediate Window of the VBEditor:
?IE.Document.getElementByID("sState").value
...you will see that the value for the control has indeed changed to 'MA'.
Further, if you go ahead and click on the web page's Find button, you will see that 'MA' was in fact included under 'You entered:'.
So my code above is the solution to your problem.
CSS selectors:
You can use css selectors to do this.
① The first selector I use is for the initial landing page to select the search by address:
#zip-lookup-app a > span
This says span tag within an a tag, inside element with id zip-lookup-app. "#" means id.
This matches the following, of which I want the first.
② The second selector:
#tState option[value='MA']
This says select option tag with attribute value, having value of 'MA', within element with id tState. The "[]" means attribute.
VBA:
As I want the first match I can use the querySelector method of document to apply the CSS selector as shown below:
Option Explicit
Public Sub MakeStateSelection()
Dim ie As New InternetExplorer, html As HTMLDocument
With ie
.Visible = True
.navigate "https://tools.usps.com/go/ZipLookupAction!input.action?mode=1&refresh=true"
While .Busy Or .READYSTATE < 4: DoEvents: Wend
Set html = .document
html.querySelector("#zip-lookup-app > div > div:nth-child(1) > div > ul > li:nth-child(1) > a > span").Click
While .Busy Or .READYSTATE < 4: DoEvents: Wend
html.querySelector("#tState option[value='MA']").Selected = True
'other code
Stop '<== Delete me
'.Quit '<== Uncomment me
End With
End Sub

Resources