How to use wildcard in excel vba internet explorer - vba

could you please tell me how to use wildcards in excel vba internet explorer?
id="btn_edit_card_1NLQNQD0D93O"
everytime that number in different. How to click that button via
document.getElementById
There is no class in code
<a id="btn_edit_card_1NLQNQD0D93O" href="/trades/bejelentes_egyszerusitett/1NLQNQD0D93O">Editing basic data</a>

As #Nathan_Sav suggested, very wisely I might add, that you will have to work around your problem with collections. For example, loop through all the "a" tags until you find one that "btn_edit_card_" as part of it's name. This will work unless there are more than one "a" tags with that phrase in it.
Set els = ie.Document.getElementsByTagName("a")
For Each el In els
If el.ID Like "btn_edit_card*"
el.click
Exit For
' Debug.Print el.ID, el.Name
End If
Next el

If your IE version is 9 or above you can use the querySelectorAll method of the HTMLDocument class.
This uses CSS selectors to enable filtering of elements by their attributes. In your case you are looking for a elements with an id beginning with btn_edit_card. The selector for this would be:
a[^=btn_edit_card]
Where the ^= means begins with.
See the example code below that pulls comments from this very page - they are all tr elements in a table beneath your question which all have id of comment-123456 where the number can change from comment to comment (because they are stored uniquely in the database etc):
Option Explicit
Sub GetElementByWildcard()
Dim objIe As InternetExplorer
Dim objDoc As HTMLDocument
Dim objElements As IHTMLDOMChildrenCollection
Dim objElement As Object
Dim lngCounter As Long
On Error GoTo ExitFunction
'get page content
Set objIe = New InternetExplorer
objIe.Visible = False
objIe.navigate "http://stackoverflow.com/questions/42225761/how-to-use-wildcard-in-excel-vba-internet-explorer"
Do While objIe.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
'get document
Set objDoc = objIe.document
'get any <tr> with an id starting with comment-
Set objElements = objDoc.querySelectorAll("tr[id^=comment-]")
'iterate output
lngCounter = 0
While lngCounter < objElements.Length
Set objElement = objElements.Item(lngCounter)
Debug.Print objElement.innerText
lngCounter = lngCounter + 1
Wend
ExitFunction:
If Err.Number <> 0 Then
Debug.Print Err.Description
End If
objIe.Quit
Set objDoc = Nothing
Set objIe = Nothing
End Sub

Related

Pilot freight tracking macro working on one computer but not another

Recently our office upgraded to new laptops. Luckily in changing over from Windows 7 to 10 and from desktop to Laptops we did not experience any issues with running this macro other than needing to enable popups on Pilotdelivers.com. For a few weeks now we've run this macro on two different laptops and everything has gone smoothly.
Today, on one of the laptops the macro is no longer working correctly, but on the other it's fine. I checked to make sure popups were enabled and that both computers are running from the same excel worksheet on our network. I restarted the computer twice and ran the macro with no other applications open. Laptops are the same model, installed at the same time. Identical software installations and updates. The laptop that is having trouble is used by my less computer savvy co worker and the laptop that's working is mine. So it's possible that there's some setting he changed that he shouldn't have, but I'm not sure what to check.
It seems like it's skipping the portion of code that clicks a link to open a new tab.
What the macro is supposed to do:
copy the tracking number on the worksheet
open IE
insert the tracking number into the text box
click track
wait for the new page to load
click the tracking number link
wait for the new tab to load
close the first tab
check to see if the most recent update is DELIVERED
if yes it switches back to excel and inputs DELIVERED and the
delivery date, if not it looks at the most recent update and adds
that line to the worksheet.
What seems like the macro is doing:
copy the tracking number on the worksheet
open IE
insert the tracking number into the text box
click track
wait for the new page to load
seems to skip clicking on the tracking number link
wait for the current page to load (which is already loaded)
when looking for the latest update it grabs the tracking number
instead (since it's not the expected page)
check to see if it's marked DELIVERED
10.if yes it switches back to excel and inputs DELIVERED and the
delivery date, if not it looks at the most recent update and adds
that line to the worksheet
It seems like it skips some or all of this section of code:
Dim ieDOC As HTMLDocument
Set ieDOC = ie.document
Set htmlColl = ieDOC.getElementsByTagName("a")
For Each htmlInput In htmlColl
If htmlInput.ID = "clickElement" Then
htmlInput.Click
Exit For
End If
Next htmlInput
ie.Quit
Set shellWins = New ShellWindows
If shellWins.Count > 0 Then
Set ie2 = shellWins.Item(1)
End If
Full code below:
Sub PilotTracking()
Dim ProURL As String
Dim ie As Object
Dim ie2 As Object
Dim RowCount As Integer
Dim i As Integer
Dim html_Document As HTMLDocument
Dim htmlColl As MSHTML.IHTMLElementCollection
Dim htmlInput As MSHTML.HTMLInputElement
Dim shellWins As ShellWindows
Dim htmlColl2 As MSHTML.IHTMLElementCollection
Dim htmlInput2 As MSHTML.HTMLInputElement
Dim marker As Integer
RowCount = 0
ProURL = "http://www.pilotdelivers.com/"
Do While Not ActiveCell.Offset(RowCount, -5).Value = ""
Set ie = CreateObject("InternetExplorer.application")
With ie
.Visible = True
.navigate ProURL
Do Until Not ie.Busy And ie.readyState = 4: DoEvents: Loop
End With
Set Doc = ie.document 'works don't delete
Doc.getElementById("tbShipNum").innerHTML = ActiveCell.Offset(RowCount, -5).Value 'works don't delete
Doc.getElementById("btnTrack").Click 'works don't delete
Do Until Not ie.Busy And ie.readyState = 4: DoEvents: Loop
i = 0
Do While i < 4
WaitHalfSec
i = i + 1
Loop
Do Until Not ie.Busy And ie.readyState = 4: DoEvents: Loop
Dim ieDOC As HTMLDocument
Set ieDOC = ie.document
Set htmlColl = ieDOC.getElementsByTagName("a")
For Each htmlInput In htmlColl
If htmlInput.ID = "clickElement" Then
htmlInput.Click
Exit For
End If
Next htmlInput
ie.Quit
Set shellWins = New ShellWindows
If shellWins.Count > 0 Then
Set ie2 = shellWins.Item(1)
End If
i = 0
Do While i < 8
WaitHalfSec
i = i + 1
Loop
Do Until Not ie2.Busy And ie2.readyState = 4: DoEvents: Loop
Set htmlColl2 = ie2.document.getElementsByTagName("td")
For Each htmlInput2 In htmlColl2
If htmlInput2.className = "dxgv" Then
If ActiveCell.Offset(RowCount).Value = "" Then
ActiveCell.Offset(RowCount).Value = htmlInput2.innerText
Else
If ActiveCell.Offset(RowCount).Value <> "DELIVERED" Then
ActiveCell.Offset(RowCount, -2).Value = ""
Else
ActiveCell.Offset(RowCount, -2).Value = htmlInput2.innerText
End If
Exit For
End If
End If
Next htmlInput2
ie2.Quit
Set shellWins = Nothing
Set ie = Nothing
Set ie2 = Nothing
RowCount = RowCount + 1
Loop
Set shellWins = Nothing
Set ie = Nothing
Set ie2 = Nothing
End Sub
Sub WaitHalfSec()
Dim t As Single
t = Timer + 1 / 2
Do Until t < Timer: DoEvents: Loop
End Sub
Instead of this:
Set htmlColl = ieDOC.getElementsByTagName("a")
For Each htmlInput In htmlColl
If htmlInput.ID = "clickElement" Then
htmlInput.Click
Exit For
End If
Next htmlInput
You should be able to just do this:
ieDOC.getElementById("clickElement").Click
Id is supposed to be unique within a given page. I see you've used getElementById elsewhere, so was there some reason it's not used here?
I'd guess maybe the problem is this:
ie.Quit
so try commenting that out. Something to do perhaps with where new pages load (new window vs new tab?)
If you're having problems grabbing the correct IE document, then try something like:
Function GetIE(sLocation As String) As Object
Dim objShell As Object, objShellWindows As Object, o As Object
Dim sURL As String
Dim retVal As Object
Set retVal = Nothing
Set objShell = CreateObject("Shell.Application")
Set objShellWindows = objShell.Windows
For Each o In objShellWindows
sURL = ""
On Error Resume Next
'check the URL and if it's the one you want then
' assign it to the return value and exit the loop
sURL = o.document.Location
On Error GoTo 0
If sURL Like sLocation & "*" Then
Set retVal = o
Exit For
End If
Next o
Set GetIE = retVal
End Function
This function will return an IE window which matches the provided URL (i.e. the first on whose URL begins with the passed sLocation string)

Scraping a single value from an HTML table and inserting into an Excel cell with VBA

Please see the code below. I am compiling a list of unusual currency pairings in excel and I wish to scrape this data with VBA. I only want to insert the value itself into the cell. Does anyone know where I am going wrong here? I am getting a 'Run-time error '91': object variable or With block variable not set'. I'm relatively new to VBA and i've put a lot a deal of thought into this.
Sub ie_open()
Dim wb As Workbook
Dim ws As Worksheet
Dim TxtRng As Range
Dim ie As Object
Set ie = CreateObject("INTERNETEXPLORER.APPLICATION")
ie.NAVIGATE "http://www.barchart.com/quotes/forex/British_Pound/Costa_Rican_Colon/%5EGBPCRC"
ie.Visible = True
While ie.ReadyState <> 4
DoEvents
Wend
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Test Sheet")
Set TxtRng = ws.Range("A1")
TxtRng.Value = ie.document.getelementsbyname("divQuotePage").Item.innertext
End Sub
This is the data which I am trying to scrape:
Thanks.
I'm not that accomplished at web scraping, but that kind of error often means that what you are looking for isn't there. In particular, I don't see divQuotePage in the screen shot you provided.
But if you want the quote (793.19) you could do something like:
Dim V As Variant
Set V = ie.document.getelementbyid("dtaLast")
TxtRng = V.innertext
This will work.
Sub Test()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "http://www.barchart.com/quotes/forex/British_Pound/Costa_Rican_Colon/%5EGBPCRC" ' should work for any URL
Do Until .ReadyState = 4: DoEvents: Loop
x = .document.body.innertext
y = InStr(1, x, "Last Price")
Z = Mid(x, y, 19)
Range("A1").Value = Trim(Z)
.Quit
End With
End Sub
You can target that element with a CSS selector of div.pricechangerow > span.last-change;
which can be simplified to .last-change.
The "." means class and you can retrieve this specific item with
Debug.Print ie.document.querySelector.querySelector(".last-change").innerText
That is for the website's current incarnation at 2018-06-30

IE button click with VBA

Can't get the "GO" button to click via VBA on this site: https://finra-markets.morningstar.com/BondCenter/BondDetail.jsp?ticker=C631551&symbol=RDS4242315
Will eventually want to loop code. Should be simple...just can't get this one.
Sub Macro1()
'we define the essential variables
Dim ie As Object
Dim acct
Dim button
Set Rng = Range("B4:B4")
Set Row = Range(Rng.Offset(1, 0), Rng.Offset(1, 0).End(xlDown))
For Each Row In Rng
'add the "Microsoft Internet Controls" reference in your VBA Project indirectly
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.navigate ("https://finra-markets.morningstar.com/BondCenter/BondDetail.jsp?ticker=C631551&symbol=RDS4242315")
While ie.ReadyState <> 4
DoEvents
Wend
Set Cusip = .document.getElementById("ms-finra-autocomplete-box") 'id of the username control (HTML Control)
Cusip.Value = Range("B" & Row.Row).Value
ie.document.getElementsByTagName("submit").Click
End With
Next Row
End Sub
The tag name of your button is not "submit" but "INPUT" ... "submit" is the type.
But watch out, there are more INPUT elements, so your getElementsBy... will return a collection and you need to further dig to find the correct one, e.g. by checking a significant attribute.
Example
' ...
Set ECol = ie.document.getElementsByTagName("input")
For Each IFld In ECol
If IFld.getAttribute("class") = "button_blue autocomplete-go" Then
IFld.Click
Exit For
End If
Next IFld
' ...

VBA hanging on ie.busy and readystate check

I am trying to grab some football player data from a website to fill a privately used database. I've included the entire code below. This first section is a looper that calls the second function to fill a database. I've run this code in MSAccess to fill a database last summer and it worked great.
Now I am only getting a few teams to fill before the program gets hung up at
While IE.Busy Or IE.ReadyState <> READYSTATE_COMPLETE: DoEvents: Wend
I've searched countless websites regarding this error and tried changing this code by putting in sub function to wait a period of seconds or other work-arounds. None of those solve the issue. I've also tried running this on multiple computers.
The first computer made it through 3 teams (or three calls of the 2nd function). The second slower computer makes it through 5 teams. Both eventually hang. The 1st computer has Internet Explorer 10 and the second has IE8.
Sub Parse_NFL_RawSalaries()
Status ("Importing NFL Salary Information.")
Dim mydb As Database
Dim teamdata As DAO.Recordset
Dim i As Integer
Dim j As Double
Set mydb = CurrentDb()
Set teamdata = mydb.OpenRecordset("TEAM")
i = 1
With teamdata
Do Until .EOF
Call Parse_Team_RawSalaries(teamdata![RotoworldTeam])
.MoveNext
i = i + 1
j = i / 32
Status("Importing NFL Salary Information. " & Str(Round(j * 100, 0)) & "% done")
Loop
End With
teamdata.Close ' reset variables
Set teamdata = Nothing
Set mydb = Nothing
Status ("") 'resets the status bar
End Sub
Second function:
Function Parse_Team_RawSalaries(Team As String)
Dim mydb As Database
Dim rst As DAO.Recordset
Dim IE As InternetExplorer
Dim HTMLdoc As HTMLDocument
Dim TABLEelements As IHTMLElementCollection
Dim TRelements As IHTMLElementCollection
Dim TDelements As IHTMLElementCollection
Dim TABLEelement As Object
Dim TRelement As Object
Dim TDelement As HTMLTableCell
Dim c As Long
' open the table
Set mydb = CurrentDb()
Set rst = mydb.OpenRecordset("TempSalary")
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
IE.navigate "http://www.rotoworld.com/teams/contracts/nfl/" & Team
While IE.Busy Or IE.ReadyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set HTMLdoc = IE.Document
Set TABLEelements = HTMLdoc.getElementsByTagName("Table")
For Each TABLEelement In TABLEelements
If TABLEelement.id = "cp1_tblContracts" Then
Set TRelements = TABLEelement.getElementsByTagName("TR")
For Each TRelement In TRelements
If TRelement.className <> "columnnames" Then
rst.AddNew
rst![Team] = Team
c = 0
Set TDelements = TRelement.getElementsByTagName("TD")
For Each TDelement In TDelements
Select Case c
Case 0
rst![Player] = Trim(TDelement.innerText)
Case 1
rst![position] = Trim(TDelement.innerText)
Case 2
rst![ContractTerms] = Trim(TDelement.innerText)
End Select
c = c + 1
Next TDelement
rst.Update
End If
Next TRelement
End If
Next TABLEelement
' reset variables
rst.Close
Set rst = Nothing
Set mydb = Nothing
IE.Quit
End Function
In Parse_Team_RawSalaries, instead of using the InternetExplorer.Application object, how about using MSXML2.XMLHTTP60?
So, instead of this:
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
IE.navigate "http://www.rotoworld.com/teams/contracts/nfl/" & Team
While IE.Busy Or IE.ReadyState <> READYSTATE_COMPLETE: DoEvents: Wend
Set HTMLdoc = IE.Document
Maybe try using this (add a reference to "Microsoft XML 6.0" in VBA Editor first):
Dim IE As MSXML2.XMLHTTP60
Set IE = New MSXML2.XMLHTTP60
IE.Open "GET", "http://www.rotoworld.com/teams/contracts/nfl/" & Team, False
IE.send
While IE.ReadyState <> 4
DoEvents
Wend
Dim HTMLDoc As MSHTML.HTMLDocument
Dim HTMLBody As MSHTML.htmlBody
Set HTMLDoc = New MSHTML.HTMLDocument
Set HTMLBody = HTMLDoc.body
HTMLBody.innerHTML = IE.responseText
I've generally found that MSXML2.XMLHTTP60 (and WinHttp.WinHttpRequest, for that matter) generally perform better (faster and more reliable) than InternetExplorer.Application.
I've found this post very helpful when I encountered similiar problem. Here is my solution:
I used
Dim browser As SHDocVw.InternetExplorer
Set browser = New SHDocVw.InternetExplorer
and
cTime = Now + TimeValue("00:01:00")
Do Until (browser.readyState = 4 And Not browser.Busy)
If Now < cTime Then
DoEvents
Else
browser.Quit
Set browser = Nothing
MsgBox "Error"
Exit Sub
End If
Loop
Sometimes page is loaded but code stops on DoEvents and goes on and on and on. Using this code it goes on only for 1 minute and if browser is not ready it quits the browser and exits sub.
I know this is a old post but. I have had the same problem with my code for downloading web site pictures using Excel VBA automation. Some sites wont let you download a image file using a link without first opening the link in a browser. However my code was getting hung up sometimes with when the objBrowser.visible was set to false with the folowing code
Do Until (objBrowser.busy = False And objBrowser.readyState = 4)
Application.Wait (Now + TimeValue("0:00:01"))
DoEvents 'browser.readyState = 4
Loop
the simple fix was to make the objBrowser.visible
I fixed it with
Dim Passes As Integer: Passes = 0
Do Until (objBrowser.busy = False And objBrowser.readyState = 4)
Passes = Passes + 1 'count loops
Application.Wait (Now + TimeValue("0:00:01"))
DoEvents
If Passes > 5 Then
'set size browser cannot set it smaller than 400
objBrowser.Width = 400 'set size
objBrowser.Height = 400
Label8.Caption = Passes 'display loop count
' position browser "you cannot move it off the screen" ready state wont change
objBrowser.Left = UserForm2.Left + UserForm2.Width
objBrowser.Top = UserForm2.Top + UserForm2.Height
objBrowser.Visible = True
DoEvents
objBrowser.Visible = False
End If
Loop
objBrowser only flashes for less than a second but it gets the job done!

if statement with getelementbyclass

First off, I am relatively new to programming. I have been making myself familiar primarily with VBA. I have asked questions here before and so far the responses have been very helpful so I am trying my luck again.
I am going to this site: http://www.otcmarkets.com/stock-screener
I want my script to say something like:
if ElementClassName("listingOdd").innertext = "USA, NV"
then GetElementsbyClassName("listingOddlistingOdd whiteSpaceNormal").innertext
I would also like it to loop through and click the next button which is behind this html until it is completed :
a href="javascript:void(null);">next & gt;/a
Any help is welcomed, I have been searching through past questions and watching tutorials and would not be asking if I was not seriously banging my head on this one. Thanks a lot in advance
This is some code that I have tried, with the following error: "Object doesnt support this method"
There is a lot commented out from trial and error
Sub t()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
IE.navigate "http://www.otcmarkets.com/stock-screener"
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Dim Doc As HTMLDocument
Set Doc = IE.document
Dim sDD As String
Dim lnk As Variant
sDD = Trim(Doc.GetElementbyClassName("listingOddlistingOdd whiteSpaceNormal").innerText)
'If lnk.classame.innerText = "USA, NV" Then
If lnk.innerText = "USA, NV" Then
'If ElementClassName("listingOdd")(0).innerText = "USA, NV" Then
'sDD
'sDD = Trim(Doc.GetElementbyClassName("listingOddlistingOdd whiteSpaceNormal").innerText)
MsgBox sDD
End If
End Sub
Sorry for the spaghetti code, like I said I am new
I'm not really clear on exactly what you're trying to get (and why not just use the handy "download all" link at the top of the page?)
EDITED - place cell values on worksheet
EDIT2 - clicking the "next" link.
EDIT3 - looped
This kind of thing is a total rabbit hole though.
Sub Tester()
Dim doc As Object
Dim IE As Object, nxt
Dim rng As Range, x As Integer
Set rng = ThisWorkbook.Sheets("sheet1").Range("A2")
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.navigate "http://www.otcmarkets.com/stock-screener"
WaitForLoad IE
Set nxt = GetNext(IE)
Do While Not nxt Is Nothing
ExtractTableContent IE, rng
nxt.Click
WaitForLoad IE
Set nxt = GetNext(IE)
Loop
End Sub
Sub WaitForLoad(IE As Object)
Do: DoEvents: Loop Until IE.readyState = 4 'READYSTATE_COMPLETE
Application.Wait Now + TimeSerial(0, 0, 3)
End Sub
'copy table content
Sub ExtractTableContent(ByRef IE As Object, ByRef rng As Range)
Dim tableDiv As Object, r As Object, rw As Object, x As Long
Set tableDiv = IE.document.getelementbyid("stockScreenerResults")
Set r = tableDiv.getelementsbytagname("table")(0).Rows
For Each rw In r
For x = 1 To rw.Cells.Length
rng.Offset(0, x - 1).Value = rw.Cells(x - 1).innerText
Next x
Set rng = rng.Offset(1, 0)
Next rw
End Sub
'find the link which takes you to the next page...
Function GetNext(IE As Object) As Object
Dim links, l As Object, rv As Object, cn As Object
Set links = IE.document.getelementsbytagname("a")
For Each l In links
If l.innerText Like "*next*" Then
Set rv = l
Exit For
End If
Next l
Set GetNext = rv
End Function