Goal: I'm trying to extract the Bid prices for 200 securities from a website.
Problem: I'm trying to pull the Innertexts of the td tag where the price is located.
The idea is to loop through the HTML document for all TH tags, once it finds "Bid", extract the innertext of the next line of code.
VBA error
"Object doesn't support this property"
My code is for extracting one security. I did not include the bigger loop for all 200 securities.
Set objHTML = objIE.document
Set Mytext = objHTML.getElementsByTagName("Th")
For Each Node In Mytext
If Node.innertext = "Bid" Then
BidPrice = Node.NextSibling.innertext
Cells(a, 2) = BidPrice
Exit For
End If
Next Node
For Each Node In elementOne
If Node.innerText = "Bid" Then
Cells(a, 2) = Node.ParentNode.querySelector("td").innerText
'This pulls the Bid Price 8.745
Again, thank you all for helping, especially SIM!
p.s. I will learn to format properly going forward, for now, I'd like to just urgently express my gratitude.
Related
Given a Column A in Excel with multiple cells containing ISBN (book id) values, I want my VBA macro to loop through each of them and, for each one, parse an online XML file that is unique to that ISBN and put the corresponding book title in Column B.
For example, if A1 contains 1931498717, I should parse this XML and grab the title "Don't think of an elephant! : know your values and frame the debate : the essential guide for progressives" and put that in B1.
Here is a sample of the XML file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<classify xmlns="http://classify.oclc.org">
<response code="4"/>
<!--Classify is a product of OCLC Online Computer Library Center: http://classify.oclc.org-->
<workCount>2</workCount>
<start>0</start>
<maxRecs>25</maxRecs>
<orderBy>thold desc</orderBy>
<input type="isbn">1931498717</input>
<works>
<work author="Lakoff, George" editions="28" format="Book" holdings="1088" hyr="2014" itemtype="itemtype-book" lyr="2004" owi="796415685" schemes="DDC LCC" title="Don't think of an elephant! : know your values and frame the debate : the essential guide for progressives" wi="796415685"/>
<work author="Lakoff, George" editions="1" format="Musical score" holdings="1" hyr="2004" itemtype="itemtype-msscr" lyr="2004" owi="4735145535" schemes="DDC" title="Don't think of an elephant! : know your values and frame the debate : the essential guide for progressives" wi="4735145535"/>
</works>
</classify>
Notice there are two "work" elements. In this case, I am happy to just grab the title attribute from the first one. But even better would be to make sure it's the title of a book (format="Book") and not some other format.
Here is my macro code:
Sub ISBN()
Do
Dim xmlDoc As DOMDocument60
Set xmlDoc = New DOMDocument60
xmlDoc.async = False
xmlDoc.validateOnParse = False
r = CStr(ActiveCell.Value)
xmlDoc.Load ("http://classify.oclc.org/classify2/Classify?isbn=" + r + "&summary=true")
ActiveCell.Offset(0, 2).Value = xmlDoc.SelectSingleNode("/classify/works/work[1]").attributes.getNamedItem("title").text
ActiveCell.Offset(1, 0).Select
Loop Until IsEmpty(ActiveCell.Value)
End Sub
I get this error, "Run-time error 91 Object variable or With block variable not set," on the line that references "xmlDoc.SelectSingleNode("/classify/works/work[1]").attributes.getNamedItem("title").text"
I've tried numerous variations to try to isolate the title text but cannot get anything other than this error.
My Excel file is Microsoft Excel for Microsoft 365, on my laptop.
Help would be greatly appreciated. I am inexperienced in VBA programming and XML parsing and have been googling/reading on this for more time than I care to admit without making any progress. (There was a previous StackOverflow question on parsing ISBN XML files, but it was for a provider that no longer offers the XML files for free. That code inspired my code, but something was lost in the translation.)
Thanks tons for any help you can offer.
Your XML has a "default" namespace which applies to its contents, so when using xpath you need to create a dummy alias for that namespace and use it in your query.
See https://stackoverflow.com/a/72997440/478884
Eg:
Dim xmlDoc As DOMDocument60, col As Object, el As Object
Set xmlDoc = New DOMDocument60
xmlDoc.async = False
xmlDoc.validateOnParse = False
'set default namespace and alias "xx"
xmlDoc.SetProperty "SelectionNamespaces", _
"xmlns:xx='http://classify.oclc.org'"
xmlDoc.Load "http://classify.oclc.org/classify2/Classify?isbn=1931498717&summary=false"
Set col = xmlDoc.SelectNodes("/xx:classify/xx:works/xx:work")
'check each `work` for format and title
For Each el In col
Debug.Print "*****************"
Debug.Print el.Attributes.getNamedItem("format").Text
Debug.Print el.Attributes.getNamedItem("title").Text
Next el
I have a list of Twitter urls in Column A, for which I am trying to pull some information off, however I am having a lot of trouble. I want to pull off everything in yellow
I am not sure if it is due to having the wrong classes or due to the Twitter Urls NOT opening in excel. If I double click a url in excel and try to open it I get this error message.
The link works fine when I copy and paste them into the browser. I have read some information on the web that states that a HKEY on the PC may need changing LINK. The problem I have the person I am building this for is not pc literate and will struggle, to do any fix.
I have always used the below code for scraping and it has never failed me. When it does pull data off Twitter, I get an error message, see image below columns D + E. I am assuming this is making some contact to Twitter but can not access the page to extract the data. I am NOT using IE as it no longer works with twitter, I am using a MSXML2.ServerXMLHTTP.
This is what i am using to extract the data, it is the same for all the columns, just the class changes and if it is a Span or a child.
''''Element 3 Column D
If doc.getElementsByClassName("css-1dbjc4n")(0) Is Nothing Then
wsSheet.Cells(StartRow + myCounter, 4).Value = "-"
Else
wsSheet.Cells(StartRow + myCounter, 4).Value = doc.getElementsByClassName("css-1dbjc4n")(0).getElementsByTagName("Span")(0).innerText
End If
Public Function NewHTMLDocument(strURL As String) As Object
Dim objHTTP As Object, objHTML As Object, strTemp As String
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.setOption(2) = 13056
objHTTP.Open "GET", strURL, False
objHTTP.send
If objHTTP.Status = 200 Then
strTemp = objHTTP.responseText
Set objHTML = CreateObject("htmlfile")
objHTML.body.innerHTML = strTemp
Set NewHTMLDocument = objHTML
Else
'There has been an error
End If
End Function
QUESTION
Is the problem due to the urls not opening in excel, or is it because the data is dynamic and it can not be extracted?
Twitter Link 1
Twitter Link 2
As always thanks for having a look and my apologies in advance for NOT adding HTML snippet as it would not let me post, I could not find the error so removed the html, it was stating that a URL had been shortened, but could not find it so removed the whole html snippet in order to post.
UPDATE
I thought this link was in my post, but I must have removed it when I removed the HTML Snippet. I found this on Stackoverflow but could not get it to work form me, nothing would extract Link
This question already has an answer here:
Scrape table from website
(1 answer)
Closed 2 years ago.
I am really struggling in trying to pull some data of a web table. I have scraped web data in the past but never from a table and can not work it out
I have tried several variations but nothing seems to work, I have channged the class several times and the child node number to reflect each items, however I can not extract anything from the table
Q) Can someone advise on the table class and how to extract from a td
I have read several posts on this forum and other forums on scraping from a table, however none helped, hence the post
''''Data 1
On Error Resume Next
If doc.getElementsByClassName("content")(0).getElementsByTagName("td").Children(0) Is Nothing Then
wsSheet.Cells(StartRow + myCounter, 1).Value = "-"
Else
On Error Resume Next
wsSheet.Cells(StartRow + myCounter, 1).Value = doc.getElementsByClassName("content")(0).getElementsByTagName("td").Children(0).innerText
End If
I have tried the following Variations
doc.getElementsByClassName("content")(0)
doc.getElementsByClassName("content")(0)).Children(0)
doc.getElementsByClassName("content")(0).getElementsByTagName("th").getElementsByTagName("td").Children(0)
doc.getElementsByClassName("content")(0).getElementsByTagName("td").Children(0)
This is an image of the html, I tried to put in the html code, but could not get it to look right
As always thanks in advance
First an advice: Split those statements into pieces and save the result into intermediate variables.
Then an observation: The <td>-tags have no children, so children(0) will return Nothing (the <th> on that page has a child, the <span>-tag) . You probably want to read the content of the cell, you can do this with the property InnerHtml.
Remove the On Error Resume Next-statement. As long as you are developing your routine, let the code run into errors so you can easily debug and see the place where the code fails. And once you are ready, it's better to check for errors by yourself.
Not sure if the following fits, but it should give you the idea:
' Fetch the "Content"-DIV
Dim content As Object
Set content = HtmlDoc.getElementsByClassName("content")(0)
' Fetch the first table with that div
Dim table As Object
Set table = content.getElementsByTagName("table")(0)
' Loop over all <td>-Tags and print the content
Dim td As Object
For Each td In table.getElementsByTagName("td")
Debug.Print td.innerHTML
If td.Children.Length > 0 Then
' If <td> has children, fetch the first child and show the content
Dim child As Object
Set child = td.Children(0)
Debug.Print " We found a child: " & child.tagName, child.innerHTML
End If
Next
When you debug the code, remember to use the "Locals Window" of the VBA (View->Locals Window). There you can inspect all the details of the objects.
I have through an API fetched my data as an XML, and I wish to cycle through nodes (there are several of the same type) and add them to certain fields/a table.
Example from the XML-file:
<HistRating
xmlns="">
<EndrAr>2020</EndrAr>
<EndrMnd>7</EndrMnd>
<Rating>A</Rating>
</HistRating>
<HistRating
xmlns="">
<EndrAr>2019</EndrAr>
<EndrMnd>6</EndrMnd>
<Rating>A</Rating>
</HistRating>
I have tried the following format (at this point the XML I need is in a string in xmlDoc xmlDoc = CreateObject("MSXML2.DOMDocument.6.0"). Fully aware that this is not a really "sexy" way to write it, but I'm new at this game:
Set nodeXML = xmlDoc.getElementsByTagName("EndrAr")
Range("G1").Value = nodeXML(1).Text
Range("H1").Value = nodeXML(2).Text
Range("I1").Value = nodeXML(3).Text
Set nodeXML = xmlDoc.getElementsByTagName("EndrMnd")
Range("G2").Value = nodeXML(1).Text
Range("H2").Value = nodeXML(2).Text
Range("I2").Value = nodeXML(3).Text
Set nodeXML = xmlDoc.getElementsByTagName("Rating")
Range("G3").Value = nodeXML(1).Text
Range("H3").Value = nodeXML(2).Text
Range("I3").Value = nodeXML(3).Text
This works great as long as all three items are there. Unfortunately that is not given. If it is a new company i.e. (3) wont exist (there is one line per year above), and I would like to either set the cell to Blank or No value or something.
The result from when I run the above code:
But if I try to add a line 4 to test what happens if value does not exists I get the following (for obvious reasons)
What I would love some help with is:
Can I by some "magic" add a ifmissing (tried it, but could not get it to work)?
Other ways to add a if variable is not found, input following into cell
Or are there a complete different way I should have solved this?
This is to add accounting data from last X available years (where X is ie 4, or less if not 4 is available) from 30 nodes.
You could use an Error trapping Function. Note in the code below we choose not to use the returned boolean.
Dim myTest as String
.
.
TryReadingXmlNode nodeXML,1, myText
Range("G1").Value = myText
.
.
Public Function TryReadingXmlNode(ByVal ipNode as object, ByVal ipIndex as Long, ByRef opText as string) as boolean
On Error Resume Next
opText=ipNode.Item(ipIndex).Text
TryReadingXmlNode=Len(opText)>0
If err.number>0 then opText="NoValue"
on Error Goto 0
End Function
Start by querying all of the HistRating elements, then loop over that collection:
Const MAX_YEARS As Long = 4
Dim ratings, rating, c As Range, i as Long
Set c= Range("A1")
Set ratings = xmlDoc.getElementsByTagName("HistRating")
For Each rating in ratings
c.offset(0, i) = rating.getElementsByTagName("EndrAr")(0).Text
c.offset(1, i) = rating.getElementsByTagName("EndrMnd")(0).Text
c.offset(2, i) = rating.getElementsByTagName("Rating")(0).Text
i = i + 1
If i >= MAX_YEARS Then Exit For 'exit if processed enough nodes
Next rating
I want to enter data into a web page field.
There are 2 data entry fields on the web page.
I entered data in the first section.
However, I cannot enter data in the other field.
Information you need to review the site :
Site : http://splan.byethost7.com/mesaj_yaz.php?fno=1&kip=yeni
user :kurucu password :a11111
I entered the data in the "BAŞLIK" field.
However I am unable to write data to the field named "İÇERİK"
I want to enter data in this field using an Excel macro. But I can't enter data using the code:
Sub deneme()
Dim URL As String
On Error Resume Next
URL = "http://splan.byethost7.com/mesaj_yaz.php?fno=1&kip=yeni"
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = 1
For i = 1 To Range("A" & Rows.Count).End(3).row
If Cells(i, 1) <> Empty Then
ie.navigate URL
Call bekle
ie.Document.getElementById("mesaj_icerik").Value = "TEST"
ie.document.getElementsByName("mesaj_baslik").Item(0).Value = Cells(i, 1)
'IE.Document.getElementsByClassName("submitButton")(0).Click
Call bekle
End If
Next i
' IE.Quit
Set ie = Nothing
End Sub
Sub bekle()
With ie
Do Until .readyState = 4: DoEvents: Loop
Do While .Busy: DoEvents: Loop
End With
Application.Wait (Now + TimeValue("00:00:02"))
End Sub
As I said in my comments, there are several issues with your code, although the overall effort is good.
Firstly, this ie.document.getElementsid("mesaj_baslik") is not a valid method. If what you want is to access a single HTML element with a unique ID, then the method you need to use is ie.Document.getElementById("the element's ID").
Assuming that what I wrote above is what you were trying to achieve, you have to keep in mind that the .getElementById() method, returns only one single element.
So this ie.Document.getElementById("the element's ID").item(0) would give you an error saying:
Object doesn't support this property or method.
Even if all the aforementioned mistakes were corrected, I still don't see any elements with an ID equal to "mesaj_baslik", in the HTML snippet that you have provided. In fact this particular string is nowhere to be found in the HTML.
So even if the method was correct, this ie.Document.getElementById("mesaj_baslik"), would return Nothing.
Secondly, although your usage of the method ie.document.getElementsByName() is correct, there is no element with a Name attribute being equal to "formlar_mesajyaz", in the HTML snippet you have provided.
In fact this string seems to be a Class name rather than anything else. In this case you would have to use this method: ie.document.getElementsByClassName().
Now, from the info you have provided, the best I can do is assume that, what you want to do is enter some text in the textArea element. To do that, you can use the element's ID like so:
ie.Document.getElementById("mesaj_icerik").Value = "TEST"