I'm looking to automate a very basic xpath check from Excel using Selenium and am getting a run-time error '7': Out of memory.
I've succesfully automated quite a bit using AHK but new to VBA so I'm curious what might be causing the problem. Currently the page loads but as soon as it goes to check the XPath it almost immediately pops up with an out of memory run-time error.
I've double checked to see if there are extra processes running or if I'm low on memory and neither seems to be an issue. I have plenty of free memory and have closed all processes so I assume there is an error with my code or some issue I'm not aware of. I've updated to the newest version of ChromeDriver for Selenium and am pretty certain that the Xpath is correct.
Public Sub DupeCheck()
Dim CID As String
Dim HireURL As String
Dim SearchResult As String
CID = 14962738
HireURL = "https://hire.amazon.com/search?q=" & CID & "&sort=relevance_desc&type=candidate"
Dim bot As New WebDriver
bot.Start "chrome", HireURL
bot.Get "/"
SearchResult = bot.FindElementByXPath(".//*[#id='search-page-root']/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div/ul/li[1]/div/div[1]/div[1]/div[2]").Attribute("innerText")
MsgBox (SearchResult)
bot.Quit
End Sub
Does anyone have any idea what might be causing the issue? I genuinely appreciate any help or ideas! Thanks!
For the html you have shown, and following our discussion, use a css attribute = value selector with ends with ($) operator to specify that the class attribute value ends with a specified substring
FindElementByCss("[class$='e15zxa0z0']")
If you need attribute values you can use the .Attribute method e.g.
FindElementByCss("[class$='e15zxa0z0']").Attribute("attributename")
XPath can be particularly brittle and css selectors are generally faster methods for selecting as modern browsers are optimized for css. They should also be less memory consuming.
Is this the only instance of an XPath you are using in your code? See memory exhaustion
Related
My question relates to coding selenium specifically in VBA.
I have a function that finds webelements based on text passed to it (in string variable 'toFind'). The relevent Xpath identification method I use is (where driver. is the selenium chromedriver):
mySearch = "//*[contains(text(),'" & toFind & "')]"
Set ret = driver.FindElementsByXPath(mySearch)
This works unless the toFind variable contains an apostrophe. For example if "Consultant's Forename" is passed then my expression evaluates to:
Set ret = driver.FindElementsByXPath("//*[contains(text(),'Consultant's Forename')]"), which causes an invalid selector run-time error.
I have researched elsewhere on the site and see a number of answers describing escaping from the single quotes using the backslash character. Based on this I have tried to use Set ret = driver.FindElementsByXPath("//*[contains(text(),\"Consultant's Forename\")]") instead. However, this will not compile in microsoft visual basic for applications as it reports a syntax error (code line is red). I have not tried using the driver.findElements(By.xpath method as opposed to driver.FindElementsByXPath as I assumed this would not make a difference to the handling of the XPath expression. I have tried the other suggestions of using the 'concat' function but this also seems not to be valid in VBA selenium.
I don't know if these methods are specficaly for platforms other than VBA or I am just getting my syntax wrong?
The only way I can work it at present is to ignore the existence of the apostrophe:
Set ret = driver.FindElementsByXPath("//*[contains(text(),'Consultant') and contains(text(),'s Forename')]")
Whilst this works it is an incomplete solution and any help on the correct syntax to deal with the xpath location in VBA for text containing an apostrophe would be much appreciated.
Feel like this should be really simple but. I have an excel program that picks a value from a list, searches for a file in our system, and outputs if the file is there or not. Works great if I use:
set missing_file = createobject("System.collections.arraylist")
missing_file.add "Missing file"
However that requires .net 3.5 to be loaded on everyone's computers which I guess is too difficult for people to do.
Ive tried using
dim missing_file as New List(of string)
but excel errors out with a "compile error expected end of statement"
Is there an alternative in the .net 4 that is similar to Arraylist or a different way to add things to a list of indeterminate length?
I have a pipe-delimited text file that I need to read, turn into a pre-formatted Excel document - complete with separate pivot table sheet - and save.
Reading the file and saving it as an Excel document are solved, but I can't seem to get the pivot table to work. I've found a variety of tutorials online, but none are actually working for me.
I've reordered the arguments in the order they present, but I get the exact same late binding error.
When VS complains and states: "Option Strict On disallows late binding", it is telling you that you are either attempting to reference some method or property on a object that it only can identify as type System.Object or perform an invalid implicit cast.
Now let's look at the problem code.
Dim ptTable As Excel.PivotTable = xlPivotSheet.PivotTables.Add(ptCache, ptLocation, "Pivot")
You previous defined:
Dim xlPivotSheet As Excel.Worksheet
Therefore, xlPivotSheet is not the culprit as VS knows it is type Excel.Worksheet.
The next logical suspect is what PivotTables returns. While you were keying in that code, you should have seen something similar to this:
Did you notice that nice little help that Intellisense gave you when you entered the code? You did enter the code, right? Or did you copy-paste an example from some internet landmine site that posts code with Option Strict Off?
Regardless, you now know that you should cast the result of xlPivotSheet.PivotTables to the Excel.PivotTables interface to enable early binding and thus use the Add Method without that nasty error.
Dim ptTable As Excel.PivotTable = DirectCast(xlPivotSheet.PivotTables,Excel.PivotTables).Add( ....
Recommended Reading: Using IntelliSense
I ended up accomplishing this by changing the problem line to the below.
Dim Table As Excel.PivotTable = xlPivotSheet.PivotTableWizard(Excel.XlPivotTableSourceType.xlDatabase,
Range,Location, "Title Here",True, True, True, False)
I am running an Excel 2010 macro that opens another workbook and removes a few code modules (a form and a BAS module). After that it re-imports them as an updated version. This is the code:
For Each x In destination_wb.VBProject.VBComponents
If LCase(x.Name) Like LCase("frmCCLogin*") Or _
LCase(x.Name) Like LCase("modCQ_test*") Then
destination_wb.VBProject.VBComponents.Remove (x)
Next
I have no problem with the import but the remove process doesn't always work as expected. For some reason the BAS (modCQ_test.bas) module is not always removed. As a result, when I re-import, a new duplicated module is created ending with a "1" (i.e. modCQ_test1.bas).
I could see that many people experienced the same problem however, none of the proposed solutions worked for me. Not sure why this is happening?
Please advise.
If you can use the exact name of the module, you can write something like:
Public Sub RemoveComponent(ByVal Book As Workbook, ByVal Name As String)
On Error Resume Next
With Book.VBProject.VBComponents
Call .Remove(.Item(Name))
End With
End Sub
If you're stuck with wildcard matching (i.e. SomeName*) you could iterate the VBComponents collection and cache the names into a collection or array or whatever and call the function above for each name matched.
Additionally, if you wish to enumerate the VBComponents collection and remove like your code sample, I recommend that you go in the reverse order.
So something like:
Public Sub RemoveComponent1(ByVal Book As Workbook, ByVal NameSearch As String)
Dim oCompS As VBComponents
Dim oComp As VBComponent
Dim i As Integer
Set oCompS = Book.VBProject.VBComponents
For i = oCompS.Count To 1 Step -1
Set oComp = oCompS(i)
If oComp.Name Like NameSearch Then Call oCompS.Remove(oComp)
Next
End Sub
Problem is resolved. This simple line of code that hides the destination workbook, fixed the duplication issue in my case:
destination_wb.Windows(1).Visible = False
After this you can remove, then add the components. No duplication will occur.
I have experienced exactly the same phenomenon and it drove me mad for weeks already.
I do check whether the Code Module had definitely been removed directly after the removal and although it had vanished from the VBE's Project View, it still exists and consequently the subsequent import creates a Code Module named xxx1.
Any of the hints given proved not to be reliable on the long run and thus are nothing but guesses. Since the phenomenon is unpredictable as mentioned you never can really tell what did the trick.
As time (some years) has passed I do now have an answer for the phenomenon and a solid and stable solution.
In order not to "cut off the branch you sit on" one will have to envoke another Workbook/VB-Project for deleting and re-importing a Component.
Even another VB-Project performing the task will have to consider that the Component is definitely removed when the code which removed it has "finished".
Conclusion: Rename, Remove, Import, all performed by a VB-Project invoked via "Run ...." will do the trick.
variableName = driver.findElement(By.XPath(".//*[#id='T_F2']/fieldset/div[1]/div/div[4]/span[2]"))
Running the above always seems to lead to the error:
Why is this? I always see other people using findElement By XPath. If it helps, I generated about half of my code using Selenium's 'record' feature. I then converted the code into 'VBA/Webdriver' before pasting it into Excel to use as a Macro.
What exactly is wrong with my code? I have used findElement a number of times before, so I'd have to guess that the problem is with the By.XPath part of my code... Is there any way around this?
Edit: Even variableName = driver.findElementsByXPath(".//*[#id='T_F2']/fieldset/div[1]/div/div[4]/span[2]") leads to the error 'Invalid procedure call or argument' even though it looks fine to me.
Try:
variableName = driver.findElementByXPath("//div[#id='T_F2']/fieldset/div[1]/div/div[4]/span[2]")
Notice that I removed the . in the beginning of the xPath and replaced * with div. Also, you're missing something at the end. You are just declaring the path here and not really getting a value.
EDIT: Referring to just the xPath is not usually enough. Do you want to perform an action on it, get the text inside, the tagname, etc.?
EDIT2: Testing to get the .Text attribute returns a "findElement By XPath not supported in Selenium VBA?" message.
Here's what works for me:
Dim variableName() as variant
variableName = driver.findElementsByXPath("//div[#id='T_F2']/fieldset/div[1]/div/div[4]/span[2]").getdata
Notice it's "find elements [plural] by XPath". This creates a two-dimensional array. variableName(1,1) will have the data you're looking for.
(I know it's been more than 6 years, but it's my first contribution and I can't resist! Maybe that can help someone else)
You have to initialise the following:
Dim By As New By, variableName As WebElement
and because variableName is an object, it has to be declared, as follows:
Set variableName = driver.FindElement(By.Xpath(".//*[#id='T_F2']/fieldset/div[1]/div/div[4]/span[2]"))