VBA to Click Login Button in IE - html

I'm not too familiar with getting the elements from IE, but I've been successful when it's straight-forward. The website I'm working with now is confusing me.
I am launching a site and putting in the username & password, then I want to click the login button but I am failing to find the correct way to locate and click the button since it doesn't have an ID.
I have seen various posts on this site with similar questions and I have tried following the advice in those posts but still can't get it to work.
I will share my code and the element information from the site.
Dim IEapp As InternetExplorerMedium
Dim divClassLogin As Object
Set IEapp = New InternetExplorerMedium
With IEapp
.Navigate "http://ctdayppv02/PVE.aspx"
.Visible = True
.AddressBar = 0
.StatusBar = 0
.Toolbar = 0
.MenuBar = 0
.Height = 700
.Width = 950
End With
Do While IEapp.Busy: DoEvents: Loop
Do Until IEapp.ReadyState = READYSTATE_COMPLETE: DoEvents: Loop
IEapp.Document.all.Item("txtUserName").Value = "Name"
IEapp.Document.all.Item("txtPassword").Value = "Pass"
IEapp.Document.all.Item("btnLogin").Click
This is the IE Inspect Elements html.
This is the Chrome Inspect Elements html.
The posts I've referenced on this site are (amongst others):
Click button on login page
VBA to click on a button in IE with no ID, Name, ClassName
Use VBA to click on a button in IE
Can somebody help me identify what element I should be looking at to click login? I'm used to finding an ID or something that says "Submit" but I'm not seeing it on this site.
Thanks in advance.

As I cannot access the URL. I just come out with the code (without testing it) that I usually do and for me the most flexible way even though it quite long. Please try:
Dim ee as Variant, htmldoc
Set htmldoc= IEapp.document
For each ee in htmldoc.getElementsByTagName("span")
If ee.className = "dijitReset dijitInline dijitButtonNode" And InStr(ee.innerHTML, "btnLogin") > 0 Then 'not sure whether innerhtml or outerhtml you need tp check in your watches
ee.Click: DoEvents: Sleep 1000
''or u can try this
ee.FireEvent ("onclick"): DoEvents: Sleep 1000
Exit For
End If
Next ee

Related

Addressing specific item within HTML string using VBA

I am trying to use VBA to populate a webform and I am struggling to correctly address the field I want to populate.
This is one line of the table in HTML
Here is the overall HTML structure
<th>
<label for="location_sales_target_2_2022_15_target_val">2022w15 (03/04)</label>
</th>
<td>
<input name="location_sales_target[2][2022/15][id]" id="location_sales_target_2_2022_15_id" type="hidden" value="12751">
<input name="location_sales_target[2][2022/15][target_val]" id="location_sales_target_2_2022_15_target_val" type="text" value="0.00">
</td>
<td>£2,097.33</td>
I need to be able to address the final value field and update its value.
This is the VBA code I have so far. My VBA is limited and this is copied from online and modified.
Sub IEWebScrape1()
Dim IE As InternetExplorer 'Reference to Microsoft Internet Controls
Set IE = New InternetExplorer
With IE
.Visible = True
.Navigate2 "https://"
'we add a loop to be sure the website is loaded and ready.
'Does not work consistently. Cannot be relied upon.
Do While .Busy = True Or .readyState <> READYSTATE_COMPLETE 'Equivalent = .ReadyState <> 4
' DoEvents - worth considering. Know implications before you use it.
Application.Wait (Now + TimeValue("00:00:01")) 'Wait 1 second, then check again.
Loop
'Print info in immediate window
With .document 'the source code HTML "below" the displayed page.
Debug.Print.getElementById("sf_admin_container").Children(1).getElementsByTagName("tr")(16).textContent
End With '.document
' .Quit 'close the application window
End With 'ie
End Sub
The VBA code produces this result, which confirms it is correctly referencing the record I am trying to reference.
2022W15 (03/04)
£2,097.33
How do I correctly address the specific element within the record?
I have solved the problem now. Obviously completely confused about using getElement statements. Problem solved by correct use of getElementById

Select HTML Menu Item via VBA

I'm fairly new to HTML, so please bear with me on this. I am using Excel VBA to interact with an website, with the intent to automate this interaction.
Problem Statement
I have a web page with (what looks like) a button that I need to click on. In the HTML it is listed as a Menu Item. Im able to successfully click other buttons on the page, but those have < button > tags.
I have tried to use the click method by selecting it by ID but I get an 'Object Variable or With block variable not set' error.
Sub WD_auto()
Dim IE As New SHDocVw.InternetExplorer
Dim HTMLDoc As MSHTML.HTMLDocument
Dim HTMLSel As MSHTML.IHTMLElement
IE.Visible = True
IE.navigate "https://wd3.myworkday.com/redacted/d/home.htmld"
Do While IE.Busy = True Or IE.readyState <> 4: DoEvents: Loop
Set HTMLDoc = IE.document
Set HTMLSel = HTMLDoc.getElementById("88831e18a0894109a83c10bc9a9be6c7")
HTMLSel.Click
End Sub
The block of HTML that i think i need to interact with is shown below.
<div class="GNMRENADFGC GNMRENADBHC GNMRENADHHC" tabindex="-2"
id="88831e18a0894109a83c10bc9a9be6c7" role="menuitem"
aria-posinset="1" aria-setsize="3">
Any pointers or literature would be appreciated.
Ok after some more research i have a solution. I am just looping all the div tags and checking the Inner Text property of each until I find the one I want to click.
It works, but if anyone has a more elegant solution I'm all ears. The loop seems a bit wasteful, I would prefer to just refer directly to, and then click the element.
Set ElementsA = IE.document.getElementsByTagName("div")
For Each ElementA In ElementsA
On Error Resume Next
If ElementA.innerText = "User Name and Password login" Then
ElementA.Click
Exit For
End If
Next ElementA

How to click on a <a> element of an <li> of a <ul> using vba?

Here is a piece of code of the HTML page I am working on.
I am trying to programmatically click on the element highlighted in blue in the picture above.
Here is the code I wrote:
Set objIE = New SHDocVw.InternetExplorer
Do While objIE.Busy: DoEvents: Loop
Do Until objIE.readyState = READYSTATE_COMPLETE: DoEvents: Loop
Set IeDoc2 = objIE.Document
Set the_input_elements2 = IeDoc2.getElementsByClassName("parent-item")
For Each input_element2 In the_input_elements2
If input_element2.href = "javascript:directToSearch()" Then
input_element2.Click
Exit For
End If
Next input_element2
How do I click on an element of a ul in HTML using VBA?
When I run this code, nothing happens. No errors but no result.
Here's a couple of ways to refer to the element you're interested in:
'Targeted (if you know exactly at which order the elements appear in the list)
Dim li As HTMLListElement
Set li = IeDoc2.getElementById("accordion-leftmenu") 'get the list item you're interested in...
Debug.Print li.Children(1).innerText '...and access its sub-element in a targeted way
Debug.Print li.getElementsByTagName("a")(1).innerText '...or find all <a></a> elements contained in it and access the one you're interested in, in a targeted way
'Non targeted (you have to search for it)
Dim element As HTMLObjectElement
For Each element In IeDoc2.getElementsByTagName("a") 'loop through all <a></a> elements...
If element.innerText = "Advanced Search" Then '...and find the one you're interested in
Debug.Print element.innerText
End If
Next element
For demonstration purposes the above code just prints the inner text of the element. You can modify it accordingly.
References used: Microsoft HTML Object Library
Also on a side note, please post the actual HTML next time rather than a screenshot of it. It would make it easier for people to help you.
Loop all "a" tags inside the ID of the left menu
IeDoc2.getElementById("accordion-leftmenu").getElementsByTagName("a")
in the loop check if the .innerText is "Advanced Search". click if it is.
Dim IeDoc2 As MSHTML.HTMLDocument
Dim the_input_elements2 As MSHTML.IHTMLElementCollection
Dim input_element2 As MSHTML.IHTMLElement
...
Set the_input_elements2 = IeDoc2.getElementById("accordion-leftmenu").getElementsByTagName("a")
For Each input_element2 In the_input_elements2
If input_element2.innerText = "Advanced Search" Then
input_element2.Click
Exit For
End If
Next input_element2
Edit: Alright, I've tested the code and it works. I did however have to make sure that Two references were checked: "Microsoft HTML Object Library" and "Microsoft Internet Controls".

Web scraping by link text

I have some experience and knowledge how to scrape by tagName or ClassName. However in this particular case className is not unique also link is changing all the time after accessing the page so it is not possible to get a direct link. The only unique combination is class and link text. What would be the code to access for example Budget and Forecast updating with a_1_610 and Budget and Forecast updating with a_1_611?
My code (edited according to QHarr answer):
Sub GoToLiinosBot()
'This will load a webpage in IE
Dim ie As InternetExplorer
Dim HWNDSrc As Long
Dim elements As Object
Set ie = Nothing
Set ie = New InternetExplorerMedium
ie.Visible = True
ie.Navigate "http://link.com"
With ie
Do
DoEvents
Loop Until ie.ReadyState = READYSTATE_COMPLETE
End With
Application.Wait (Now + TimeValue("0:00:04"))
ie.Document.querySelector(".data .a_1_611").innerText
'Unload IE
Set ie = Nothing
End Sub
Here is source code:
They are class names not ids. A loop is perhaps required, with test of innerText value of node, if ordering changes but otherwise you want the first match for the example shown in image
.data .a_1_611
Which is
ie.document.querySelector(".data .a_1_611").click
nth-of-type is useful for fixed position selection but more expensive than class selectors.

Excel VBA: Webpage HTML not showing when I navigate to new page

I'm trying to create a VBA macro in Excel that:
Navigates to a webpage
Searches the HTML document for all elements with the tag name "input"
Prints the attributes of each element found (name, type, and value)
Clicks the button on the webpage to navigate to the second webpage.
Search the HTML document on the second page for all elements with the tag name "input"
Prints the attributes of each element found (name, type, and value)
Everything works find up until Step 5. When I try to search the HTML document, for some reason it doesn't search the HTML document of the second page, instead it looks at the HTML of the initial webpage in Step 2 and prints out the same results in Step 3.
Could you guys please take a look at my code to see what I am doing wrong? I listed my code below and tried to make comments to make it readable.
Sub C_R()
Dim ie As New SHDocVw.InternetExplorer
Dim HTMLDoc As MSHTML.HTMLDocument
Dim HTMLInput As MSHTML.IHTMLElement
Dim HTMLButtons As MSHTML.IHTMLElementCollection
Dim HTMLButton As MSHTML.IHTMLElement
'Opens Internet Explorer and navigates to website.
ie.Visible = True
ie.navigate "http://openaccess.sb-court.org/OpenAccess/"
Do While ie.ReadyState <> READYSTATE_COMPLETE
Loop
'Searches HTML(initial page) to find all elements with "input" tag name.
'Prints attributes of each element (name, type, and value".
Set HTMLDoc = ie.Document
Set HTMLButtons = HTMLDoc.getElementsByTagName("input")
Debug.Print "Initial Page"
For Each HTMLButton In HTMLButtons
Debug.Print HTMLButton.getAttribute("name"), HTMLButton.getAttribute("type"), HTMLButton.getAttribute("value")
Next HTMLButton
'Navigates to second page
HTMLButtons(1).Click
Do While ie.ReadyState <> READYSTATE_COMPLETE
Loop
'Searches HTML(second page) to find all elements with "input" tag name.
'Prints attributes of each element (name, type, and value".
Set HTMLDoc = ie.Document
Set HTMLButtons = HTMLDoc.getElementsByTagName("input")
Debug.Print "Second Page"
For Each HTMLButton In HTMLButtons
Debug.Print HTMLButton.getAttribute("name"), HTMLButton.getAttribute("type"), HTMLButton.getAttribute("value")
Next HTMLButton
End Sub
Any help you can provide will be greatly appreciated. Thank you so much.
It looks like your second loop is continuing even though the webpage hasn't completely loaded.
Do While ie.ReadyState <> READYSTATE_COMPLETE
Loop
To see this, put a break point at the second loop, and wait for the second web page to load. Then continue the code, and it should work fine.
You will need to either add a wait time in the loop, which may not always work, or find another way to tell if the ie.ReadyState is complete.