"Out of memory" error when div class not found - excel

I am using Selenium with ChromeDriver
Dim driver As New ChromeDriver
driver.Get "https://somewebsite.com"
val = driver.FindElementByCss(".some-class-that-does-not-exist-on-this-page").Text
Cells(x, 2).Value = val
When my vba code cannot find that class on a page, it throws an
"out of memory" error 7
even though, my task manager says my memory is only at 29%.
When I click on help it takes me to https://learn.microsoft.com/en-us/office/vba/Language/Reference/User-Interface-Help/out-of-memory-error-7
I have tried things suggested there:
Restart Microsoft Windows in enhanced mode.
Increase virtual memory
But the issue still persists. This only happens when it fails to find the div class.
I tried to add an if statement to check if the element exists
If IsObject(driver.FindElementByCss(".some-class-that-does-not-exist-on-this-page")) Then
val = driver.FindElementByCss(".some-class-that-does-not-exist-on-this-page").Text
Cells(x, 2).Value = val
End If
But still results in out of memory error.

I solved it by using error handler
On Error GoTo ErrorHandler
elem = driver.FindElementByCss(".some-class-that-does-not-exist-on-this-page")
Cells(x, 2).Value = elem.Text
ErrorHandler:
Cells(x, 2).Value = "HTML element not found"
Resume Next

remove the ".Text" part. Check if element exists before reading that value.
pseudo:
elem = driver.FindElementByCss(".some-class-that-does-not-exist-on-this-page")
if elem is not nothing then
val = elem.Text
// do other stuff
end if

Related

How to loop through XML-nodes and validate if values exists?

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

How to make an If Statement into a For Loop in VBA

I am making a project in VBA and I face a problem with the following code...
It says there is a object or an undefined function, but I don't understand why... Any Idea of what the problem is?
(All the variables are declared and i checked the name of the sheets)
Set FinalRange = ActiveWorkbook.Worksheets("Fiche Horaire").Range("A:A")
emptyroww = WorksheetFunction.CountA(FinalRange)
precautionroww = 0
If emptyroww > 50 Then precautionroww = emptyroww - 50
For a = precautionroww To emptyroww
If ActiveWorkbook.Worksheets("Fiche Horaire").Cells(a, 1).Value = name Then ActiveWorkbook.Worksheets("Fiche Horaire").Cells(a, 4).Value = "it works"
Next
The message it gives is "Application-defined or object-defined error"
If your precautionroww is 0 because your emptyrow is below 50 you try to insert your data in row 0 which is causing the error
Thats a problem within VBA if you have a for loop and start with the same value as your "end" value than i still runs 1 time.

NextSibling.Innertext error "Object doesn't support this property"

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.

Parsing HTML with Excel VBA

Hi StackOverflow community!
Before I go to the nearest petrol station to buy a gallon of petrol and then proceed to a shopping centre (wiping tears of desperation along the way) to set my self on fire...
I am trying to parse few websites, each an instance of finance.google.co.uk, for share prices. This sub only opens 3 sites(for now, I'm planning few hundred), get the share price from each and puts it in cells A1, A2, A3 respectively. The code I wrote works fine only after starting/ restarting my laptop and running excel the first time. 2nd and subsequent runs produce random results, meaning 2nd run will give me say A1 and A3 values, next A1, next A1 and A2 etc. Have spent last few days trying to figure out what is going on. Also I cant find a way to get rid of the "On Error Resume Next" line. If I do that I get "Method 'Navigate' of Object 'IWebBrowser2' failed" error, any idea why?. BTW, I'm green, code for personal use, or trying to. So maybe I overlooked something painfully simple, or what I think is the case, simply don't know that simple thing.
The gear:
- windows7 32bit
- IE 11
My sub:
Sub Google_Finance()
Dim o(3) As String
o(1) = "http://finance.google.co.uk/finance?q=LON%3ABARC"
o(2) = "http://finance.google.co.uk/finance?q=LON%3ACCH"
o(3) = "http://finance.google.co.uk/finance?q=LON%3ASUK2"
Dim IE As Object
Set IE = New InternetExplorer
IE.Visible = False
For i = 1 To 3
IE.navigate o(i)
On Error Resume Next
Do While IE.Busy
DoEvents
Loop
Next i
Dim n as Integer
n = 1
Dim v(3) As Variant
v(1) = IE.document.getElementById("ref_11248216_l").innerText"
v(2) = IE.document.getElementById("ref_243113080920948_l").innerText
v(3) = IE.document.getElementById("ref_14572000_l").innerText
For i = 1 To 3
Sheet1.Range("a" & n) = v(i)
n = n + 1
Next i
IE.Quit
Set IE = Nothing
End Sub
Cheers,
Sam
I tried running the code on my side. I don't get the error you are getting when removing 'on error'. Code works OK for me few times in a row, no issues occurred.
To me it looks like this: the error you are getting is happening when IE is trying to reach the page. Because you use 'on error resume next', the compiler does not try to rerun this task on failure, thus any error leads to no data for the value it is trying to read from the web.
You should either: a) remove 'on error resume next' or b) change error handling to loop the task until completion.
For solution a) you will need to overcome your error, which I believe is explained here
For solution b) you will need to change your sub to include a loop - example solution can be found here
Hope this helps!

Handle error when no data to return with getElementById

I'm trying to get data from a company owned webpage. I use getElementById method to return a value from the website.
The macro gets the data if the particular element has data else it throws an error. I tried an On Error Resume Next error handler method to skip the error if the particular element doesn't have any data.
Elementid = ctl00_conMainPageContent_lblGeneralNotesData
Actually its labelbox .. mostly it has data.
Code:
on error resume next
Sheets("AVS").Range("I" & lRow + 1).Value =ie.Document.getElementById("ctl00_conMainPageContent_lblGeneralNotesData").Value
Something like
Dim var As Variant
On Error resume Next
var = ie.Document.getElementById("ctl00_conMainPageContent_lblGeneralNotesData").Value
If Len(var) > 0 then
Sheets("AVS").Range("I" & lRow + 1).Value = var
Else
'nothing in there
On Error GoTo 0
Exit Sub/Function
End If
On Error GoTo 0
Or try setting Break in Class Module in VBE (Tool\Options\General)
I know this question is old, but I've discovered the answer.
When calling a method that returns a single DOM element (like getElementById or querySelector), you must check first that it has returned a DOM element. Do not check if it is Nothing. When these methods can't find the DOM element, they return the Null value, they do NOT return the Nothing object and are not objects. When they do find the DOM element, then they are objects.
This code should work:
If TypeName(id.Document.getElementById("ctl00_conMainPageContent_lblGeneralNotesData") = "HTMLInputElement" Then
Sheets("AVS").Range("I" & lRow + 1).Value = ie.Document.getElementById("ctl00_conMainPageContent_lblGeneralNotesData").Value
End if
NOTE: Methods that return more than one DOM element (e.g. getElementsByClassName) should be tested with Is Nothing since they DO return the Nothing object when they don't find a matching DOM element.

Resources