I'm trying to select and item from a dropdown kendolistbox in IE with Excel Vba - excel

I found a solution to choosing a fixed selection from a dropdown list. Now all I have to do is figure out how to choose an item based on the choices.
The following chooses the first item in the dropdown, however, I found out that making the dropdown "open" is not necessary.
Changing the select parameter to 2 chooses the second item in the list etc.
I suppose trying to use getElementById and cycling through the innerText may be the way to go, since I don't know any other way.
ie.Document.parentWindow.execScript "$('#drgdTankCrude').data('kendoGrid').dataItem($('#Tank_ID').data('kendoDropDownList').select(1));"
Here a section of the web page code.
<input name="Tank.ID" id="Tank_ID" style="width: 200px; display: none;" type="text" data-role="dropdownlist"></span>
'Lots of other stuff in here for formatting
<div class="k-widget k-grid" id="drgdTankCrude" style="left: 890.32px; top: 93.7px; display: block; position: absolute;" data-role="grid">
<table class="k-selectable" role="grid" style="-ms-touch-action: double-tap-zoom pinch-zoom;" data-role="selectable">
<colgroup><col><col></colgroup>
<thead class="k-grid-header" role="rowgroup">
<tr role="row">
<th class="k-header" scope="col" data-title="Tank" data-index="0" data-field="ID"><span class="k-link">Tank</span></th>
<th class="k-header" scope="col" data-title="Capacity" data-index="1" data-field="Capacity"><span class="k-link">Capacity</span></th>
</tr>
</thead>
<tbody role="rowgroup">
<tr class="k-state-selected" aria-selected="true">
<td>179800</td>
<td>202.06</td></tr>
<tr class="k-alt" aria-selected="false">
<td>179801</td>
<td>202.82</td>
</tr>
</tbody>
</table>
</div>
'Code before dropdown
<tbody role="rowgroup">
<tr>
<td>179800</td>
<td>202.06</td></tr>
<tr class="k-alt">
<td>179801</td>
<td>202.82</td>
</tr>
</tbody>
'Code before dropdown opens
<div class="k-widget k-grid" id="drgdTankCrude" style="left: 890.32px; top: 93.71px; display: none; position: absolute;" data-role="grid">
'Code change after dropdown opens
<div class="k-widget k-grid **k-custom-visible**" id="drgdTankCrude" style="left: 890.32px; top: 93.71px; display: block; position: absolute;" data-role="grid">
'Code change after making a selection
<tbody role="rowgroup">
<tr class="k-state-selected" aria-selected="true">
<td>179800</td> '<<-----This item selected
<td>202.06</td></tr>
<tr class="k-alt" aria-selected="false"> '<<--If selected then unselected
<td>179801</td> 'otherwise ends at k-alt">
<td>202.82</td>
</tr>
</tbody>

The answer to selecting the first item in a kendoDropDownList ..
ie.Document.parentWindow.execScript "$('#drgdTankCrude').data('kendoGrid').dataItem($('#Tank_ID').data('kendoDropDownList').select(1));"

Related

I am working on a project to fill data in a pre existing web table

I am working on a project where I have to fill data in a pre populated dynamic web table. I am able to find the element with the help of XPath in selenium VBA. I am able to click the element. But Whenever I Try to fill data with sendkey command I get the message "Run time error 0.Element not intractable.
When I try sendKey command with normal id of the element or CSS id then it gets accepted but when I try XPath i get the above message.
bot.FindElementByXPath("//td[contains(text(),'XYZ')]/following-sibling::td[5]").SendKeys "54"
<tr style="background-color:White;height:24px;">
<td class="gridtext" align="center">
<span class="checkboxclass"><input id="ctl00_ContentPlaceHolder1_grdUsers_ctl02_chkSelect" type="checkbox" name="ctl00$ContentPlaceHolder1$grdUsers$ctl02$chkSelect" onclick="javascript:setTimeout('__doPostBack(\'ctl00$ContentPlaceHolder1$grdUsers$ctl02$chkSelect\',\'\')', 0)"></span>
<input type="hidden" name="ctl00$ContentPlaceHolder1$grdUsers$ctl02$hdnUserId" id="ctl00_ContentPlaceHolder1_grdUsers_ctl02_hdnUserId" value="206451744">
</td><td align="center" style="width:2%;">
1
</td><td class="gridtext" align="center">
<span id="ctl00_ContentPlaceHolder1_grdUsers_ctl02_lblStudentId" style="display:inline-block;color:#000000;font-family:Calibri;font-size:12px;font-weight:normal;font-style:normal;width:120px;">091001118051500183</span>
</td><td class="gridtext" align="center">
</td><td class="gridtext" align="left" style="background-color:#FDE9D9;">SHIVAKSHI</td><td class="gridtext" align="left" style="background-color:#FDE9D9;">SANJAI KUMAR</td><td class="gridtext" align="left" style="background-color:#FDE9D9;">SANGEETA</td><td class="gridtext" align="left" style="background-color:#FDE9D9;">19/02/2010</td><td class="gridtext" align="center" style="background-color:#FDE9D9;">
</td><td class="gridtext" align="center">
<input name="ctl00$ContentPlaceHolder1$grdUsers$ctl02$txtNoOfDays" type="text" maxlength="3" id="ctl00_ContentPlaceHolder1_grdUsers_ctl02_txtNoOfDays" class="TextBox" onkeypress="return AllowNumeric_Browser(event, false);" onpaste="return false;" style="width:50px;">
</td><td class="gridtext" align="center">
You need to target the child input tag of the td as the td itself is not interactable. So, you need to add /input to your current path
bot.FindElementByXPath("//td[contains(text(),'XYZ')]/following-sibling::td[5]/input").SendKeys "54"
Here is a similar example where you select the child input of a td based on the parent tr having a td with specific text
bot.Get 'https://datatables.net/examples/api/form.html'
bot.FindElementByXPath("//tr[contains(td/text(), 'Angelica Ramos')]/td[2]/input").SendKeys "test"
Or
//td[contains(text(),'Angelica Ramos')]/following-sibling::td[1]/input

Extra quotes after every quotes when I copy and paste to notepad from excel

I have the following text stored in a cell in a worksheet
<tr onmouseover="this.style.backgroundColor='#74eb61';" onmouseout="this.style.backgroundColor='#e8e8e8';">
Now when I copy and paste it to notepad from that I get the extra quote sign after every quote so it becomes like the following string
<tr onmouseover=""this.style.backgroundColor='#74eb61';"" onmouseout=""this.style.backgroundColor='#e8e8e8';"">
You can recreate this by:
Copy this text:
<!-- CSS goes in the document HEAD or added to your external stylesheet -->
<style type="text/css">
table.hovertable {
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #999999;
border-collapse: collapse;
}
table.hovertable th {
background-color:#009fe3;
color:#FFFFFF;
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
}
table.hovertable tr {
background-color:#e8e8e8;
}
table.hovertable td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
}
</style>
<!-- Table goes in the document BODY -->
<table class="hovertable">
<th colspan="4">Info Header</th>
<tr onmouseover="this.style.backgroundColor='#74eb61';" onmouseout="this.style.backgroundColor='#e8e8e8';">
<td>Item 1A</td><td>Item 1B</td><td>Item 1C</td>
</tr>
<tr onmouseover="this.style.backgroundColor='#74eb61';" onmouseout="this.style.backgroundColor='#e8e8e8';">
<td>Item 2A</td><td>Item 2B</td><td>Item 2C</td>
</tr>
<tr onmouseover="this.style.backgroundColor='#74eb61';" onmouseout="this.style.backgroundColor='#e8e8e8';">
<td>Item 3A</td><td>Item 3B</td><td>Item 3C</td>
</tr>
<tr onmouseover="this.style.backgroundColor='#74eb61';" onmouseout="this.style.backgroundColor='#e8e8e8';">
<td>Item 4A</td><td>Item 4B</td><td>Item 4C</td>
</tr>
<tr onmouseover="this.style.backgroundColor='#74eb61';" onmouseout="this.style.backgroundColor='#e8e8e8';">
<td>Item 5A</td><td>Item 5B</td><td>Item 5C</td>
</tr>
</table>
and paste to any cell in Excel
And then Copy the cell contents and paste on notepad and you will find extra quotes
This is 'behavior by design'. The clipboard's involvement in the process of transferring the cell value from XL to Notepad++ mean that the text string is evaluated. There are a lot of scenarios that are tested for (I do not have a complete list) but it seems that your paste operation is being interpreted as creating a comma separated or tab separated TXT export file. The quote characters are being doubled up because your system is using the quote character as the Text Qualifier special character in an XL-to-TXT export.
Unfortunately, you do not want this transitional behavior but many others do. If you need to bypass it, copy the text string from the formula bar or in-cell while in edit mode. This is not Excel's doing or even the Office Clipboard (OCB). It is the Windows clipboard's behavior which is trying to interpret a transfer from XL to Notepad++.

excel web query in vba

I have a worksheet that currently updates about 200 stocks using Yahoo Finance API and MSXML. I would like to also get some other info from other websites that don't have an api, for example "http://www.earningswhisper.com/stocks.asp?symbol=googl".
Also for example, if you look at some info from that web page below, you see there is a Release Date of 1/29/2015. There is also some text in between, currently "[not confirmed]", but at some point it will change to "[confirmed]" and both items of text are of interest.
For lack of better web skills, I currently have a single sheet with a QueryTable that is refreshed in a code synchronously. It works...eventually. I would rather work with the response in code, but I don't know how to do that. I don't need this particular info to be auto refreshed.
Questions
Is there a preferred VBA way work with the html response? Can you show a code snippet to illustrate?
Is it possible to convert the html to xml or json relatively easy? code snippet?
If QueryTable is in fact the good enough solution, would it be faster to create a sheet for each stock and refresh async, using events?
I know there is oodles of info on the web, but most of it seems dated and confusing. I am using Excel 2013.
I am able to get at the data I want using html and grabbing Table(6) as shown in the code below. I guess I could parse the InnerText but I suspect there is an easier way to grab the elements I need from that table.
Sub TestHtml()
Dim Resp, sText, FirstCode As String
Dim oHttp, oFile, oTable As Object
Dim lines As Variant
Set oHttp = CreateObject("Microsoft.XMLHttp")
oHttp.Open "GET", "http://www.earningswhisper.com/stocks.asp? symbol=googl", False
oHttp.send ("")
Resp = oHttp.responseText
Set oFile = CreateObject("htmlfile")
oFile.Write Resp
Set oTable = oFile.getElementsByTagName("Table")(6)
sText = oTable.innertext
MsgBox sText
End Sub
Here is a line from that table, and the full table below.
<tr onMouseover="this.className='newsart_s2'" onMouseOut="this.className='newsart'">
<td width="67%" align=left valign=middle> Release Date: <font color='#505050'><small>[not confirmed]</small></font>
</td>
<td width="33%" align=right valign=middle>1/29/2015 </td>
</tr>
What is the best way to drill down and get at the elements in the table, using VBA code?
<TABLE cellpadding=1 cellspacing=0 border=0 id=QEsts width="100%" bgcolor="#505050"><tr><td><TABLE cellpadding=2 cellspacing=0 border=0 width="100%" bgcolor="#FFFFFF" height='148'><tr><td valign=top>
<table cellpadding=0 cellspacing=0 border=0 width="100%" class='newsart'>
<tr><td colspan="2" bgcolor="#FFFFFF"><table width="100%" bgcolor="#FFFFFF" cellpadding=1 cellspacing=0 border=0><tr><td style="background-image: url('images/headbar2.gif'); background-color: #000000; BORDER-RIGHT: #000000 thin solid; BORDER-TOP: #000000 thin solid; FONT-WEIGHT: bold; FONT-SIZE: 12px; MARGIN: 2px; BORDER-LEFT: #000000 thin solid; COLOR: #e1b64b; BORDER-BOTTOM: #000000 thin solid; FONT-FAMILY: Arial;"> 4th Quarter Ending December 2014</td></tr></table></td></tr>
<tr onMouseover="this.className='newsart_s2'" onMouseOut="this.className='newsart'"><td width="67%" align=left valign=middle> <b>Earnings Whisper</b> <small>&#174</small>: </td><td width="33%" align=right valign=middle><b>$7.24</b> </td></tr>
<tr onMouseover="this.className='newsart_s2'" onMouseOut="this.className='newsart'"><td width="67%" align=left valign=middle> Consensus Estimate:</td><td width="33%" align=right valign=middle>$7.16 </td></tr>
<tr onMouseover="this.className='newsart_s2'" onMouseOut="this.className='newsart'"><td width="67%" align=left valign=middle> Surprise Expectation <small><sup>1</sup></small>: </td><td width="33%" align=right valign=middle> </td></tr>
<tr onMouseover="this.className='newsart_s2'" onMouseOut="this.className='newsart'"><td width="67%" align=left valign=middle> Release Date: <font color='#505050'><small>[not confirmed]</small></font></td><td width="33%" align=right valign=middle>1/29/2015 </td></tr>
<tr><td width="100%" align=right colspan="2" valign=middle>After Close </td></tr>
<tr onMouseover="this.className='newsart_s2'" onMouseOut="this.className='newsart'"><td width="67%" align=left valign=middle> Expected Time <small><sup>2</sup></small>: </td><td width="33%" align=right valign=middle>N/A </td></tr>
<tr onMouseover="this.className='newsart_s2'" onMouseOut="this.className='newsart'"><td width="67%" align=left valign=top> Conference Call: </td><td width="33%" align=right valign=top>4:30 PM ET <small><br> </small></td></tr>
</table>
</td></tr></TABLE></td></tr></TABLE>
</td>
You can interact with DOM since you created that object successfully, but you know in your case the easiest way to get the necessary value from the table above is parsing the InnerText as string, try the code below:
aTmp0 = Split(sText, "Release Date:")
If Ubound(aTmp0) = 1 Then
aTmp1 = Split(aTmp0(1), "Expected Time")
MsgBox aTmp1(0)
Else
MsgBox "Release Date not found"
End If

VBA Excel get text inside HTMLObject

I know this is really easy for some of you out there. But I have been going deep on the internet and I can not find an answer. I need to get the company name that is inside the
tbody tr td a eBay-tradera.com
and
td class="bS aR" 970,80
/td /tr /tbody
<tbody id="matrix1_group0">
<tr class="oR" onmouseover="onMouseOver(this, false)" onmouseout="onMouseOut(this, false)" onclick="onClick(this, false)">
<td class="bS"> </td>
<td>
<a href="aProgramInfoApplyRead.action?programId=175&affiliateId=2014848" title="http://www.tradera.com/" target="_blank">
eBay-Tradera.com
</a>
</td>
<td class="aR">
175</td>
<td class="bS aR">0</td><td class="bS aR">0</td><td class="bS aR">187</td>
<td class="aR">0,00%</td><td class="bS aR">124</td>
<td class="aR">0,00%</td>
<td class="bS aR">26</td>
<td class="aR">20,97%</td>
<td class="bS aR">32</td>
<td class="aR">60,80</td>
<td class="aR">25,81%</td>
<td class="bS aR">5 102,00</td>
<td class="bS aR">0,00</td>
<td class="aR">0,00</td>
<td class="bS aR">
970,80
</td>
</tr>
</tbody>
This is my code, where I only try to get the a tag to start of with but I cant get that to work either
Set TDelements = document.getElementById("matrix1_group0").document.getElementsbytagname("a").innerHTML
r = 0
C = 0
For Each TDelement In TDelements
Blad1.Range("A1").Offset(r, C).Value = TDelement.innerText
r = r + 1
Next
Thanks on beforehand I know that this might be to simple. But I hope that other people might have the same issue and this will be helpful for them as well. The reason for the "r = r + 1" is because there are many more companies on this list. I just wanted to make it as easy as I could. Thanks again!
You will need to specify the element location in the table. Ebay seems to be obfuscating the class-names so we cannot rely on those being consistent. Nor would I usually rely on the elements by their table index being consistent but I don't see any way around this.
I am assuming that this is the HTML document you are searching
<tbody id="matrix1_group0">
<tr class="oR" onmouseover="onMouseOver(this, false)" onmouseout="onMouseOut(this, false)" onclick="onClick(this, false)">
<td class="bS"> </td>
<td>
<a href="aProgramInfoApplyRead.action?programId=175&affiliateId=2014848" title="http://www.tradera.com/" target="_blank">
eBay-Tradera.com <!-- <=== You want this? -->
</a>
</td>
<!-- ... -->
</tr>
<!-- ... -->
</tbody>
We can ignore the rest of the document as the table element has an ID. In short, we assume that
.getElementById("matrix1_group0").getElementsByTagName("TR")
will return a collection of html row objects sorted by their appearance.
Set matrix = document.getElementById("matrix1_group0")
Set firstRow = matrix.getElementsByTagName("TR")(1)
Set firstRowSecondCell = firstRow.getElementsByTagName("TD")(2)
traderaName = firstRowSecondCell.innerText
Of course you could inline this all as
document.getElementById("matrix1_group0").getElementsByTagName("TR")(1).getElementsByTagName("TD")(2).innerText
but that would make debugging harder. Also if the web-page is ever presented to you in a different format then this won't work. Ebay is deliberately making it hard for you to scrape data off of it for security.
With only the HTML you have shown you can use CSS selectors to obtain these:
a[href*='aProgramInfoApplyRead.action?programId']
Which says a tag with attribute href that contains the string 'aProgramInfoApplyRead.action?programId'. This matches two elements but the first is the one you want.
CSS Selector:
VBA:
You can use .querySelector method of .document to retrieve the first match
Debug.Print ie.document.querySelector("a[href*='aProgramInfoApplyRead.action?programId']").innerText

Formatting HTML Tables for Excel

I have a page in asp that makes a xls table, however when open the table all the rows are stuffed into the default column width which I would like to set.
My table looks something like this:
<table>
<thead>
'A for loop makes a series of th
</thead>
'another loop pulls db values
<tr><td>value1</td><td>value2</td> 'etc </tr>
</table>
I have tried the following to set the space
width="3.29in"
&nsp; spam (barbaric but sometimes effective)
width="400px"
style="width:300px"
none of the above seem to work.
Additionally here is my header asp incase its relevant
Response.Clear()
Response.Buffer = False
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader "Content-Disposition", "attachment; filename=blah.xls"
Also on a side note for some reason when I have a dollar value printed as such
<td>$<%=dbvalue%></td>
for some reason this yields '$dollar value and I am not sure how to nuke the single quote.
Do you need the thead tag? Something like this should work:
<html>
<body>
<h1>Report Title</h1>
<table >
<tr>
<th style="width : 300px">header1</th>
<th style="width : 100px">header2</th>
<th style="width : 200px">header..</th>
<th style="width : 300px">....</th>
</tr>
<tr class="row1">
<td >value1</td>
<td >value2</td>
<td >value..</td>
<td >....</td>
</tr>
....
Optionally you can put the table row with th tags inside a <thead> tag

Resources