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
Related
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
I got the below vba code from this site. The code will automatically open the site in IE(will be using different url) and will import files as well. When I ran this code,it did not work due to incorrect elementsTagName and maybe InputType as well. What should be the correct codes? I am not sure. The second part is the html codes.
Please help check the codes.
Sub File_Test()
Dim HTMLDoc As MSHTML.HTMLDocument
Dim HTMLButtons As MSHTML.IHTMLElementCollection
Dim HTMLButton As MSHTML.IHTMLElement
Dim btnInput As MSHTML.IHTMLInputElement
Dim ie As Object
Dim pointer As Integer
Set ie = CreateObject("internetexplorer.application")
ie.Visible = True
ie.navigate "http://www.htmlquick.com/reference/tags/input-file.html"
Do While ie.readyState <> READYSTATE_COMPLETE
Loop
Set HTMLDoc = ie.document
Set HTMLButtons = HTMLDoc.getElementsByTagName("Upload Files")
For Each HTMLButton In HTMLButtons
For Each btnInput In HTMLButtons
If btnInput.Type = "button" Then
HTMLButton.Click btnInput.Value = "C:\temp\test.txt"
pointer = 1
Exit For
End If
Next
btnInput
If pointer = 1 Then Exit For
Next
End sub
<button title="Upload Files" class="button button--white xc-action-nav__button ng-binding ng-scope" type="button" loading-key="0" ng-click="setLoading('group1', '0'); " ng-disabled="isLoading('group1', null)"><span class="spinner-transition" ng-class="{'spinner spinner--is-loading': isLoading('group1', '0')}"></span> Upload Files</button>
Some pointers:
This HTMLButton.Click btnInput.Value = "C:\temp\test.txt" should be on two separate lines.
HTMLButton.Click
btnInput.Value = "C:\temp\test.txt"
I think the second line is redundant. Your code is missing the more complex instructions required to interact with the file dialog for inputing the filepath. A subject for a whole other question which has been addressed elsewhere on SO.
The "buttons" are input tag elements and you need to limit to the appropriate three.
Dim uploads As Object, i As Long
Set uploads = ie.document.querySelectorAll("#examples [type=file]")
For i = 0 To uploads.Length-1
uploads.item(i).click
'other code
Next
My advice would be to try and code with the actual url and share the problems you are having with the actual scenario. The code above, IMO, is not fit for purpose for the url given.
I tested it but it is not working. I received Run Time Error '-2147417848 (80010108). THE OBJECT INVOKED HAS DISCONNECTED FROM ITS CLIENTS after I clicked F8 in the Loop line.. Below is the new code as per your suggestion. What is causing this issue? Apologies if I postes my comment here as a simple Add Comment does not allow me to put the codes. Thanks for your time!
Private Sub CommandButton21_Click() Dim ie As Object Dim uploads As Object, i As Long Set ie = CreateObject("internetexplorer.application") ie.Visible = True ie.navigate "http://www.htmlquick.com/reference/tags/input-file.html" Do While ie.readyState <> 4 Loop Set uploads = ie.document.querySelectorAll("#examples [type=file]") For i = 0 To uploads.Length - 1 uploads.Item(i).Click'other code Next End Sub
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.
I'm trying to use a loop to get the data from web to excel sheet. I will attach the sheet and also paste the code here. Please help me with this. Thank you.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = Range("Number").Row And _
Target.Column = Range("Number").Column Then
Dim IE As New InternetExplorer
IE.Visible = True
IE.navigate "https://www.truecaller.com/search/in/" & Range("Number").Value
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Dim Doc As HTMLDocument
Set Doc = IE.document
Dim sdd As String
sdd = Doc.getElementsByClassName("profile-name").innerText
MsgBox sdd
End If
End Sub
WHEN I USE ABOVE CODE I GET THE BELOW ERROR
Run-time error '438':
Object doesn't support this property or method
.
See how .getElementsByClassName is plural? .getElementsByClassName returns a collection, not a single object. In essence, you are trying to treat an array of integers as a single integer; they are not the same thing.
You cannot simply remove the s; there is no getElementByClassName function. However, you can ask for the first element the same way you specify an individual integer within an array of integers.
sdd = Doc.getElementsByClassName("profile-name")(0).innerText
Sub Extractdatafromwebsite()
Dim ie As InternetExplorer
Dim Eventno As String
Dim doc As HTMLDocument
Eventno = Sheet1.Range("A2").Value
ie.Visible = True
ie.navigate "https://www.bankeauctions.com/#" & Eventno
Do
DoEvents
Loop Until ie.readyState = READYSTATE_COMPLETE
Set doc = ie.document
On Error Resume Next
output = doc.getElementById("ContentPlaceHolder1_lblReserverPrice" & Eventno).innerText
Sheet1.Range("B2").Value = output
ie.Quit
You haven't actually created an instance of IE yet, so there's nothing to make visible
Dim IE As InternetExplorer
Set IE = New InternetExplorer '// <~~ The bit you need
IE.Visible = True
...
When you Dimension a variable, you are simply reserving some memory in order to place something there. Data types (such as Integer or String) do not need to be Set - but Internet Explorer is an Object
An Object needs to be built and in order to do that, the system needs some instructions - a blueprint if you will - of how to build that object. This is called a Class.
You have asked the system to reserve some memory for your IE object, but until you actually create the object and place it in that memory, there is nothing to interact with and so you receive that error.
Hope that makes sense.
You have declared a variable using Dim but you have not initiated an instance. It's like when you're having a baby. You can name it before it's born but you can't really call it (as you call anyone) with its name until it's born (initiated).
Sub Main()
Dim Mike As baby
Set Mike = new baby
Mike.PeekaBoo
'baby laughs
End Sub
Sub Main()
Dim Mike As baby
Mike.PeekaBoo
'Returns an error as an instance of the baby class is not found
End Sub