Click on picture or link behind it - vba

Hi I have macro which supposed to click on button on web page..problem is there is no ID behind just this code. Its intranet web page.
Begining of my code
Set IE = New InternetExplorerMedium
IE.Navigate = "some website"
While IE.ReadyState <> READYSTATE_COMPLETE
DoEvents
Wend
IE.Visible = True
IE.document.getElementById("CategoryCombo").Value = "78"
IE.document.getElementById("CategoryCombo").FireEvent ("onchange")
'~~> wait until element is present on web page
Do
Set ieobj = Nothing
On Error Resume Next
Set ieobj = IE.document.getElementById("text1265")
DoEvents
Loop Until Not ieobj Is Nothing
'~~> search box
IE.document.getElementById("text1265").Value = "some value"
'~~> button click example
IE.document.getElementById("subBtn").Click
Part of website code
<a title="View document" href="javascript:FSResults_fsopenWindow('index.fsp?pn=DOLViewDocument&d=78&q=78-17158635-1&o=78-17158635-1&p=DOCUMENT_NAME#ensureVisible')" onclick="fsCancelEvent(event)"><img border="0" alt="View document" align="absmiddle" src="Images/DocTypes/PDF.gif"></a>
I tried
IE.document.getElementByTitle("View document").FireEvent ("onclick")
I also tried
IE.document.getElementByTagName("a").FireEvent ("onclick")
Thank you

I also tried
IE.document.getElementByTagName("a").FireEvent ("onclick")
This should work for you, but you are missing something. You need to specify which <a> tag you are looking for, so .getElementsByTagName("a") turns into .getElementsByTagName("a")(i), where i is the index of the tag you are looking for (you get the index by counting in order every <a> tag in the HTML, starting from 0).
The index is needed because .getElementsByTagName("tagName") returns an array, not a single value.

You could have used CSS selectors.
For example, an attribute selector
ie.document.querySelector("[title='View document']").Click
Or same thing to target href by its value
ie.document.querySelector("[href*=fsopenWindow]").Click
The last one looks for href containing 'fsopenWindow'
Both of these avoid looping over collections of elements and use CSS so are faster.

In the end I came up with this. Thank you for help Nicholas Kemp, your answer send me to right direction
Set elements = IE.document.getElementsByTagName("a")
For Each element In elements
If Left(element, 33) = "javascript:FSResults_fsopenWindow" Then
Debug.Print element
IE.Navigate element
End If
Next

Related

Trying to click on the first youtube video link using VBA

My end goal is to dynamically get music playing. I figured that navigating to youtube, searching for the string, and playing the first video suggested is a good way of getting this done. Pandora and Spotify both have hoops that you need to jump through before playing.
Sub YouTube()
So we open up IE, and navigate to the website
Set objIE = CreateObject("InternetExplorer.Application")
WebSite = "www.youtube.com"
With objIE
.Visible = True
.navigate WebSite
Do While .Busy Or .readyState <> 4
DoEvents
Loop
So far, so good. Next we find the search box, and make a search. Dummy text entered for the sake of easy coding, it'll eventually be an argument passed to the function.
Set Element = .document.getelementsbyname("search_query")
Element.Item(0).Value = "portal 2 walkthrough video"
.document.forms(1).submit
Do While .Busy Or .readyState <> 4
DoEvents
Loop
Great, we made it! Now for the part I'm struggling on - clicking on the first video.
I've tried a few different things - I can't seem to find a name, and I keep getting a "Permission denied" when I try to do something like this, as suggested by other users. See: How do I click a link on a web page using Excel VBA?
I've decided not to programatically control the mouse and click, since the location I need to click on keeps dynamically changing.
I'm not very good at interfacing with IE while using VBA, so at this point I'm stumped.
Set Element2 = .document.getelementsbytagname("a")
For Each i In Element2
If i.classname = "yt-lockup-content" Then
i.Click
Exit For
Else
'do nothing
End If
Next i
End With
End Sub
I've also tried:
.document.getelementsbyclassname("yt-lockup-content").Click
But that's not a supported method
.document.querySelector("a[href=javascript:browserPrint();]").Click
Gets a permission denied
The following using a loop to wait until results are present. I try to keep much of the selectors used to target elements fairly loose to allow for changes in html
Option Explicit
Public Sub test()
Dim ie As InternetExplorer
Set ie = New InternetExplorer
With ie
.Visible = True
.Navigate2 "https://www.youtube.com/"
While .Busy Or .readyState <> 4: DoEvents: Wend
.document.querySelector("[title=Search]").Value = "portal 2 walkthrough video"
.document.querySelectorAll("form").item(1).submit
While .Busy Or .readyState <> 4: DoEvents: Wend
Do
Loop While .document.querySelectorAll("#results").Length = 0
.document.querySelector("#results h3 a").Click
While .Busy Or .readyState <> 4: DoEvents: Wend
Stop '<Delete me later
End With
End Sub
Another method is to use the querySelector() method. You know you want the element with the tag a, because the a tag means that it contains a link.
Then combine the above with the class name that you're looking for, yt-lockup-title, and you get this single line:
.querySelector("h3.yt-lockup-title").Click
Take note that this is a method of the document object. So objIE.Document.querySelector()
Don't want to use the .Click method? You can also grab the url from the href attribute and just perform a navigation:
Dim vidURL As String
vidURL = objIE.document.querySelector("h3.yt-lockup-title > a").getAttribute("href")
objIE.navigate "https://www.youtube.com" & vidURL
However, in the method you attempted with using
.document.getelementsbyclassname("yt-lockup-content").Click
the getElementsByClassName() function returns a collection of elements. Because of this, you would need to append the index number of the element you are wanting, which would very likely be the first element (since you want the first video).
One of the two lines would be what you're looking for:
.document.getelementsbyclassname("yt-lockup-content")(0).Click
' - OR -
.document.getelementsbyclassname("yt-lockup-content").Item(0).Click
They both do and mean the same thing.
I have changed a element to span element and it worked. Code below:
Sub YouTube()
Set objIE = CreateObject("InternetExplorer.Application")
WebSite = "www.youtube.com"
With objIE
.Visible = True
.navigate WebSite
Do While .Busy Or .ReadyState <> 4
DoEvents
Loop
Set Element = .document.getelementsbyname("search_query")
Element.Item(0).Value = "portal 2 walkthrough video"
.document.forms(1).submit
Do While .Busy Or .ReadyState <> 4
DoEvents
Loop
Set Element2 = .document.getelementsbytagname("span")
For Each i In Element2
Do While .Busy Or .ReadyState <> 4
DoEvents
Loop
If i.classname = "yt-thumb-simple" Then
i.Click
Exit For
Else
'do nothing
End If
Next i
End With
End Sub

VBA Automate IE: element.click and element.FireEvent (OnClick) Not working

I am trying to parse a web based pivot table.
Unfortunately, I need to expand additional lines in the web based pivot table in order to access all the data I need. I think that when I click on the + sign to expand additional lines, a script downloads the additional data from the database.
Anyway, here is the html code of the + sign:
<DIV class="clip9x9 di-img" onclick=_Ewa.Gim.tpdfce(event);>
<INPUT title=Expand class=ewaboot_expand type=image alt=Expand src="http://...">
</DIV>
I manage to get the correct element into an variable using IE.document.getElementsByTagName("Div") and a If Loop (for some reason the GetElementByClassName would crash my IE), but none of the .Click or .FireEvent (OnClick) methods works. I also tried both methods on the Input element below the DIV, and these are not working either.
Here is the code
Sub Test()
Dim IE As InternetExplorer
Dim div As Variant
Dim Obj As Variant
Dim WebUrl As String
WebUrl = "http://..../filename.aspx"
Set IE = New InternetExplorerMedium
Sleep 1000
IE.Visible = True
IE.navigate WebUrl
Do While IE.Busy Or IE.readyState <> READYSTATE_COMPLETE
Sleep 1000
Loop
Set div = IE.document.getElementsByTagName("Div")
For Each Obj In div
If Obj.className = "clip9x9 di-img" Then
Obj.Click
Obj.FireEvent ("OnClick")
End If
Next i
End Sub
When I look at the onclick attribute of my Obj element in th Spy Window (VBA editor), the onclick property has a + sign aside, and when inspecting inside it, no variable is attributed to it. I find it weird since the HTML code indicates a value =”_Ewa.Gim.tpdfce(event);” which I believe refers to the script that expands the pivot table line.
Any help would be much appreciated

VBA checkbox website interaction

I'm currently experiencing a problem with VBA. I'm trying to tick checkbox on an external website. Here is a html snippet that I'm working with:Html code from external website
I have redacted any confidential information from the snippet.
Here is my VBA code:
Set elements = objIE.document.getElementsByTagName("input")
For Each ele In elements
ele.toString
If ele.Value = "xxx" Then ele.Click
Next
So in this code the elementsvariable is an object and the loop variable ele is not being populated at all. I need to compare that the value in the check box contains value xxx. I'm not too experienced in VBA.
Any help would be appreciated
Thanks
I really don't know if that works. But in VBA the
.Value
property of a Checkbox is eighter true or false. The property of the text that is shown is:
.Caption
This code is looping properly:
Sub test()
Set objIE = CreateObject("InternetExplorer.Application")
Dim elements, ele
objIE.Visible = True
For Each ip In Sheets("Sheet1").Range("A2:A13").Value
objIE.Navigate ip
Do Until Not objIE.Busy And objIE.ReadyState = 4
DoEvents
Loop
Set elements = objIE.document.getElementsByTagName("input")
For Each ele In elements
ele.toString
If ele.Value = "xxx" Then ele.Click
Next
Next
End Sub

VBA getelementsbyclassname use with getelementsbyid

I'm trying to write a short VBA code to click on a button on a website by searching first by its classname, and then by id:
Sub Autoclick[enter image description here][1]()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate "http://stackoverflow.com/"
IE.Visible = True
While IE.Busy
DoEvents
Wend
IE.Document.getElementsByClassname("nav mainnavs").getElementById("nav-jobs").Click
End Sub
However the code would not click on the Jobs button. I understand that I can just use getelementbyid directly, but I'd still like to know why using getelementsbyclassname and getelementbyid together would not work.
Attached image contains the html code of the website.
Thanks a lot for any help!
I'd still like to know why using getelementsbyclassname and
getelementbyid together would not work.
Because code IE.Document.getElementsByClassname("nav mainnavs").getElementById("nav-jobs") causes error 438: object doesn't support this property or method.
It doesn't work because getElementsByClassName("nav mainnavs") returns a div and divs doesn't have any getElementById method.
To search the div by element id it would probably be necessary to loop through all the elements of it and check their id:
Dim mainnavs
Set mainnavs = IE.document.getElementsByClassName("nav mainnavs")
If mainnavs.Length > 0 Then
Dim mainnavItem ' this is a div element and it doesn't have .getElementById() method
Set mainnavItem = mainnavs.Item(0)
Dim itm
For Each itm In mainnavItem.all
If itm.ID = "nav-jobs" Then
itm.Click
Exit For
End If
Next itm
Else
MsgBox "getElementsByClassName('nav mainnavs') didn't return any elements"
End If
when I apply the same method to my company's website it keeps on
showing the message box "didn't return any elements"
This means that element with such class name does not exist on the page.
Do you wait until the page is fully loaded?
While ie.Busy Or ie.readyState <> READYSTATE_COMPLETE: DoEvents: Wend
why would we do mainnavItem.all in the For loop
This is because there is no other possibility to search for element by its id. Therefore we go through all the children of the mainnavItem and check the id.

VBA and Internet Explorer: fill in an input box

I'm new to making interactions between VBA and Internet Explorer, but I've read many things online and couldn't figure out the problem in my code. I just want to retrieve the 'Username' box on a website and add a value inside. So I retrieved all input boxes into a collection of HTML elements, but then that collection is empty:
Dim Collect As IHTMLElementCollection
With IE
.navigate "http:xxxxxxxxxx"
.Visible = True
End With
Do While IE.Busy
Loop
Set Collect = IE.document.getElementsByTagName("input")
MsgBox Collect.Length
End Sub
This will give a message box with "0". If I toggle a breakpoint before the end of the code and I "watch" the variable Collect, I can see there are 17 items inside, one of them being the username 'inputbox', with name 'tfUserName'. Can you help me please?
EDIT: I found that the problem comes from this code:
Do While IE.Busy
Loop
Which I replaced with this:
Do Until IE.readyState = READYSTATE_COMPLETE
DoEvents
Loop
And now everything works fine. Thank you for your responses.
Validate the collection against null instead to determine if it contains elements
If Not Collect Is Nothing Then
For Each htmlElement In Collect
If Not htmlElement.getAttribute("username") Is Nothing Then
htmlElement.setAttribute("value", "licou6")
Exit For
End If
Next
End If