Cant download a scorecard from pgatour.com - vba

I've searched throughout the site here to improve my simple code, but continue to have an error 424 at the set allRowofdata line, which I gleaned from here. I'm just trying to load a golfers scorecard into my excel spread. I appreciate any help I can get.
Here's my code:
Note: based on advise from below, I've changed my code to the below, but now get a type mismatch error at set allRowOfData.
Sub Trial()
Dim IE As InternetExplorer
Dim allRowOfData
Dim document As Object
Set IE = New InternetExplorer
IE.Visible = False
IE.navigate "https://www.pgatour.com/players/player.32757.patton-kizzire.html/scorecards/r457"
Do Until IE.readyState = 4: DoEvents: Loop
Set allRowOfData = IE.document.getElementById("module-1510443455695-953403-17")
Dim myValue As String: myValue = allRowOfData.Cells().innerHTML
IE.Quit
Set IE = Nothing
Range("A1").Value = myValue
End Sub

I think you've set the page element before it gets a chance to load on the page, therefore 'allRowOfData' remains nothing.
Consider replacing this:
Application.Wait Now + TimeSerial(0, 0, 1)
With:
Do Until IE.ReadyState = 4: DoEvents: Loop
Or alternatively (inefficient but can't see any reason why it wouldn't work):
Do until not(allRowOfData is nothing)
Do events
Set allRowOfData = IE.document.getElementById("#module-1510443455695-953403-17")
Loop
The above assumes your usage of .getElementByID method is correct. Untested, written on mobile.
Edit 1:
See if changing this
Dim allRowOfData
To this
Dim allRowOfData As IHTMLElement
Works.
Before you re-run code, in VBA editor, click Tools > References and add a reference to the Microsoft HTML Object Library (scroll down and tick it).
Type Mismatch would suggest we're assigning something to a variable of the wrong type, so let's get rid of the implicit variant.
I haven't been able to examine the code's HTML source as I'm on mobile. It may be the case though that the specific element that you want is created subsequent to the page's initial loading (in which case you may need to use the inefficient alternative above), or that you need to iterate through a IHTMLElementCollection to get at the information. All depends on the page's structure and loading behaviour.

Related

Error 91 Search and scrape web

I am new to VBA, and trying to put together a code that will allow me to search a website for bond information, which is listed in my excel file, and pull back the bond's issue date. I have been able to get to the website, and using F8 to execute the code manually, the code appears to work fine. However, when I run the macro, I get
Error 91: Object variable or With block variable not set.
I am unsure how to fix this issue, and I have tried to find earlier answers, as there is a lot of info on error 91. But none seem to be able to help with my specific problem.
Please assist, thanks.
Dim objIE As InternetExplorer 'special object variable representing the IE browser
Dim datelabel As String
Dim x As String 'for the CUSIP number
Dim y As Integer 'integer variable we'll use as a counter
Dim result As String 'string variable that will hold our result link
'initiating a new instance of Internet Explorer and asigning it to objIE
Set objIE = New InternetExplorer
'make IE browser visible (False would allow IE to run in the background)
objIE.Visible = False
'navigate IE to this web page
objIE.navigate "https://emma.msrb.org/Search/Search.aspx"
'wait here a few seconds while the browser is busy
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
'DATA SCRAPING Portion
Dim Doc As HTMLDocument
Set Doc = objIE.document
'get issue date
datelabel = Doc.getElementsByClassName("value")(0).innerText 'HERE IS WHERE I HAVE MY PROBLEM
'MsgBox datelabel
End If
Loop
'close the browser
objIE.Quit
This is the html that I am trying to pull:
span class="value"
from:
https://emma.msrb.org/SecurityView/SecurityDetails.aspx?cusip=ACDB05F7DCC14B929AC9D2D082A3D9AE0

getelementbytagname isn't recognized

I'm attempting to have Excel open a web site, populate some fields, submit, and download the resulting data in a file.
My code never gets very far, however, because it looks like Excel doesn't recognize "getelementsbytagname" as an existing operation. I assume this is the issue because it does not correct the case to GetElementsByTagName like it does for everything else.
My References in the editor include Microsoft Internet Controls and Microsoft HTML Object Library. Is there another one that I need to activate?
The code is just a modified version of something found online.
Private Sub IE_automation()
'Retrieve data from Enterprise Reporting with IE
Dim i As Long
Dim IE As Object
Dim objElement As Object
Dim objCollection As Object
'Create Internet Explorer Object
Set IE = CreateObject("InternetExplorer.Application")
'Comment out while troubleshooting
'IE.Visible = False
'Send the form data to URL as POST binary request
IE.Navigate "http://corpprddatawhs1/Reports/Pages/Report.aspx?ItemPath=%2fInventory%2fInventory+By+Branch"
'Set statusbar
Application.StatusBar = "Webhost data is loading. Please wait..."
'Wait while IE loading
Do While IE.busy
Application.Wait DateAdd("s", 1, Now)
Loop
'Find 2 input tags:
' 1. Text field
' <input type="text" class="null" name="ct132$ct104$1ct105$txtValue" size="30" value="" />
'
' 2. Button
' <input type="submit" value="View Report" />
Application.StatusBar = "Searching form submission. Please wait..."
Set objCollection = IE.document.getelementsbytagname("input")
My References in the editor include Microsoft Internet Controls and Microsoft HTML Object Library.
Then you have no need to do this:
Dim IE As Object
Dim objElement As Object
Dim objCollection As Object
Set IE = CreateObject("InternetExplorer.Application")
Declaring everything As Object is a technique called late-binding. In that paradigm you create a new instance of an object by passing a ProgID to the CreateObject function.
Late-bound code is, by definition, resolved at run-time: the compiler is happy with the Object interface, and the onus is on you to use the correct members.
With late-bound code you can't get IntelliSense or auto-complete, because the compiler has no idea what you're up to: all it's seeing is Object.
When you actually reference a type library, you can use early binding, which means the types and member calls are resolved at compile-time instead of run-time. But for this to work, you need to use the types you're referencing. Otherwise you're late-binding against a type library that's referenced... and late-bound code doesn't require a reference (just that some version of the type library is registered on the machine that's running the code).
Dim browser As InternetExplorer
Set browser = New InternetExplorer
browser.Navigate url
'...
Dim dom As HTMLDocument
Set dom = browser.Document
Dim inputElements As HTMLElementCollection
Set inputElements = dom.getElementsByTagName("input")
And now you're coding against an HTML DOM just like you would against any Excel worksheet, with IntelliSense and parameter info and all the goodies.
This is suspicious:
Do While IE.busy
Application.Wait DateAdd("s", 1, Now)
Loop
That wait-loop isn't even looking at the browser's ReadyState. Try this instead:
Do Until IE.ReadyState = 4 And IE.Busy = False
DoEvents
Loop
See this post for an allegedly fail-safe way to go about it.
Your code otherwise looks fine though, so my money is on the wait-loop.
Even though VBA is case-insensitive, all the methods/properties under document are case-sensitive.
A safe way to call them with late-binding is to use CallByName:
Set items = CallByName(IE.document, "getElementsByTagName", VbMethod, "input")

VBA with Excel and IE: Can't get the source right source code?

I'm currently trying to automate my IE at work with VBA and Excel, because we have some repetitive tasks to complete in an SAP System which is called within the Internet Explorer.
So far I am able to start IE and navigate to the starting page of our System.
I looked on the source code from the Sap System to search for an id from a div (lets say its 'SampleID'). But if I try to click it via VBA I only get returned 'nothing'. So I tried to print out the source code via VBA Debug.Print to look at the problem. And here's the thing:
The source code that gets printed is completely different from the Website's Source Code. In the printed code for example is a iframe that I can't find in the website source code. So that's the reason I can't find my div and any other objects, because they are not in the code that VBA is searching through.
Can anyone tell me what's going wrong? Why are the source codes completely different?
Sub stgGo(){
Dim i As Long
Dim IE As InternetExplorerMedium
Dim objElement As Object
Dim objCollection As Object
Set IE = New InternetExplorer
IE.Visible = True
IE.Navigate ("URL")
'waiting 10 seconds to be really sure javascript is ready
Application.Wait (Now + TimeValue("0:00:10"))
'printing out the false source code
Debug.Print strHTML = myIE.Document.body.innerHTML
Set objCollection = IE.document.getElementsByTagName("div")
i = 0
While i < objCollection.Length
If objCollection(i).ID = "SampleID" Then
objCollection(i).Click
End If
i = i + 1
Wend
End Sub

VBA: not able to pull value within <input> tag using getelementsbyTagname().Value

This is my first post on stackflow :) I've been Googling VBA knowledge and writing some VBA for about a month.
My computer info:
1.window 8.1
2.excel 2013
3.ie 11
My excel reference
Microsoft Object Library: yes
Microsoft Internet Controls: yes
Microsoft Form 2.0 Object library: yes
Microsoft Script Control 1.0: yes
Issue:
I was trying to retrieve data from internet explorer automatically using VBA.
I would like to retrieve the value within an input tag from a id called "u_0_1" which is under a id called "facebook". I am expecting to retrieve the value "AQFFmT0qn1TW" on cell c2. However, it got this msg popped up after I run the VBA "run-time error '91':object variable or with block variable not set.
I have been trying this for a couple of weeks using different methods such as,
1.getelementsbyClassname
2.getelementbyid
3.getelementsbyTagname
But it just doesn't work.
url:
http://coursesweb.net/javascript/getelementsbytagname
Below is my VBA code. Could you guys help me out a little bit please?
Private Sub CommandButton1_Click()
Dim ie As Object
Dim Doc As HTMLDocument
Dim getThis As String
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = 0
ie.navigate "http://coursesweb.net/javascript/getelementsbytagname"
Do
DoEvents
Loop Until ie.readyState = 4
Set Doc = ie.document
getThis = Trim(Doc.getElementById("u_0_1")(0).getElementsByTagName("input")(0).Value)
Range("c2").Value = getThis
End Sub
Thanks for your help. I have no idea that there is difference between JS and VBA in aspect of getelementsby () methods. And using the loop method to find the id which I find it very useful as well.
I still have some issues to retrieve value from a form or input type. I hope that you could help me or give me some suggestions as well.
Expected Result:
retrieve the value "AQFFmT0qn1TW" and copy it on Cell ("c2") automatically.
Actual Result:
nothing return to Cell ("C2")
Below is the HTML elements.
<form rel="async" ajaxify="/plugins/like/connect" method="post" action="/plugins/like/connect" onsubmit="return window.Event && Event.__inlineSubmit && Event.__inlineSubmit(this,event)" id="u_0_1">
<input type="hidden" name="fb_dtsg" value="AQFFmT0qn1TW" autocomplete="off">
Below is the VBA code based on your code.
Private Sub CommandButton1_Click()
Dim ie As Object
Dim Doc As HTMLDocument
Dim Elements As IHTMLElementCollection
Dim Element As IHTMLElement
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = 0
ie.navigate "http://coursesweb.net/javascript/getelementsbytagname"
Do
DoEvents
Loop Until ie.readyState = 4
Set Doc = ie.document
Set Elements = Doc.getElementsByTagName("input")
For Each Element In Elements
If Element.name = "fb_dtsg" Then
Range("c2").Value = Element.innerText
End If
Next Element
Set Elements = Nothing
End Sub
Cheers.
first of all, I can't find in source of website tags you were searching. Anyway, I think you can't chain getElementById.getElementsByTag as in JS. You have to loop through collection of document elements.
Private Sub CommandButton1_Click()
Dim ie As Object
Dim Doc As HTMLDocument
Dim Elements As IHTMLElementCollection
Dim Element As IHTMLElement
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = 0
ie.navigate "http://coursesweb.net/javascript/getelementsbytagname"
Do
DoEvents
Loop Until ie.readyState = 4
Set Doc = ie.document
Set Elements = Doc.getElementsByTagName("ul")
For Each Element In Elements
If Element.ID = "ex4" Then
Sheets(1).Cells(1, 1).Value = Element.innerText
End If
Next Element
Set Elements = Nothing
End Sub
First I'm getting collection of tags "ul", then looping through them for id "ex4". In your case you'd get collection of "input"s then loop for id you want. Finding id which is followed by different id shouldn't be hard, just some if...thens.
If you need further assistant please respond with url in which I can find exactly what you're looking for.
Cheers

need help scraping with excel vba

I need to scrape Title, product description and Product code and save it into worksheet from <<<HERE>>> in this case those are :
"Catherine Lansfield Helena Multi Bedspread - Double"
"This stunning ivory bedspread has been specially designed to sit with the Helena bedroom range. It features a subtle floral design with a diamond shaped quilted finish. The bedspread is padded so can be used as a lightweight quilt in the summer or as an extra layer in the winter.
Polyester.
Size L260, W240cm.
Suitable for a double bed.
Machine washable at 30°C.
Suitable for tumble drying.
EAN: 5055184924746.
Product Code 116/4196"
I have tried different methods and none was good for me in the end. For Mid and InStr functions result was none, it could be that my code was wrong. Sorry i do not give any code because i had already messed it up many times and have had no result. I have tried to scrape hole page with GetDatafromPage. It works well, but for different product pages the output goes to different rows as ammount of elements changes from page to page. Also it`s not possible to scrape only chosen elements. So it is pointless to get value from defined cells.
Another option instead of using the InternetExplorer object is the xmlhttp object. Here is a similar example to kekusemau but instead using xmlhttp object to request the page. I am then loading the responseText from the xmlhttp object in the html file.
Sub test()
Dim xml As Object
Set xml = CreateObject("MSXML2.XMLHTTP")
xml.Open "Get", "http://www.argos.co.uk/static/Product/partNumber/1164196.htm", False
xml.send
Dim doc As Object
Set doc = CreateObject("htmlfile")
doc.body.innerhtml = xml.responsetext
Dim name
Set name = doc.getElementById("pdpProduct").getElementsByTagName("h1")(0)
MsgBox name.innerText
Dim desc
Set desc = doc.getElementById("genericESpot_pdp_proddesc2colleft").getElementsByTagName("div")(0)
MsgBox desc.innerText
Dim id
Set id = doc.getElementById("pdpProduct").getElementsByTagName("span")(0).getElementsByTagName("span")(2)
MsgBox id.innerText
End Sub
This seems to be not too difficult. You can use Firefox to take a look at the page structure (right-click somewhere and click inspect element, and go on from there...)
Here is a simple sample code:
Sub test()
Dim ie As InternetExplorer
Dim x
Set ie = New InternetExplorer
ie.Visible = True
ie.Navigate "http://www.argos.co.uk/static/Product/partNumber/1164196.htm"
While ie.ReadyState <> READYSTATE_COMPLETE
DoEvents
Wend
Set x = ie.Document.getElementById("pdpProduct").getElementsByTagName("h1")(0)
MsgBox Trim(x.innerText)
Set x = ie.Document.getElementById("genericESpot_pdp_proddesc2colleft").getElementsByTagName("div")(0)
MsgBox x.innerText
Set x = ie.Document.getElementById("pdpProduct").getElementsByTagName("span")(0).getElementsByTagName("span")(2)
MsgBox x.innerText
ie.Quit
End Sub
(I have a reference in Excel to Microsoft Internet Controls, I don't know if that is there by default, if not you have to set it first to run this code).