Excel respond to a web DOM event via VBA - excel

I am trying to respond to a button click on a website opened via Excel VBA.
The code below is trying to getting it working as a test with Duckduckgo.
The web page loads fine but I just cannot seem to get the onclick event, which I need to do to grab the values out of the text input elements that the user will have filled in.
Option Explicit
Private WithEvents IEButton As MSHTML.HTMLInputButtonElement
Public Sub Init(aButton As MSHTML.HTMLInputButtonElement)
Set IEButton = aButton
End Sub
Private Function IEButton_onclick() As Boolean
Debug.Print "Clicked"
MsgBox "HI"
End Function
Private Sub cmdTest_Click()
Dim ie As InternetExplorer, html As HTMLDocument
Dim link As String
link = "http://www.duckduckgo.com/"
Set ie = New InternetExplorer
With ie
.Visible = True
.navigate link
While .Busy = True Or .readyState < 4
DoEvents
Wend
Set html = .document
Dim ieBut As New clsIEButton
ieBut.Init html.querySelector("#search_button_homepage")
End With
ShowWindow ie.hwnd, SW_SHOWMAXIMIZED
End Sub

The web page loads fine but I just cannot seem to get the onclick
event, which I need to do to grab the values out of the text input
elements that the user will have filled in.
Please refer to the following sample code:
Private ieBut As clsIEButton 'global variable.
Private Sub cmdTest_Click()
Dim ie As InternetExplorer, html As HTMLDocument
Dim link As String
link = "http://www.duckduckgo.com/"
Set ie = New InternetExplorer
With ie
.Visible = True
.navigate link
While .Busy = True Or .readyState < 4
DoEvents
Wend
Set html = .document
Set ieBut = New clsIEButton
'transfer the button element and the html document.
ieBut.Init html.getElementById("search_button_homepage"), html
End With
End Sub
clsIEButton (class module)
Option Explicit
Private WithEvents IEButton As MSHTML.HTMLInputButtonElement
Private html As MSHTML.HTMLDocument
Private Function IEButton_onclick() As Boolean
Debug.Print "button: clicked!"
'based on the html document to get the entered value.
Debug.Print html.getElementById("search_form_input_homepage").Value
End Function
Public Sub Init(aButton As MSHTML.HTMLInputButtonElement, ahtml As MSHTML.HTMLDocument)
Set IEButton = aButton
Set html = ahtml
End Sub
After entering the value and click the search button, the VBA output looks as below:

As soon as cmdTest_Click completes, all its local variables are destroyed, including ieBut.
If you need that to hang around until someone clicks the button, you need to move
Dim ieBut As New clsIEButton
to the top of the module, outside of any Sub/Function.
Similar code here: detect event on IE from visio

Try this part
Set html = .document
html.queryselector("#search_form_input_homepage").Value = "Excel VBA"
html.queryselector("#search_button_homepage").Click
Put the following line before the action of the Cick
Range("A1").value = html.queryselector("#search_form_input_homepage").Value

Related

Click on Class names in VBA - No Selenium

I am into Project Management with no knowledge of IT / Coding.
I am trying to do web automation.
It will have to click on certain links, submit a form and then hit save.
However I am not able to click on the first link as well.
this is my code as of now.
Sub CommandButton1_Click()
Dim ie As Object
Dim html As HTMLDocument
Dim form As Variant, button As Variant
Sheet1.Range("B6").Value = Application.UserName
'Open Internet Explorer
Set ie = CreateObject("InternetExplorer.Application")
ie.navigate "https://www.link.com/"
ie.Visible = True
While ie.Busy
DoEvents
Wend
Set html = ie.document
html.getElementsByClassID("p2205").Click
End Sub
Below is the code.
I want to click on Company Name.
Website Code
I have tried the web and YouTube videos as well but I guess I don't know the language or the logic behind coding. Hence I am not able to get through.
Add reference to Microsoft Internet Controls then try
Option Explicit
Sub CommandButton1_Click()
Dim ie As Object, html As HTMLDocument, e As HTMLHtmlElement
Dim URL As String
URL = "https://www.link.com/"
Set ie = New InternetExplorerMedium
ie.navigate URL
ie.Visible = True
While ie.Busy
DoEvents
Wend
Set html = ie.document
For Each e In html.getElementsByClassName("dsh_sta_301")
If InStr(e.onclick, "projectSelection") > 0 Then
e.Click
End If
Next
End Sub

VBA - Excel - Scraping website using IE - How to avoid forever loops when user close IE application while I'm waiting for readystate?

I'm trying to access an internal webpage that requires authentication. Once the user login in correctly, I look for an specific pattern in the application webpage and turn IE.visible = False. I've managed to make it work, but if for ever reason the user close the IE window before the authentication is completed, my macro looses control and remains waiting an answer forever.
Is there any way to prevent it from happening?
This is my code:
Sub myapplication()
Dim IE As New InternetExplorerMedium
Dim elements As MSHTML.IHTMLElementCollection: Dim element As MSHTML.IHTMLElement
Dim URL As String: Dim flag As Boolean
logindate = Format(Date, "dd mmm yyyy"): clockon = Timer: delay = 10
URL = "http://app1.htm"
IE.Visible = True: IE.navigate URL
Do While IE.readyState <> READYSTATE_COMPLETE Or IE.Busy
Loop
Set HTMLDoc = IE.document
Set elements = HTMLDoc.getElementsByClassName("normalText")
flag = False
While flag = False
For Each element In elements
If InStr(element.innerHTML, logindate) Then
IE.Visible = False: flag = True
Exit For
End If
clockoff = Timer
If delay > clockoff - clockon Then flag = True
Next
Wend
End Sub
I understand that your code launching the IE and make it visible so that the user can finish the login process and then after executing some code you make the IE visible false.
You said that if the user closes the IE window manually during the authentication then your code loses the control.
There are several approaches you can try to handle this issue.
You can try to launch the IE browser in fullscreen. So it will not show any browser window controls and close button.
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.FullScreen = True
Note that With this approach, the user can use the ALT + TAB key to switch the window, and then the user can try to close it manually.
Another thing you can try is to use the OnQuit event.
OnQuit event will get fired when the IE browser gets closed. So you can try to set the objects to Nothing on this event or take the necessary steps to reset your code. In this way, you can keep control of the code.
You can refer to the steps below to implement the OnQuit event.
Create a Class module with the name clsIE.
Add the code below in the class module.
Option Explicit
Public WithEvents IE As InternetExplorer
Private Sub Class_Initialize()
Set IE = New InternetExplorer
End Sub
Private Sub Class_Terminate()
Set IE = Nothing
End Sub
Private Sub Ie_OnQuit()
MsgBox "Closed now"
End Sub
Create a new module and add the code below in it.
Option Explicit
Dim objApp As clsIE
Sub Tester()
'// Ivan F Moala
Set objApp = New clsIE
With objApp
.IE.FullScreen = True
.IE.Visible = True
.IE.Navigate ("http://example.com")
End With
End Sub
Now if you run the module and try to close the IE browser manually then it will show a message. Further, you can try to modify the code as per your requirements.
Reference:
Code in IE's Close event

“Compile error: the variable has not been defined” using call function

I have a macro that opens a web page, assigns certain variables and then calls another procedure using the Call function. I would need to use some of the variables defined in the first procedure (for example numberOfPages) in the second procedure but I get the following error:
Compile error: the variable has not been defined
Can someone please tell me what the error is and how to solve it? I detail below both procedures.
Sub test()
Dim element As IHTMLElement
Dim elements As IHTMLElementCollection
Dim ie As InternetExplorer
Dim numberOfPages As Double
Dim html As HTMLDocument
Set ie = New InternetExplorer
ie.Visible = True
ie.navigate "https://cebra.com.ar/category/73/Juego-de-Construccion.html"
Do While ie.readyState <> READYSTATE_COMPLETE
Application.StatusBar = "Loading Web page …"
DoEvents
Loop
Set html = ie.document
Set elements = html.getElementsByClassName("container")
Set ElementCol = html.getElementsByTagName("a")
numberOfPages = ie.document.querySelectorAll(".setPage").Length
'MsgBox numberOfPages
For Each ele In ie.document.getElementsByTagName("li")
For Each element In elements
If element.className = "container" Then
'Do something
Call procedure
End If
Next element
Next
MsgBox "Done"
End Sub
Option Explicit
Public Sub procedure()
MsgBox numberOfPages
'I want to use the internet explorer opened and this variable to do something
End Sub
As #Karlomanio said, you need to pass variables to your sub-procedure (and please don't call it "procedure").
Here's your code, adjusted to make numberOfPages work:
Option Explicit
Public Sub WebProcedure(numberOfPages as Long)
MsgBox numberOfPages
'Do something here based on the number of pages
End Sub
This would be called using the following line in your test() sub:
WebProcedure numberOfPages

How can I get to click on a hypertext within the source code?

I have started to write these command lines, but does seem to work correctly...
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = Range("Name").Row And Target.Column = Range("Name").Column Then
Dim HTMLdoc As HTMLDocument
Dim downloadLink As HTMLAnchorElement
Dim i As Long
Dim ie As New InternetExplorer
With ie
.Visible = True
.navigate "http://www.XXXXXXXXXX" & Range("Name").Value
While .Busy Or .readyState <> 4
DoEvents
Wend
Set HTMLdoc = .document
End With
Dim Elmt As IHTMLElement
Dim Elm_Children As IHTMLElementCollection
Elm = HTMLDocument.getElementById("tableList2")
Elm_Children = Elm.Children
ElmChildren.FirstChild.Click
ie.Quit
End If
End Sub
The source code looks like this :
The main idea is to open a search page and picup a search request listed in an Excel sheet, then click on the first hit and finaly scrap information in the new page: paste these informations in the same sheet but different lines.
Thanks a lot for the help :-)
You can try
HTMLDoc.querySelector("#tableList2 .lstw4 a[onclick]").Click
Or even
HTMLDoc.querySelector("#tableList2 [onclick*='openMainWindow']").Click
These use # id selector to get the table, . class selector in the first in descendant combinator to get the element with class lstw4 within the table, both above use an attribute selector to target the onclick attribute. The first simply by going for first child a tag with onclick attribute and parent class lstw4, the second by onclick whose value contains openMainWindow.

Get a single value from a table with no ID with VBA

I am developing a web bot that scrapes the importation taxes from different countries customs website, and I have a problem retrieving the value I want from the following site : http://www.aduanet.gob.pe/itarancel/arancelS01Alias , using the test value 3303000000 next to CODIGO. The value I want to retrieve is the 6% next to "Ad / Valorem", but the table it is in has no ID properties nor class or something relevant to get directly to it or at least near to it. I have been trying to use .parent and .child methods, but without success. My code so far is as follows:
Function Peru(partida As String) As String
'Open IE
Set objIE = New InternetExplorer
objIE.Visible = True
objIE.navigate "http://www.aduanet.gob.pe/itarancel/arancelS01Alias"
'Load sub
Cargar
'Navigate further into the website (Im using partida = 3303000000)
For Each box In objIE.document.getElementsByTagName("input")
If box.Name = "cod_partida" Then
box.Value = partida
Exit For
End If
Next
For Each boton In objIE.document.getElementsByTagName("input")
If boton.Value = "Consultar" Then
boton.Click
Exit For
End If
Next
'Get the 6% value (This part is the one I cant figure out)
End Function
This is how you can get the data from that page. It was needed to switch two iframes from that page to reach the required content.
Sub Aduanet_Info()
Dim IE As New InternetExplorer, html As HTMLDocument
Dim elem As Object, frm As Object, frm1 As Object
With IE
.Visible = False
.navigate "http://www.aduanet.gob.pe/itarancel/arancelS01Alias"
Do While .readyState <> READYSTATE_COMPLETE: Loop
Set html = .document
End With
html.getElementsByTagName("input")(0).Value = "3303000000"
html.getElementsByTagName("input")(3).Click
Application.Wait Now + TimeValue("00:00:05")
Set frm = html.getElementsByClassName("autoHeight")(0).contentWindow.document
Set frm1 = frm.getElementsByClassName("autoHeight")(1).contentWindow.document
For Each elem In frm1.getElementsByTagName("td")
If InStr(elem.innerText, "Valorem") > 0 Then MsgBox elem.NextSibling.NextSibling.innerText: Exit For
Next elem
IE.Quit
End Sub
Output:
6%

Resources