IE automation VBA Excel find element by title - html

I am trying to get some information from a webpage using an excel macro, VBA.
I have the InternetExplorer.document object, but don't find a way to locate the exact info that I need.
The HTML part of what I am looking for looks like this:
<a title="BE xxx.xxx.xxx - straat 70 - 3630 - Maasmechelen" class="leftalign floatleft" href="Page_companydetail.asp?vat=xxxxxxxxx" target="_blank">
Oprichter van een onderneming natuurlijk persoon BE xxx.xxx.xxx
The information I want is the title here.
I tried a lot of things, but can't manage to single this element out and get the title.
So
1. Is there a way to get elements by title (Title starts with BE), or by class sinds this information is the only one on the page that has class "leftalign floatleft"

Yes ... knowing that the title is just another attribute of the <a> tag, you can cycle through all elements of concern using e.g.
HtmlDocument.GetElementsByTagName(String) method
and use the
HtmlElement.GetAttribute(String) method
to see if a title attribute exists and what's the value of it
see Reading Web Pages using Excel VBA for some more information

Something like this should work, I'm assuming you already have a pointer to the IE or Document Object.
Public Sub getTitleElement()
Dim myElement As Object
'Assuming you already have IE object/Document
Set myElement = IE.Document.getElementsByClassName("leftalign floatleft")(0)
Debug.Print myElement.Title
End Sub

Related

Obtain Innertext from Web Element with Variable Path - Selenium

I have a VBA macro that I'm running in Excel 2016. The macro brings back information from the internet using Chrome and Selenium WebDriver. The macro iterates through several similar webpages, but some pages have a few more or less lines than others. Hence, the XPath to the innertext I'm interested in varies slightly from page to page. Here is a snippet of the source code for the element, it is the "242" that I'm trying to locate and extract.
<div ng-repeat="squarefootage in improvement.SquareFootage" class="ng-scope">
<div>
<span class="labelSquareFootage ng-binding">ATTACHED GARAGE AREA </span><span class="result ng-binding">242</span>
</div>
</div>
As a workaround I'm just grabbing the entire source code for the page and then parsing it with INSTR to find what I'm looking for. I was wondering if there was a more elegant method to find an element with a variable path? Is there something in WebDriver that would work like
WDriver.FindElementbyInnerHTML
?
Here is a link to the website, you can look at a few different addresses and see how the path changes from page (address) to page (next address).
You could gather all nodes with matching class and loop until desired garage text found then take the nextSibling
Public Sub Demo()
'Your code to get to page and enter address and search, open heading, then....
Dim html As MSHTML.HTMLDocument
Set html = New MSHTML.HTMLDocument
html.body.innerHTML = WDriver.PageSource
Dim nodes As Object, node As Object, i As Long
Set nodes = html.querySelectorAll(".labelSquareFootage")
For i = 0 To nodes.Length - 1
Set node = nodes.Item(i)
If InStr(node.innerText, "ATTACHED GARAGE AREA") > 0 Then
Debug.Print node.NextSibling.innerText
Exit For
End If
Next i
End Sub
For xpath, you could try
//*[text()[contains(.,'ATTACHED GARAGE AREA')]]/following-sibling::span
if the desired value is the next span node. This searches for the desired text in the .innerText then takes the nextSibling span.
CSS selectors

Get value of HTML5 input type search from code behind after postback in .NET

I'm creating a sample textbox for search like this (I'm using VB) in my webpage:
Dim txtSearchFilter As New HtmlGenericControl("input")
With txtSearchFilter
.ID = "txtSearchFilter"
.Attributes.Add("placeholder","Filter")
.Attributes.Add("type","search")
.Attributes.Add("maxlength","80")
End With
It's great, because this is the HTML5 style box which has some useful features, such as the "x" on the right side of the box to clear the text entry. However, from the code behind, I can't retrieve the text that was entered. I've tried:
txtSearchFilter.InnerText
txtSearchFilter.InnerHtml
txtSearchFilter.Attributes("value")
Request.Form("txtSearchFilter")
But none of these work. Is there a way to get the value?
P.S., SO prevents me from selecting the HTML5 tag and, instead, puts in the HTML tag even though I selected the HTML5 tag.
Add a name attribute to the input element.
txtSearchFilter.Attributes.Add("name", "txtSearchFilter")
Then on postback, you can retrieve the value by Request.Form(name_attribute). Example based on the above code :
Dim value as String = Request.Form("txtSearchFilter")

Driving a website using VBA and Selenium

I have to log into SnapSurveys and download 20+ files monthly. Already a tedious process, I now have to do it weekly instead and it will be beyond tedious to do it by hand, so I want to automate it and have installed Selenium to do so. I've tracked the entire process using the SeleniumIDE (in FireFox), so I know what I want to do, and the basics of how to do it, however, I've run into an absolute brick wall trying to understand the web page structure to make it happen.
Using the Dev tools in both Chrome & FireFox, I've identified the "User Name" field as this:
<p>
<label for="UserName">Username</label>
<input data-val="true" data-val-required="The Username field is required." id="UserName" name="UserName" type="text" value="">
<span class="field-validation-valid" data-valmsg-for="UserName" data-valmsg-replace="true"></span>
</p>
I'm using the following code to attempt to locate the "Username" text box so I can type data into it. I've tried each of the values of Text, in turn, with each of the Driver.FindElementBy... possibilities, and they all give me this error:
Run-time Error '7':
NoSuchElementError
Element not found for <By type> = <text>
This is the code:
Private Sub Login()
Const SITE_BASE_NAME As String = "https://www.snapsurveys.com/login"
Dim Driver As IEDriver
Set Driver = New IEDriver
Dim IsSiteLoaded As Boolean
IsSiteLoaded = Driver.Get(SITE_BASE_NAME)
If IsSiteLoaded Then
Dim Text As String
Text = "columns six"
Text = "UserName"
Text = "main"
Text = "//*[#id=""UserName""]"
Dim El As WebElement
Set El = Driver.FindElementByClass(Text)
Set El = Driver.FindElementByCss(Text)
Set El = Driver.FindElementById(Text)
Set El = Driver.FindElementByLinkText(Text)
Set El = Driver.FindElementByName(Text)
Set El = Driver.FindElementByPartialLinkText(Text)
Set El = Driver.FindElementByTag(Text)
Set El = Driver.FindElementByXPath(Text)
End If
Driver.Quit
End Sub
The one combination I've found that's not given me an error is:
Text = "main"
Set El = Driver.FindElementById(Text)
But that only gives me the breadcrumbs at the top of the screen, and I'm not really sure how to get anywhere useful from there.
Obviously, I don't understand enough about web design to have any clue what I'm supposed to be looking for, but I thought I could trial and error my way through it with a little less frustration than this.
What element(s) do I need to be looking for in the page source, and which FindElementBy function do I need to use to search for it in code?
Further, is filling in the UserName & Password fields, clicking "Log In", then clicking on the appropriate links on the next page, etc. the best way to go about this? I think that once I've logged myself in, I should be able to get a collection of links for each file I need and directly download each link, but I'm not 100% certain if I can do that or not.
Some notes:
Yes, I realize that the code is using IE as the browser. The drivers I have for FF & Chrome seem to be out of date (browser opens, but it won't load the web page) and I haven't gotten newer ones. At the moment, I don't care what browser I use so long as I get it working.
Yes, I realize that I'm closing the browser down at the end of the Sub. Again, I'm just testing, trying to find my way in the dark.
The login functionality is inside an iframe. You have to switch selenium's focus to that iframe and then try again and it should work.
You can try this:
Driver.switchtoframe (0)
Driver.FindElementById("UserName")
Some knowledge about web design can help a long way when dealing with selenium to automate, but with just some basic knowledge you can get the work done easily.
What element you should be looking for depends on what you are trying to achieve. If you want to enter something in a text field, you should be looking for <input type="text"> elements, for table's you need to be looking for <table> elements.
I usually prefer using find elements by xpath, but if the element has a unique id or class on the webpage, you can use find element by class name or find element by id.
You seem to be going on the right track to automate your task.

Using selenium to access attribute text

I'm really new to selenium and this is probably really simple, but what i'm trying to do is store the '2017 League Table Ranking: 25th" text inside this attribute to a string in java:
<a href="/league-tables/rankings">
2017 League Table Ranking: 25th
</a>
public void findRanking() throws Exception {
String ranking = driver.findElement(By.xpath("(//a[contains(#href, '/league-tables/rankings')])")).getAttribute(href) ;
}
This gives me the link to the href that the attribute is using, and is the closest i've got to getting an output kind of right. I've tried simply getting the text of the element above, using the .getText() method but that returns nothing, where am i going wrong?
Since we now have a link to the page, I was able to create a unique locator. The problem was that there was more than one element that matched the locator and the first match wasn't the one you wanted. Since we don't need XPath here, I switched to a CSS selector. CSS selectors have better browser support, are faster, and I think are easier to create. This should work now.
public String findRanking() {
return driver.findElement(By.cssSelector("p.league-table-latest-rank > a[href='/league-tables/rankings']")).getText();
}
Here are some references for CSS selectors. I would suggest that you spend some time learning them. They are extremely powerful and should be your goto locator after By.id().
W3C CSS Selector Reference
Sauce Labs CSS Selector Tips
Original answer with XPath
.getText() should work on that element. It looks like you have an extra set of () in your XPath. Also, you should be able to use equals instead of contains(). There may be other links that contain that partial href that may be causing issues. I would try the below. I added a return and changed the return type to String.
public String findRanking() {
return driver.findElement(By.xpath("//a[#href='/league-tables/rankings']")).getText();
}
You can test your XPath in Chrome. Open the page and try $x("//a[#href='/league-tables/rankings']").length in the dev console and make sure it returns 1. If it's 0 then something is wrong with the locator. If it's > 1 then you'll have to further narrow the focus of your locator. Find a unique parent that has an ID or something unique.
Try this:
public String findRanking(){
WebElement e = driver.findElement(By.xpath("//a[contains(#href, '/league-tables/rankings')]");
return e.getText();
}
Try this way.
If you want to get the text of 2017 League Table Ranking: 25th then use below code.
String test = driver.findElement(By.xpath("//a[contains(text(), '2017 League Table Ranking: 25th')]")).getText();
System.out.println(test);
If you want to get the href attribute of this text 2017 League Table Ranking: 25th then use below code.
String href = driver.findElement(By.xpath("//a[contains(text(), '2017 League Table Ranking: 25th')]")).getAttribute("href");
System.out.println(href);

Get value from HTML element for display in Textbox

I have tried adapting a handful of solutions Ive found on here and cannot get any to work. Most recently,
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim Web As New HtmlAgilityPack.HtmlWeb
Dim Doc As New HtmlAgilityPack.HtmlDocument
Doc = Web.Load("http://MyWebSearch.com/s/" + TextBox1.Text)
For Each table As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(<div class="inline-block"></div>)
Textbox5.text(table.InnerText)
Next
End Sub
I am trying to conduct a search with a fixed address where + textbox1 contains the search item. I need to return the value from one element on the page into Textbox5 after search is conducted. I cant for the life of me get this to work. Ive tried obtaining the xpath but that failed also. What am I doing wrong?
The web page is rbx.trade/s/"username"
I am trying to return the users "Rap" and display in textbox5
You're searching for the class of an element. You probably want to search for the ID instead.
For Each table As HtmlAgilityPack.HtmlNode In Doc.DocumentNode.SelectNodes(<div id="elementID"></div>)
Textbox5.text(table.InnerText)
Next
Or if you indeed mean to be using the class, store each value in an array or append to the text box instead of storing it directly. Say there are 8 element with that class. Doing it the way you are will always store the value of the 8th skimmed element with that class name.