How to click HTML text with VBA - html

I'm writing a code to automatically fill some website with cells values:
Sub prueba()
Dim oIE As InternetExplorer: Set oIE = New InternetExplorer
Dim oDocument As HTMLDocument
Dim ECICOR As HTMLSelectElement
Dim i, j As Integer
Dim x As Long
oIE.Visible = True
oIE.Navigate "http://sirem.eci.geci/smcfs/console/login.jsp"
Do While oIE.readyState <> 4: DoEvents: Loop
With oDocument
Set oDocument = oIE.Document
End With
Call oDocument.parentWindow.execScript("window.parent.sc.postDummyFormForWindow('/smcfs/console/inventory.search');", "JScript")
Set ECICOR = oDocument.getElementById("enterpriseFieldObj")
ECICOR.Focus
ECICOR.Click
ECICOR.Value = "ECICOR"
ECICOR.FireEvent ("onChange")
oDocument.getElementsByClassName("unprotectedinput")(0).Value = Cells(i, 1)
oDocument.getElementsByTagName("a")(0).Click
oDocument.getElementsbyClassName("evenrow")(1).click
End Sub
So my problem is that my program doesn't do anything after the last line on the code and I don't know what problem it is because it worked before.
Here you can see the HTML code:
<
<TR class=evenrow><TD class=checkboxcolumn><INPUT type=checkbox value=%3CInventoryItem+ItemID%3D%22000000000152030052%22+OrganizationCode%3D%22ECICOR%22+ProductClass%3D%22%22+UnitOfMeasure%3D%22%22%2F%3E name=EntityKey oldChecked="false"> <INPUT type=hidden value=000000000152030052 name=ItemID_1> <INPUT type=hidden name=UOM_1> <INPUT type=hidden name=PC_1> <INPUT type=hidden value=ECICOR name=OrgCode_1> </TD>
<TD class=tablecolumn><A onclick="javascript:showDetailFor('%3CInventoryItem+ItemID%3D%22000000000152030052%22+OrganizationCode%3D%22ECICOR%22+ProductClass%3D%22%22+UnitOfMeasure%3D%22%22%2F%3E');return false;" href="">000000000152030052</A> </TD>
<TD class=tablecolumn></TD>
<TD class=tablecolumn></TD>
<TD class=tablecolumn>001097578527174</TD></TR>">
How can I find a solution?

document.getElementsByClassName() will return an array, not an Element. If you have only one element with the unprotectedinput class, then you need to get the first element in the array returned by document.getElementsByClassName().

Related

How to click in HTML with vba?

I'm writing a code to automatically fill some website with cells values:
Sub prueba()
Dim oIE As InternetExplorer: Set oIE = New InternetExplorer
Dim oDocument As HTMLDocument
Dim ECICOR As HTMLSelectElement
Dim i, j As Integer
Dim x As Long
oIE.Visible = True
oIE.Navigate "http://sirem.eci.geci/smcfs/console/login.jsp"
Do While oIE.readyState <> 4: DoEvents: Loop
With oDocument
Set oDocument = oIE.Document
End With
Call oDocument.parentWindow.execScript("window.parent.sc.postDummyFormForWindow('/smcfs/console/inventory.search');", "JScript")
Set ECICOR = oDocument.getElementById("enterpriseFieldObj")
ECICOR.Focus
ECICOR.Click
ECICOR.Value = "ECICOR"
ECICOR.FireEvent ("onChange")
oDocument.getElementsByClassName("unprotectedinput")(0).Value = Cells(i, 1)
oDocument.getElementsByTagName("a")(0).Click
oDocument.getElementsbyClassName("evenrow")(1).click
End Sub
So my problem is that my program doesn't do anything on the last line of the code and I don't know what problem it is because it worked before.
Here you can see the HTML code:
<
<TR class=evenrow><TD class=checkboxcolumn><INPUT type=checkbox value=%3CInventoryItem+ItemID%3D%22000000000152030052%22+OrganizationCode%3D%22ECICOR%22+ProductClass%3D%22%22+UnitOfMeasure%3D%22%22%2F%3E name=EntityKey oldChecked="false"> <INPUT type=hidden value=000000000152030052 name=ItemID_1> <INPUT type=hidden name=UOM_1> <INPUT type=hidden name=PC_1> <INPUT type=hidden value=ECICOR name=OrgCode_1> </TD>
<TD class=tablecolumn><A onclick="javascript:showDetailFor('%3CInventoryItem+ItemID%3D%22000000000152030052%22+OrganizationCode%3D%22ECICOR%22+ProductClass%3D%22%22+UnitOfMeasure%3D%22%22%2F%3E');return false;" href="">000000000152030052</A> </TD>
<TD class=tablecolumn></TD>
<TD class=tablecolumn></TD>
<TD class=tablecolumn>001097578527174</TD></TR>">
How can I find a solution?

excel vba extract data from website table

I'm trying to scrape website and need only 1 value.
How do I retrieve purchase method using code below? see html below
Private Sub CommandButton1_Click()
Dim IE As Object
' Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")
' You can uncoment Next line To see form results
IE.Visible = False
' URL to get data from
IE.Navigate Cells(1, 1)
' Statusbar
Application.StatusBar = "Loading, Please wait..."
' Wait while IE loading...
Do While IE.Busy
Application.Wait DateAdd("s", 5, Now)
Loop
Application.StatusBar = "Searching for value. Please wait..."
Dim tr As Object, td As Object, tb As Object
Dim value As String
Set tb = IE.Document.getElementById("prop_desc clearfix")
For Each tr In tb.Rows 'loop through the <tr> rows of your table
For Each td In tr.Cells 'loop through the <th> cells of your row
value = td.outerText 'your value is now in the variable "value"
MsgBox value
Next td
Next tr
' Show IE
IE.Visible = True
' Clean up
Set IE = Nothing
Application.StatusBar = ""
End Sub
</div>
</div>
<div class="prop_desc clearfix"><div class = "span-half">
<h3>RV Park/Campground for Sale</h3>
<table>
<tr>
<td>Number of RV Lots: </td>
<td>270</td>
</tr>
<tr>
<td>Size:</td>
<td>
157 acre(s)
</td>
</tr>
<tr>
<td>Purchase Method:</td>
<td>Cash, New Loan</td>
</tr>
<tr>
<td>Status:</td>
<td>
Active
</td>
</tr>
<tr>
<td>Property ID:</td>
<td>966994</td>
</tr>
<tr>
<td>Posted on:</td>
<td>Jul 10, 2018</td>
</tr>
<tr>
<td>Updated on:</td>
<td>Jul 10, 2018</td>
</tr>
<tr>
You can target by class by index and then the td by index
Option Explicit
Public Sub GetInfo()
Dim IE As New InternetExplorer
With IE
.Visible = True
.navigate "https://www.rvparkstore.com/rv-parks/902077--2843-lake-frontage-42-acres-for-sale-in-north-central-us"
While .Busy Or .readyState < 4: DoEvents: Wend
Debug.Print .document.getElementsByClassName("span-half")(0).getElementsByTagName("td")(5).innerText
.Quit '<== Remember to quit application
End With
End Sub
UPDATE:
Url https://www.rvparkstore.com/rv-parks/902077--2843-lake-frontage-42-acres-for-sale-in-north-central-us
HTML Here https://docs.google.com/document/d/1J5tDV99IbzucCB_z8QX8lDa4X3ecxQbQOWeVy5B7Irg/edit?usp=sharing
please use links for more info jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj

Website Login through VBA is throwing error stating "Invalid user name or password"

I used below code for auto login on website through VBA but it is throwing error stating
"Invalid user name or password"
Can someone guide me to what changes required in below code to eliminate the issue?
Private Sub time_sheet_filling()
Dim I As Long
Dim IE As Object
Dim doc As Object
Dim objElement As Object
Dim objCollection As Object
' Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
' Send the form data To URL As POST binary request
IE.Navigate "http://sanjay.com/default.aspx"
' Wait while IE loading...
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
'Load the logon page
Set objCollection = IE.Document.getElementsByTagName("input")
I = 0
While I < objCollection.Length
If objCollection(I).ID = "username" Then
' Set text to enter
objCollection(I).Value = "abc"
End If
If objCollection(I).ID = "password" Then
' Set text for password
objCollection(I).Value = "123"
End If
If objCollection(I).ID = "submit" Then ' submit button clicking
Set objElement = objCollection(I)
End If
I = I + 1
Wend
objElement.Click
End Sub
Website code as you asked.. kindly check and please help with resolution
</script>
<table cellspacing="0" cellpadding="0" style="margin: 0px auto 0 auto;">
<tr>
<td class="parrafo" style="text-align: left; vertical-align: middle; padding: 0 15px 0 0;">ACCOUNT</td>
<td class="parrafo" style="text-align: left; vertical-align: middle; padding: 0 15px 0 0;">PASSWORD</td>
<td> </td>
</tr>
<tr>
<td style="text-align: left; vertical-align: middle; padding: 0 15px 0 0;">
<input name="ctl00$MainContent$ctlLogin$_UserName" type="text" size="15" id="ctl00_MainContent_ctlLogin__UserName" accesskey="u" tabindex="60" class="login_input" />
</td>
<td style="text-align: left; vertical-align: middle; padding: 0 15px 0 0;">
<input name="ctl00$MainContent$ctlLogin$_IdBook" type="hidden" id="ctl00_MainContent_ctlLogin__IdBook" value="54,60,51,24,3,7,6" />
<input name="ctl00$MainContent$ctlLogin$Redir" type="hidden" id="ctl00_MainContent_ctlLogin_Redir" value="wager/welcome.aspx" />
<input name="ctl00$MainContent$ctlLogin$_Password" type="password" size="15" id="ctl00_MainContent_ctlLogin__Password" accesskey="p" tabindex="61" onkeyup="onkey(event, this.value, this)" class="login_input" />
</td>
<td style="text-align: left; vertical-align: middle;">
<input type="submit" name="ctl00$MainContent$ctlLogin$BtnSubmit" value="Login" id="ctl00_MainContent_ctlLogin_BtnSubmit" class="login_input" style="text-transform: uppercase;" />
</td>
</tr>
</table>
</div>
No need to iterate through all the input tag collections. When you have an ID, then you can reference them directly.
Try this modification:
Private Sub time_sheet_filling()
Dim I As Long
Dim IE As Object
Dim doc As Object
Dim objElement As Object
Dim objCollection As Object
' Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
' Send the form data To URL As POST binary request
IE.navigate "http://sanjay.com/default.aspx"
' Wait while IE loading...
Do While IE.Busy Or IE.readyState < 4
DoEvents
Loop
'Load the logon page
Dim oUser As Object, oPass As Object, oSubmit As Object
Set doc = IE.document
Set oUser = doc.getElementById("ctl00_MainContent_ctlLogin__UserName")
Set oPass = doc.getElementById("ctl00_MainContent_ctlLogin__Password")
Set oSubmit = doc.getElementById("ctl00_MainContent_ctlLogin_BtnSubmit")
oUser.Value = "abc"
oPass.Value = "123"
oSubmit.Click
Also - notice the change I made to your loop. IE.Busy by itself is very unreliable. Sometimes it will turn False when the webpage is still loading. On your line I added IE.ReadyState < 4 as another factor on reliability. 4 is the value of the constant READYSTATE_COMPLETE.

how to find location of specific <tr> each time code is run

My code below will extract a value for each hour of the day.
However, the webpage I'm scraping can change and so I want to find a way to assign the location of the to a variable so that it will know what number it is everytime. I found the current number "116" by trial and error.
I included the html structure below as well. Any suggestions?
Sub scrape()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.application")
With IE
.Visible = False
.navigate "web address"
Do Until .readyState = 4
DoEvents
Loop
.document.all.item("Login1_UserName").Value = "user"
.document.all.item("Login1_Password").Value = "pw"
.document.all.item("Login1_LoginButton").Click
Do Until .readyState = 4
DoEvents
Loop
End With
Dim htmldoc As Object
Dim r
Dim c
Dim aTable As Object
Dim TDelement As Object
Set htmldoc = IE.document
Dim td As Object
For Each td In htmldoc.getElementsByTagName("td")
On Error Resume Next
If span.Children(0).id = "ctl00_PageContent_grdReport_ctl08_Label50" Then
ThisWorkbook.Sheets("sheet1").Range("j8").Offset(r, c).Value = td.Children(1).innerText
End If
On Error GoTo 0
Next td
End Sub
HTML:
<form name="aspnetForm" id="aspnetForm" action="./MinMaxReport.aspx"
method="post">
<div>
</div>
<script type="text/javascript">...</script>
<div>
</div>
<table class="header-table">...</table>
<table class="page-area">
<tbody>
<tr>
<table id="ctl00_PageContent_Table1" border="0">...</table>
<table id="ctl00_PageContent_Table2" border="0">
<tbody>
<tr>
<td>
<div id="ctl00_PageContent_grdReport_div">
<tbody>
<tr style="background-color: beige;">
<td>...</td>
<td>
<span id="ctl00_PageContent_grdReport_ctl08_Label50">Most Restrictive
Capacity Maximum</span>
</td>
<td>
<span id="ctl00_PageContent_grdReport_ctl08_Label51">159</span>
</td>
</tr>
</tbody>
</div>
</td>
</tr>
</tbody>
</table>
</table>
</tr>
</tbody>
</table>
You could loop through all TDs and check if id= "ctl00_PageContent_grdReport_ctl08_Label50" for example:
For Each td In htmldoc.getElementsByTagName("td")
On Error Resume Next
If td.Children(0).ID = "ctl00_PageContent_grdReport_ctl08_Label50" Then
ThisWorkbook.Sheets("sheet1").Range("j8").Offset(r, c).Value = td.Children(1).innerText
End If
On Error GoTo 0
Next td
Children(0) will pick the first iHTML element contained in your table cell. On Error Resume Next is for the situation when td element has no child.
It is possible that you have more then one element with this id in your webpage. Then, you must identify table or table row first. I cannot do it because I can't see your whole HTML code.

VB.NET getElementById

I'm stumped. I don't want to use a WebBrowser in my application, and I want to get a specific element by id. my code is:
Dim request As System.Net.HttpWebRequest = System.Net.HttpWebRequest.Create("http://www.google.com/finance?q=NASDAQ:GOOG")
Dim response As System.Net.HttpWebResponse = request.getresponse()
Dim sr As System.IO.StreamReader = New System.IO.StreamReader(response.GetResponseStream())
Dim sourcecode As String = sr.ReadToEnd()
TextBox1.Text = sourcecode
This gets me the source code. But how do I get a specific element? I would think that there is an easy way to do this... Btw I don't want to use Regex, or download HTML Agility Pack.
You can make a parse table to recognize html tags, and search for id=elementname (plus possible whitespace characters) inside the tags. It's not the impossible task it may seem, because you can ignore most tags and you don't have to validate the html. Just consider <>, and ignore the contents of quotes, scripts, etc. There are lots more details and it takes a little work, but it's fun programming.
The alternative would be to download something like html agility pack, use a browser, or use a regex, which you'd like to avoid.
Heres a very rough idea and it does not work for BLOCK elements that need a SEPARATE closing tag (like ) but it works fine for self closing elements like
also i noted that some of tag id's are enclosed in speech marks and some are not, so you would have to tweak that possibly...
I just roughed this code up and copy pasted the routine to detect unenclosed id tags but it still needs work on it and could be shortened too.
<script runat="server">
Dim sourcecode As String
Dim bodycode As String
Dim RetVal As String
Protected Sub Page_Load(sender As Object, e As System.EventArgs)
'
LoadHttpStuff()
If Request.Form("Button1") = "Submit" Then
RetVal = MyGetElementById(Request("Text1"))
End If
End Sub
Private Sub LoadHttpStuff()
Dim request As System.Net.HttpWebRequest
Dim response As System.Net.HttpWebResponse
Dim sr As System.IO.StreamReader
Dim finishat As Long
Dim startat As Long
request = System.Net.HttpWebRequest.Create("http://www.google.com/finance?q=NASDAQ:GOOG")
response = request.GetResponse()
sr = New System.IO.StreamReader(response.GetResponseStream())
sourcecode = sr.ReadToEnd()
startat = InStr(sourcecode, "<body>")
finishat = InStr(sourcecode, "</body>") + 7
bodycode = Mid(sourcecode, startat, finishat - startat)
bodycode = LCase(bodycode)
End Sub
Private Function MyGetElementById(Id As String) As String
Dim tagstart As Long
Dim tagend As Long
Dim posx As Long
Dim item As System.Web.UI.HtmlControls.HtmlGenericControl
Dim test As Boolean
Dim letter As Char
Dim text As String
item = Nothing
test = False
text = ""
If Trim(Id) <> "" Then
'-> with SPEECHMARKS
posx = InStr(bodycode, LCase("id=" & Chr(34) & Id & Chr(34)))
If posx > 0 Then
'find start of tag
Do
posx = posx - 1
letter = Mid(bodycode, posx, 1)
If letter = "<" Then
'found tag start
tagstart = posx
Exit Do
End If
Loop Until posx < 1
If tagstart > 0 Then
posx = InStr(bodycode, LCase("id=" & Chr(34) & Id & Chr(34)))
Do
posx = posx + 1
letter = Mid(bodycode, posx, 1)
If letter = ">" Then
tagend = posx + 1
Exit Do
End If
Loop Until posx >= Len(bodycode)
If tagend > 0 Then
text = Mid(bodycode, tagstart, tagend - tagstart)
test = True
End If
End If
Else
posx = InStr(bodycode, LCase("id=" & Id))
If posx > 0 Then
'find start of tag
Do
posx = posx - 1
letter = Mid(bodycode, posx, 1)
If letter = "<" Then
'found tag start
tagstart = posx
Exit Do
End If
Loop Until posx < 1
If tagstart > 0 Then
posx = InStr(bodycode, LCase("id=" & Id))
Do
posx = posx + 1
letter = Mid(bodycode, posx, 1)
If letter = ">" Then
tagend = posx + 1
End If
Loop Until posx >= Len(bodycode)
If tagend > 0 Then
text = Mid(bodycode, tagstart, tagend - tagstart)
test = True
End If
End If
End If
End If
End If
Return Text
End Function
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<table style="width: 100%;">
<tr>
<td style="text-align:left; vertical-align: top; width: 75%;"><textarea rows="20" cols="80" style="width: 90%;" disabled="disabled"><%=sourcecode%></textarea></td>
<td style="width: 25%; text-align: left; vertical-align: top;">
<table style="width:100%;">
<tr>
<td>Element Id <input id="Text1" name="Text1" type="text" /></td>
</tr><tr>
<td> </td>
</tr><tr>
<td> </td>
</tr><tr>
<td><input id="Button1" type="Submit" value="Submit" name="Button1" /></td>
</tr><tr>
<td> </td>
</tr><tr>
<td> </td>
</tr>
</table>
</td>
</tr><tr>
<td style="width: 75%;"> </td>
<td style="width: 25%;"> </td>
</tr><tr>
<td style="width: 100%;" colspan="2"><textarea rows="20" cols="80" style="width: 75%;" disabled="disabled"><%=RetVal%></textarea></td>
<td style="width: 25%;"> </td>
</tr>
</table>
</form>
</body>
</html>
Hope it helps a little