VBA Clicking on an Item with Internet Exporer - vba

My company uses a web based reporting system and I'm trying to automatically export the data to Excel. There is a standard dropdown menu with File > Export to XLS and I would like to automatically click the "Export" button to download the report.
I have read through other posts dealing with clicking buttons to expand a page, or enter a value into a form, etc, but possibly because the button is in a drop down menu, or because the element is within an iframe none of the previously posted solutions have worked for me.
So Far:
I can navigate to the page
I can get the menuExportXLS element
Debug.print prints the correct innerText
My code is not throwing any errors
BUT I can't successfully click the button to download the file.
Alternatively, there is a javascript onclick script within the HTML that could trigger the download, but I don't know how to call it in VBA. I would be happy to get either method running.
Sample of HTML
Sub ExportXLSTest()
Dim appIE As InternetExplorerMedium
Dim Obj As Object
Set appIE = New InternetExplorerMedium
sURL = "https://Site"
With appIE
.Navigate sURL
.Visible = True
End With
Do While appIE.Busy Or appIE.ReadyState <> 4
DoEvents
Loop
Application.Wait (Now + TimeValue("0:00:05"))
Set Obj = appIE.document.getElementsByTagName("iframe")(0).contentDocument.getElementById("menuExportXLS")
Debug.Print Obj.innerText
Obj.Click
Set appIE = Nothing
End Sub

You can use a CSS selector to target the element;
appIE.document.getElementsByTagName("iframe")(0).contentDocument.querySelector("[onclick*='exportXLS']").Click
This is an attribute = value selector that targets the first element in the content document that has an onclick attribute containing the value exportXLS.

Related

Can't find any logic how the faulty script works flawlessly?

I've written a script in vba using IE to get the titles of different hotel names from a webpage. The hotel names traverse multiple pages through pagination.
My scraper can keep clicking on the next button successfully while parsing the titles from each page until ther is no more click left to perform. The parser is doing is job just perfect. All I wish to know is a simple logic I've asked below.
My question: How the content of each page is rightly coming through even when I didn't use this Set Htmldoc = IE.document line just after the .click? When a click is initiated, the scraper goes to a new page with new content. How come it gets updated with new content from each page as my defined do loop comes after with IE block?
This is the script:
Sub GetTitles()
Const Url As String = "https://www.tripadvisor.com/Hotels-g147237-Caribbean-Hotels.html"
Dim IE As New InternetExplorer, Htmldoc As HTMLDocument, post As Object, R&
With IE
.Visible = True
.navigate Url
While .Busy = True Or .readyState < 4: DoEvents: Wend
Set Htmldoc = .document
End With
Do
For Each post In Htmldoc.getElementsByClassName("listing") ''how this "Htmldoc" gets updated
With post.getElementsByClassName("property_title")
If .Length Then R = R + 1: Cells(R, 1) = .Item(0).innerText
End With
Next post
If Not Htmldoc.querySelector(".standard_pagination span[onclick*='pagination_next']") Is Nothing Then
Htmldoc.querySelector(".standard_pagination span[onclick*='pagination_next']").Click
Application.Wait Now + TimeValue("00:00:05")
''I didn't use anything like "Set Htmldoc = IE.document" but it still works flawlessly
Else:
Exit Do
End If
Loop
IE.Quit
End Sub
The script is not faulty. Though, you are using it without fully understanding is certainly troublesome.
When you do this Set Htmldoc = .document you are setting the IE's document for later use.
When you do this Htmldoc.querySelector(".standard_pagination span[onclick*='pagination_next']").Click javascript comes in play and updates the content of the page (i.e document).
You may believe that the document has changed but its only being updated. In reality,there is no navigation happening at all.
Add the following and see how the page/document remains the same, just the content changes.
'/ Url before Next button click
Debug.Print "Before Click " & Htmldoc.Url
Htmldoc.querySelector(".standard_pagination span[onclick*='pagination_next']").Click
'/ Url after Next button click
Debug.Print "After Click " & Htmldoc.Url
Since the document, once set remains the same and the updated content has same layout/DOM (that is how mostly programmers code, most likely all the pages are being rendered using a template) hence your code works perfectly fine. Net to net for your do loop, nothing changed.
Set Htmldoc = .document
gets a pointer to the DOM. When it changes the Htmldoc is pointing at the new content. No need to do a new Set Htmldoc

Can't click on some dots to scrape information

I've written a script in vba in combination with IE to click on some dots available on a map in a web page. When a dot is clicked, a small box containing relevant information pops up.
Link to that website
I would like to parse the content of each box. The content of that box can be found using class name contentPane. However, the main concern here is to generate each box by clicking on those dots. When a box shows up, it looks how you can see in the below image.
This is the script I've tried so far:
Sub HitDotOnAMap()
Const Url As String = "https://www.arcgis.com/apps/Embed/index.html?webmap=4712740e6d6747d18cffc6a5fa5988f8&extent=-141.1354,10.7295,-49.7292,57.6712&zoom=true&scale=true&search=true&searchextent=true&details=true&legend=true&active_panel=details&basemap_gallery=true&disable_scroll=true&theme=light"
Dim IE As New InternetExplorer, HTML As HTMLDocument
Dim post As Object, I&
With IE
.Visible = True
.navigate Url
While .Busy = True Or .readyState < 4: DoEvents: Wend
Set HTML = .document
End With
Application.Wait Now + TimeValue("00:0:07") ''the following line zooms in the slider
HTML.querySelector("#mapDiv_zoom_slider .esriSimpleSliderIncrementButton").Click
Application.Wait Now + TimeValue("00:0:04")
With HTML.querySelectorAll("[id^='NWQMC_VM_directory_'] circle")
For I = 0 To .Length - 1
.item(I).Focus
.item(I).Click
Application.Wait Now + TimeValue("00:0:03")
Set post = HTML.querySelector(".contentPane")
Debug.Print post.innerText
HTML.querySelector("[class$='close']").Click
Next I
End With
End Sub
when I execute the above script, it looks like it is running smoothly but nothing happens (I meant, no clicking) and it doesn't throw any error either. Finally it quits the browser gracefully.
This is how a box with information looks like when a dot gets clicked.
Although I've used hardcoded delay within my script, they can be fixed later as soon as the macro starts working.
Question: How can I click each of the dots on that map and collect the relevant information from the popped-up box? I only expect to have any solution using Internet Explorer
The data are not the main concern here. I would like to know how IE work in such cases so that I can deal with them in future cases. Any solution other than IE is not I'm looking for.
No need to click on each dots. Json file has all the details and you can extract as per your requirement.
Installation of JsonConverter
Download the latest release
Import JsonConverter.bas into your project (Open VBA Editor, Alt + F11; File > Import File)
Add Dictionary reference/class
For Windows-only, include a reference to "Microsoft Scripting Runtime"
For Windows and Mac, include VBA-Dictionary
References to be added
Download the sample file here.
Code:
Sub HitDotOnAMap()
Const Url As String = "https://www.arcgis.com/sharing/rest/content/items/4712740e6d6747d18cffc6a5fa5988f8/data?f=json"
Dim IE As New InternetExplorer, HTML As HTMLDocument
Dim post As Object, I&
Dim data As String, colObj As Object
With IE
.Visible = True
.navigate Url
While .Busy = True Or .readyState < 4: DoEvents: Wend
data = .document.body.innerHTML
data = Replace(Replace(data, "<pre>", ""), "</pre>", "")
End With
Dim JSON As Object
Set JSON = JsonConverter.ParseJson(data)
Set colObj = JSON("operationalLayers")(1)("featureCollection")("layers")(1)("featureSet")
For Each Item In colObj("features")
For j = 1 To Item("attributes").Count - 1
Debug.Print Item("attributes").Keys()(j), Item("attributes").Items()(j)
Next
Next
End Sub
Output

Trying to press a button on an internet page using vba

I know there is a similar question to this - but it doesn't show enough detail to help me, I am still new to this and need a little more guidance. What I am trying to do is use a VBA Macro to press a button on a web page.
The details that I can find out about the button are
class = "urBtnEmph"
id = "b1_pki"
ct= "Button"
onclick = "LoginViaPKI();"
It isn't a page I have written, or have access to change anything on. But is there anyway I can automate clicking the button?
Thank You
Try this with IE:
Dim IE As New InternetExplorer
Dim doc As HTMLDocument
Set doc = IE.document
'below line may be needed in case the page load is slow
'Do While IE.readyState <> READYSTATE_COMPLETE Or IE.Busy: DoEvents: Loop
Dim Button As Object
Set Button = doc.getElementById("b1_pki")
Button.Click
It requires reference to Microsoft Internet Controls and Microsoft HTML Object Library

how to click a button on webpage having class name using vba excel

I am a rookie in VBA excel.
There is a web page application in which
i need to click a button, the source of which is
<em class="x-btn-arow" unselectable="on">
<button class= x-btn-text" id="ext-gen7576" style="" type="button">Actions</button>
Sub xx()
Dim IE As Object
Dim doc As HTMLDocument
Dim l As IHTMLElement
Dim lo As IHTMLElementCollection
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "http://theapplicationlink"
Do
DoEvents
Loop Until IE.ReadyState = 4
Set doc = IE.Document
Set lo = doc.getElementsByTagName("button")
For Each l In lo
If l.getAttribute("class") = "x-btn-text" Then
l.click
End If
Next
End Sub
it doesn't throw any error but it doesn't click the button.
I cannot use ID as it keeps on changing each time i launch the application.
Also the class and type is same for other buttons also.
Forgive me for any technical errors
Any help will be a huge favour here.
There is an id. Does it change completely or does part of it remain the same? If it were you could partial match on the bit that remain the same using a CSS selector.
That aside you could use:
objIE.document.querySelector("button[class*= x-btn-text]").Click
This uses a CSS selector to target the element of button[class*= x-btn-text]. Which will be the first element with button tag having attribute class with value containing x-btn-text.
"button" is not a HTML tag. use a "Tag". let me give you an example here. Replace the "strTagName" with a HTML tage that inlcudes the thing you want to click.
Dim objTag As Object
For Each objTag In objIE.document.getElementsByTagName(strTagName)
If InStr(objTag.outerHTML, "x-btn-text") > 0 Then
objTag.Click
Exit For
End If
Next

Is it possible to open a website when clicking vbMsgHelpButton?

I have a MsgBox that displays both "OK" and "Help" buttons. I would like to redirect to a website when Help button is clicked, but I'm completely unable to achieve it.
I have read in some forums that the easiest way to get it is to make your own userform and to assign a subroutine to each button attached.
Another possible way that I've found is to create a *.hlp file, call it from the Help File parameter and place the proper context ID, but I need to store the help file in a website, and, anyway, I can't find the context IDs numbers.
Thanks in advance for your help!
Here is what you would need to put in the VBE for your help button.
Private Sub HelpButton_Click()
Dim IE as Object
Set IE = CreateObject(InternetExplorer.Application)
IE.Visible = True
IE.Navigate = "Insert your URL here"
End Sub
Here you can find all you need to manage URLs to be opened with Internet Explorer (easiest way) .
In the link I gave it will be shown how to use IE (Internet Explorer) libraries in order to manage some tasks such as opening URL (which you can of course trigger by a click on the "help" button in your userform), filling forms and/or click buttons in a webpage.
Although I think if you have directly a help web page, the first option will suffice.
An overview of what can help you in the link I gave you:
Sub GoToWebSite()
Dim appIE As Object ' InternetExplorer
Dim sURL As String
Application.ScreenUpdating = False
Set appIE = GetIE
sURL = "yourhelpwebpage"
' Here you can add the "on Help button click" action to trigger the following
With appIE
.Navigate sURL
.Visible = True
End With
Application.ScreenUpdating = True
Set appIE = Nothing
End Sub