How to click in HTML 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 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?

Related

How to click HTML text 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 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().

Table scraping Excel VBA

I need help scraping the tags onto my excel from an internal company website.
This is the source code.
<br />
<span class="RptTitle"><input id="chkPromisDataLog" type="checkbox" name="chkPromisDataLog" checked="checked" onclick="showOnOffPromisLog();" /><label for="chkPromisDataLog">Promis Processing data log [83508442.1].</label></span>
<div id="divPromisDataLog" style="display: none;">
<table id="tblPromisDataLog" cellspacing="0" cellpadding="0" width="100%" border="0" class="table">
<tr>
<td width="60%"></td>
<td>
<a class="textnormal" href="javascript:popwnd=window.open('../Tools/ExportExcel.aspx?KEY=LOT_GEN_PROMIS','popwnd','status=no,toolbar=Yes,menubar=Yes,location=no,scrollbars=yes,resizable=Yes');popwnd.focus()">
Export to Excel
</a>
</td>
</tr>
<tr>
<td colspan="2">
<table cellspacing="0" rules="all" border="1" id="dgPromisDataLog" style="border-color: Black; border-collapse: collapse;">
<tr class="rptDetailsHeaderMgt" align="center">
<td>LotID</td>
<td>Hist Stage</td>
<td>Datein</td>
<td>Dateout</td>
<td>Qtyin</td>
<td>Qtyout</td>
<td>M/C ID</td>
<td>Emp TrackOut</td>
<td>Hold Code</td>
<td>Hold Reason</td>
<td>Staging (Hrs)</td>
</tr>
<tr class="rptDetailsItemMgt" align="center" style="white-space: nowrap;">
<td>83508442.1</td>
<td>
<a
href="javascript:popwnd=window.open('LotGen_Dtl.aspx?iDate=04/09/2021 09:07:07 PM&amp;oDate=04/10/2021 03:47:59 PM&amp;oLotid=83508442.1&amp;oStage=C-WFRPROCS&amp;oLastRow=N','popwnd','width=900,height=600,status=no,toolbar=no,menubar=no,location=no,scrollbars=yes,top=100,right=50,left=50');popwnd.focus();"
>
C-WFRPROCS
</a>
</td>
<td>4/9/2021 9:07:07 PM</td>
<td>4/10/2021 3:47:59 PM</td>
<td>0</td>
<td>9</td>
<td></td>
<td>10911700</td>
<td> </td>
<td> </td>
<td>18.68</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
This is roughly my code
Sub Lotsearch()
Dim ie As InternetExplorer
Dim htmlEle As IHTMLElement
Dim i As Integer
Set ie = New InternetExplorer 'start new IE page
ie.Visible = True 'View what is happening in IE
ie.navigate "www.internalcompanywebsite.aspx" 'Open link in IE
While ie.readyState <> 4 'Waits for IE to finish loading
DoEvents
Wend
i = 1
'ie.document.getElementById("tblPromisDataLog") = Cells(2, 1).Value
'ie.document.getElementsByTagName("td").Value = Cells(5, 1).Value
'Set Data = ie.document.getElementByTagName("rptDetailsItemMgt")
'Dim myValue As String
'myValue = allRowOfData.Cells(0).innerHTML
'Cells(3, 13) = myValue
'Range("L1").Value = myValue
'For Each htmlEle In ie.document.getElementById("tblPromisDataLog")(0).getElementsByClassName("rptDetailsItemMgt")
With ActiveSheet
.Range("A" & i).Value = htmlEle.Children(0).textContent
' .Range("B" & i).Value = htmlEle.Children(1).textContent
' .Range("C" & i).Value = htmlEle.Children(2).textContent
' .Range("D" & i).Value = htmlEle.Children(3).textContent
' .Range("E" & i).Value = htmlEle.Children(4).textContent
' .Range("F" & i).Value = htmlEle.Children(5).textContent
' .Range("G" & i).Value = htmlEle.Children(6).textContent
' .Range("H" & i).Value = htmlEle.Children(7).textContent
' .Range("I" & i).Value = htmlEle.Children(8).textContent
' .Range("J" & i).Value = htmlEle.Children(9).textContent
' .Range("K" & i).Value = htmlEle.Children(10).textContent
' .Range("L" & i).Value = htmlEle.Children(11).textContent
End With
i = i + 1
Next htmlEle
ie.Quit
End Sub
As you can see, I have tried various methods but to no avail.
getElementbyID not working
getElementsbyTagName not working
getElementsByClassName not working
Any help would be appreciated. Thanks.
it may not actually be the most efficient way to deal with HTML extraction, but you might consider using Regex matching.. Raw Coding on youtube just made a killer regex tutorial, and I remembered seeing this question, and thought it might be a good alternative if you didn't like dealing with html explicitly.
Regex Tutorial for Beginners from Raw Coding on Youtube
like, if you only wanted normal text between td tags, you could regex search for
(?<OpenTag>[\<]+td[\>]+)(?<Contents>[\w\/\(\)\[\]\.\&\:\;\s]*?)(?<CloseTag>[\<]+[\/]+[td]+[\>]+)
here's an example at Regex101
Regex101 example using your html
Dim ht As HTMLDocument
Dim i As Integer
Dim htmltable As MSHTML.htmltable
Set htmltable = ht.getElementById("dgPromisDataLog")
myValue = htmltable.getElementsByClassName("rptDetailsItemMgt")(0).getElementsByTagName("td")(0).innerText
After messing with it for a few days, I found that the code works if I split up the getElementbyId from the other 'getElements'.
Changed htmlEle As IHTMLElement into ht As HTMLDocument. Also added htmltable As MSHTML.htmltable
For some reason the code returns an error if I chain the entire 'getelement' together. Hope this helps someone else with the same problem.

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.

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