I am working on a web automation project. I have come up to a web drop box to where I have to choose a value. I have a query selector which works fine in doing the job but now I want that query selector to find those values in the drop box which are taken from a cell value of excel sheet.
With .document.querySelector("[value='536']")
.Selected = True
.dispatchEvent evt
End With
Above is the query which works fine. But now I want to replace "536" from cell "A1" .
I have tried to replace ("[value='536']") with ([value='thisWorkbool.sheets.("sheet1").Range(A1).value']") but it shows error.
Option Explicit
Public Sub FillForm()
Dim ie As Object, tool As Workbook
Set tool = ActiveWorkbook
Set ie = CreateObject("InternetExplorer.application")
With ie
.Visible = True
.navigate "https://******.com/"
While .Busy Or .readyState < 4: DoEvents: Wend
With .document
.getElementById("txtUserName").Value = "09100107801-01"
.getElementById("txtPassword").Value = "Abc#1234"
.getElementById("btnSubmit").Click
End With
While .Busy Or .readyState < 4: DoEvents: Wend
.navigate "https://***************"
While .Busy Or .readyState < 4: DoEvents: Wend
Dim evt As Object
Set evt = .document.createEvent("HTMLEvents")
evt.initEvent "change", True, False
With .document.querySelector("[value='536']")
.Selected = True
.dispatchEvent evt
End With
end sub
How to put the value from the cell value "A1" of exel sheet in above code.
Something like this should work:
Dim v
v = thisWorkbook.sheets("sheet1").Range("A1").value
With .document.querySelector("[value='" & v & "']")
.Selected = True
.dispatchEvent evt
End With
I'm trying to understand why my references arent working well to scrape this data.
Here is the site as an example:
http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX®ion=USA&culture=en-CA&ops=clear
And as a target:
<div id="data_i6" class="rf_crow"><div id="Y_1" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="741131269">741</div><div id="Y_2" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="836611464">837</div><div id="Y_3" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="939841654">940</div><div id="Y_4" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="1010472512">1,010</div><div id="Y_5" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="1100344312">1,100</div><div id="Y_6" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="1115401551">1,115</div></div>
What I need to extract is the actual value in rawvalue="741131269" and the following is what I've gotten to work so far.
'Cells(1, 1) = Document.getElementsByClassName("rf_crow")'returns the rows of data into one cell
'Cells(1, 1) = Document.getElementById("Y_1").innerText 'returns the text for the year
'Cells(1, 1) = Document.getElementById("data_i1").innerText 'returns to first row of data
I know the above doesn't return what I want, because the comment tells you what it extracts into Excel. The sub-element doesn't seem to work as it does in other macros I've built. I thought something like this would work:
Cells(1, 1) = Document.getElementById("Y_1").getAttribute("rawvalue")
but that doesn't work, also, I tried:
Cells(1, 1) = Document.getElementById("data_i6").getElementById("Y_1").innertext
and that doesn't work either.
The solution is very easy. Just call it using it's attribute which is `rawvalue.
This is how you can go:
Using Hardcoded delay and for loop to check the availability of the desired value:
Sub GetValue()
Dim IE As New InternetExplorer, HTML As HTMLDocument, post As Object, elem As Object
With IE
.Visible = True
.Navigate "http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX®ion=USA&culture=en-CA&ops=clear"
While .Busy = True Or .ReadyState < 4: DoEvents: Wend
Set HTML = .Document
End With
''using hardcoded delay
Application.Wait Now + TimeValue("00:00:05")
For Each elem In HTML.getElementsByTagName("div")
If elem.innerText = "741" Then MsgBox elem.getAttribute("rawvalue"): Exit For
Next elem
End Sub
Using Explicit Wait:
Sub GetValue()
Dim IE As New InternetExplorer, HTML As HTMLDocument, post As Object
With IE
.Visible = True
.Navigate "http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX®ion=USA&culture=en-CA&ops=clear"
While .Busy = True Or .ReadyState < 4: DoEvents: Wend
Set HTML = .Document
End With
Do: Set post = HTML.querySelector("#data_i6 #Y_1"): DoEvents: Loop While post Is Nothing
MsgBox post.getAttribute("rawvalue")
End Sub
Output at this moment:
741131269
The following should illuminate some of the problems you were having.
.querySelectorAll
The exact element you mention is the second index returned by .querySelectorAll method of .document using the CSS selector #Y_1. The # means Id.
From that webpage it returns the following (sample shown - not all):
From the above you can see the string you want is returned by the index of 2 in the result.
querySelectorAll with Id? Isn't Id a unique identifier for a single element?
This Id, unexpectedly, is not unique to a single element on the page. It occurs a whopping 27 times:
This means you can use the .querySelectorAll method to return a nodeList of all matching items and take the item at index 2 to get your result.
Note:
If you want the long number next to rawvalue, 741131269, then parse the outerHTML of the returned element.
Debug.Print Replace(Split(Split(a.item(2).outerHTML, "rawvalue=")(1), ">")(0), Chr$(34), vbNullString)
.querySelector
Alternatively, you can target the id which is specific data_i6 with
.document.querySelector("#data_i6")
This CSS selector (#data_i6) returns the entire row as it has each year within. If using .querySelector you will only get the first item anyway which is year 1.
You can be more specific with the CSS selector and add the additional year Id to get just the year of interest:
#data_i6 #Y_1
Code: (querySelector method commented out next to querySelectorAll)
Option Explicit
Public Sub Get_Information()
Dim IE As New InternetExplorer
With IE
.Visible = True
.navigate "http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX®ion=USA&culture=en-CA&ops=clear"
While .Busy = True Or .readyState < 4: DoEvents: Wend
Dim a As Object, exitTime As Date
exitTime = Now + TimeSerial(0, 0, 2)
Do
DoEvents
On Error Resume Next
Set a = .document.querySelectorAll("#Y_1") ' .document.querySelector("#data_i6 #Y_1")
On Error GoTo 0
If Now > exitTime Then Exit Do
Loop While a Is Nothing
If a Is Nothing Then Exit Sub
Debug.Print Split(Split(a.item(2).innerText, "rawvalue=")(0), ">")(0) 'Split(Split(a.innerText, "rawvalue=")(0), ">")(0)
Debug.Print Replace(Split(Split(a.item(2).outerHTML, "rawvalue=")(1), ">")(0), Chr$(34), vbNullString) 'Replace(Split(Split(a.outerHTML, "rawvalue=")(1), ">")(0), Chr$(34), vbNullString)
.Quit
End With
End Sub
Try and declare "objCollection" as an object, strValue as string, and in the code below, replace in the first line the name of the http-request you declared:
Document.body.innerHTML = YourHTTPRequest.responseText
Set objCollection = Document.getElementsByClassName("rf_crow")
For Each objElement In objCollection
If objElement.ID = "Y_1" Then
strValue = objElement.getAttribute("rawvalue")
Exit For
End If
Next
Cells(1, 1) = strValue
Does this work for you?
Sub web_table_option_two()
Dim HTMLDoc As New HTMLDocument
Dim objTable As Object
Dim lRow As Long
Dim lngTable As Long
Dim lngRow As Long
Dim lngCol As Long
Dim ActRw As Long
Dim objIE As InternetExplorer
Set objIE = New InternetExplorer
objIE.Navigate "http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX®ion=USA&culture=en-CA&ops=clear"
Do Until objIE.ReadyState = 4 And Not objIE.Busy
DoEvents
Loop
Application.Wait (Now + TimeValue("0:00:03")) 'wait for java script to load
HTMLDoc.body.innerHTML = objIE.Document.body.innerHTML
With HTMLDoc.body
Set objTable = .getElementsByTagName("table")
For lngTable = 0 To objTable.Length - 1
For lngRow = 0 To objTable(lngTable).Rows.Length - 1
For lngCol = 0 To objTable(lngTable).Rows(lngRow).Cells.Length - 1
ThisWorkbook.Sheets("Sheet1").Cells(ActRw + lngRow + 1, lngCol + 1) = objTable(lngTable).Rows(lngRow).Cells(lngCol).innerText
Next lngCol
Next lngRow
ActRw = ActRw + objTable(lngTable).Rows.Length + 1
Next lngTable
End With
objIE.Quit
End Sub
I am trying to login to this webpage, https://www.fois.indianrail.gov.in/ecustomer/JSP/QryInsight.jsp
using VBA. Debugging shows me that the VBA throws an error 424 object required when username line is active (apparently it is not able to fill the username data).
Here's the code:
Sub Test()
Set ie = CreateObject("InternetExplorer.application")
ie.Visible = True
ie.Navigate ("https://www.fois.indianrail.gov.in/ecustomer/JSP/QryInsight.jsp")
With ie.document
.getElementById("txtUserId").Value = "ABCDE"
.getElementById("txtPassword").Value = "ABCDE"
.getElementById("submit").Click
End With
End Sub
Can anyone help me with debugging the problem while logging in to the given webpage?
Take a look at the below example:
Option Explicit
Sub Test()
Dim oIE As Object
Set oIE = CreateObject("InternetExplorer.application")
With oIE
.Visible = True
.Navigate ("https://www.fois.indianrail.gov.in/ecustomer/JSP/QryInsight.jsp")
Do While .ReadyState < 4 Or .Busy
DoEvents
Loop
With .Document
Do While .ReadyState <> "complete"
DoEvents
Loop
With .parentWindow.frames("frmCUMain").document
.getElementsByName("txtUserId")(0).Value = "ABCDE"
.getElementsByName("txtPassword")(0).Value = "ABCDE"
.getElementsByName("cmdLogin")(0).Click
End With
End With
End With
End Sub
I used the below code for loading the web site http://www.flashscore.com/soccer/england/premier-league/results/.
After I found and click on the "Show more matches" link, all the football matches are loaded in the browser.
The below code will give as results only the first half of matches, the events showed before pressing the "Show more matches" link.
My question is how can I list all the events URL adress?
Sub Test_Flashscore()
Dim URL As String
Dim ie As New InternetExplorer
Dim HTMLdoc As HTMLDocument
Dim dictObj As Object: Set dictObj = CreateObject("Scripting.Dictionary")
Dim tRowID As String
URL = "http://www.flashscore.com/soccer/england/premier-league/results/"
With ie
.navigate URL
.Visible = True
Do Until .readyState = READYSTATE_COMPLETE: DoEvents: Loop
Set HTMLdoc = .document
End With
For Each objLink In ie.document.getElementsByTagName("a")
If Left(objLink.innerText, 4) = "Show" Or Left(objLink.innerText, 4) = "Arat" Then
MsgBox "The link was founded!"
objLink.Click
Exit For
End If
Next objLink
With HTMLdoc
Set tblSet = .getElementById("fs-results")
Set mTbl = tblSet.getElementsByTagName("tbody")(0)
Set tRows = mTbl.getElementsByTagName("tr")
With dictObj
'If if value is not yet in dictionary, store it.
For Each tRow In tRows
'Remove the first four (4) characters.
tRowID = Mid(tRow.ID, 5)
If Not .Exists(tRowID) Then
.add tRowID, Empty
End If
Next tRow
End With
End With
i = 14
For Each Key In dictObj
ActiveSheet.Cells(i, 2) = "http://www.flashscore.com/" & Key & "/#match-summary"
i = i + 1
Next Key
Set ie = Nothing
MsgBox "Process Completed"
End Sub
You need to wait a little while for the rest of the content to load - clicking the link fires off a GET request to the server, so that needs to return content and the content needs to be rendered on the page before you can grab it.
Clicking on that link takes you to fixtures. You can replace all that before dictionary with
.navigate "https://www.flashscore.com/football/england/premier-league/fixtures/"
That is:
Option Explicit
Public Sub GetInfo()
Dim IE As New InternetExplorer
With IE
.Visible = True
.navigate "https://www.flashscore.com/football/england/premier-league/fixtures/"
While .Busy Or .readyState < 4: DoEvents: Wend
'other code...using dictionary
'.Quit
End With
End Sub
I am in need of assistance. I am trying to write a VBA script that would take the value in column A and place it on an online form in an input element with no ID but the name ("OldUrl"). Then the VBA script would take the value in the adjacent cell in column B and place that in the same form ("digiSHOP") in the input field named ("NewUrl").
The form is on a secure server however I have gotten as far as the window pulling up and the form selected. I am having trouble finding a way to target the input field since they have no ID. Below is my code and thank you for your help.
Sub Redirect()
Dim IE As Object
Dim doc As Object
Dim form As Object
Dim OldURL As Object
Dim NewURL As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "https://...."
Do Until .ReadyState = 4: DoEvents: Loop
Set doc = IE.Document
Set form = doc.forms("digiSHOP")
Set OldURL = doc.getElementById("OldUrl")'Error occurs here. Element has no ID
OldURL.Value = Range("A2")
Set NewURL = doc.getElementById("NewUrl")
NewURL.Value = Range("B2")
form.submit
Do Until .ReadyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
End With
End Sub
Also I wasn't sure how to target the entire column and loop it therefore the Value is set to the cell A2. This was more to test the script.
Sub Redirect()
Dim IE As Object
Dim doc As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "https://...."
Do Until .ReadyState = 4: DoEvents: Loop
With .Document.forms("digiSHOP")
.elements("OldUrl").Value = Range("A2")
.elements("NewUrl").Value = Range("B2")
.submit
End With
Do Until .ReadyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
End With
End Sub