VBA log in failing with getElementsByClassName - vba

I am trying to login to a website using VBA but I can't get it to click the submit button even though I do the things that I have found recommended. Any help would be greatly appreciated.
Below is the HTML of the form:
<div class="pdForm login">
<div class="pdLoginBox">
<div class="pdLoginBoxInner">
<div class="pdLoginFieldTitle">
<div>Email Address</div>
<div class="register"></div>
</div>
<input type="email" name="email" value="" class="pdInput text" id="pdLogin-email">
<br>
<div class="pdLoginFieldTitle">
<div>Password</div>
<div class="forgot"> Forgot your Password?</div>
</div>
<input type="password" name="password" value="" class="pdInput text" id="pdLogin-password">
<div class="pdLoginBtn">
<input type="image" src="http://myaccount.asdf.com/skins/standard_custom/butLogin.gif" border="0" vspace="4">
</div>
<div class="pdRegisterBtn">
</div>
</div>
</div>
</div>
Here is the VBA that I have tried and it fills in the name and password but will not submit even through it runs the code without error.
Sub Login()
Dim lr As Long, a
Set IE = CreateObject("InternetExplorer.Application")
my_url = "http://myaccount.asdf.com/login.php"
With IE
.Visible = True
.Navigate my_url
.Top = 50
.Left = 530
.Height = 1200
.Width = 1200
Do Until Not IE.Busy And IE.READYSTATE = 4
DoEvents
Loop
End With
' Input the userid and password
IE.Document.GetElementById("pdLogin-email").Value = "asdf#asdf.com"
IE.Document.GetElementById("pdLogin-password").Value = "xxxxxx"
Set ElementCol = IE.Document.getElementsByClassName("pdLoginBtn")
For Each btnInput In ElementCol
btnInput.Click
Next btnInput
End Sub
Any ideas? Thanks in advance for your time.

Does this work for you?
Set ElementCol = IE.document.getElementsByClassName("pdLoginBtn").Children(0)
ElementCol.Click

Related

Iterate li in html with vba

I cant seem to locate an answer to this anywhere through searches...
I am trying to iterate through a list on a webpage using vba and then use the data in excel.
Accessing the webpage is fine, locating the correct div is fine but I cannot find how to iterate through the list.
What I am trying is:
Sub getdata()
Dim ie As InternetExplorer
Dim html As HTMLDocument
Set ie = New InternetExplorer
ie.Visible = False
ie.navigate "http://www.springfieldeducationalfurniture.co.uk/products/60-Chair-Trolley/11116/"
Do While ie.READYSTATE <> READYSTATE_COMPLETE
Application.StatusBar = "Attempting connection ..."
DoEvents Loop
Set html = ie.document
Set ie = Nothing
Application.StatusBar = ""
Dim content Set content = html.getElementsByClassName("tabs__content")
For Each bullet In content
'tried this
IHtml = bullet.innerHTML'this gives the whole div not sure how to convert to a string
'and this but get "Run-time error '438': Object doesn't support this property or method"
IHtml = bullet.getElementsByTagName("li")
Next
End Sub
They HTML I am after is as follows, I am wanting to iterate through the <ul> in the <div class="tabs__content"> and assign the content i.e. "Requires simple self assembly" to a cell in excel (once I read the data from the list, the rest is easy):
<div class="tabs">
<div class="container">
<ul class="tabs__nav">
<li class="is-active background-grey-lighter">
Description
</li>
<li class="background-grey-light">
Delivery
</li>
</ul>
</div>
<div class="tabs__tab tabs__tab--product-info is-active">
<div class="tabs__title">
Information
</div>
<div class="tabs__content">
<div class="container">
<p>
60 Chair Trolley</p>
<ul>
<li>
Requires simple self assembly</li>
<li>
Non marking wheels </li>
<li>
Heavy duty lockable castors</li>
<li>
Black frame</li>
<li>
Vertical / hanging chair storage</li>
<li>
Does not fit through a single doorway</li>
<li>
Fits through double doors when fully loaded</li>
<li>
Dimensions: W780 x L1770 x H1340mm</li>
</ul>
<p>
Code: Y16527<br />
</p>
</div>
</div>
</div>
<div class="tabs__tab tabs__tab--product-info ">
<div class="tabs__title">
Delivery
</div>
<div class="tabs__content">
<div class="container">
<p>
Please <span style="color: rgb(0, 0, 255);">contact us</span> for delivery information.</p>
</div>
</div>
</div>
</div>
And this targets the class you mentioned. Requires reference to HTML Object library and Microsoft XML (your version)
Option Explicit
Sub Getinfo2()
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
With http
.Open "GET", "http://www.springfieldeducationalfurniture.co.uk/products/60-Chair-Trolley/11116/", False
.send
html.body.innerHTML = .responseText
End With
Dim posts As MSHTML.IHTMLElementCollection
Dim post As MSHTML.IHTMLElement
Set posts = html.getElementsByClassName("tabs__content")(0).getElementsByTagName("li")
For Each post In posts
Debug.Print post.innerHTML
Next post
End Sub
Output:
This gets the html for all the li elements
Option Explicit
Sub Getinfo2()
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
With http
.Open "GET", "http://www.springfieldeducationalfurniture.co.uk/products/60-Chair-Trolley/11116/", False
.send
html.body.innerHTML = .responseText
End With
Dim posts As MSHTML.IHTMLElementCollection
Dim post As MSHTML.IHTMLElement
Set posts = html.getElementsByTagName("li")
For Each post In posts
Debug.Print post.innerHTML
Next post
End Sub
Here is an alternative option that doesn't require any reference's to library's (Late binding). It also show a different way of looping through the class, as well as the LI's.
Sub getData()
Dim ie As Object
Dim li As Object
Dim tabsClass As Object
'Late Binding
Set ie = CreateObject("InternetExplorer.Application")
On Error GoTo Catch
ie.Visible = False
ie.navigate "http://www.springfieldeducationalfurniture.co.uk/products/60-Chair-Trolley/11116/"
While ie.ReadyState <> 4 Or ie.Busy: DoEvents: Wend
'LOOP EACH CLASS ELEMENT
For Each tabsClass In ie.Document.getElementsByClassName("tabs__content")
'LOOP EACH LI WITHIN THAT CLASS
For Each li In tabsClass.getElementsByTagName("li")
Debug.Print li.innertext
Next li
Next tabsClass
'CLOSE INSTANCE OF IE
Catch:
ie.Quit
Set ie = Nothing
End Sub

Scraping dropdown menu selection

Hi I have a code for an automation using VBA, What I've managed to reach so far is the code is opening the url, entering the credentials, accessing the search page, however in the search page, I cannot select any of the options in the dropdown menu.
below is the code from the website, and the VBA code
Sub Test()
Dim rng As Range
Set rng = Sheets("sheet1").Range("A1", Sheets("sheet1").Cells.Range("A1").End(xlDown))
Dim ie As Object
Set ie = CreateObject("InternetExplorer.application")
ie.Visible = True
ie.Navigate ("Home page")
Do
If ie.ReadyState = 4 Then
Exit Do
Else
DoEvents
End If
Loop
ie.Document.forms(0).all("txtUsername").Value = ""
ie.Document.forms(0).all("txtPassword").Value = ""
ie.Document.forms(0).submit
ie.Visible = True
Application.Wait (Now + TimeValue("00:00:02"))
For Each cell In rng
ie.Navigate ("search URL")
DoEvents
Set myElementsCollection = ie.Document.getElementsByTagName("Global Service Reference")
ie.Document.getElementById("txtFieldValue").Select
SendKeys (cell.Value)
DoEvents
ie.Document.forms(0).getElementById("cmdFind").Click
Next cell
End Sub
and the code for the webpage as its an intranet URL
<form action="search.asp?Find=1" method="post" onsubmit="return validate(this);">
<table border="0" cellspacing="0" cellpadding="2" width="100%">
<tbody><tr>
<td valign="top">
<br><table border="0" cellspacing="0" cellpadding="2" width="100%">
<tbody><tr>
<td colspan="3"><b><font size="3" face="cambria" color="#e60000">Please enter your search criteria:</font></b></td>
</tr>
<tr>
<td width="20%">
<select name="cboFieldName">
<option value="0"></option>
<option value="1">Customer Name</option>
<option value="2">Customer Reference</option>
<option value="3">Site Name</option>
<option value="4">Site City</option>
<option value="5">Site Country</option>
<option value="6">Global Service Reference</option>
<option value="7">Customer Service Reference</option>
</select>
</td>
<td align="center" width="10%"><font size="2" face="Tahoma" color="#000000">contains</font></td>
<td width="50%">
<input type="text" name="txtFieldValue" value="">
</td>
</tr>
</tbody></table>
</td>
<td width="25%" valign="top">
<table border="0" cellpadding="0" cellspacing="0">
<tbody><tr>
<td width="2" bgcolor="#003399"> </td>
<td width="10"> </td>
<td>
<font size="2" face="Tahoma">
<input type="submit" style="background-color:#a3418f" name="cmdFind" value="Find">
<p>
All Customers<br><br>
New Search<br><br>
Help...
</p></font></td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</form>
Try this. It should work:
Sub Select_dropdown_item()
With CreateObject("InternetExplorer.Application")
.Visible = True
.navigate "you_link"
While .Busy = True Or .readyState < 4: DoEvents: Wend
''if the script fails, activate the delay
' Application.Wait Now + TimeValue("00:00:05")
' Set post = .document.getElementsByName("cboFieldName")(0)''activate this line if you want to select using index
' post.selectedIndex = 2
''the below portion will select the item using it's name
For Each post In .document.getElementsByName("cboFieldName")(0).getElementsByTagName("option")
If InStr(post.innerText, "Customer Name") > 0 Then post.Selected = True: Exit For
Next post
End With
End Sub

VBA Web query with login+password

Morning guys,
Using already answered questions on here i am still unable to get any code to work for my particular site, unfortunately as it is an internal website i cannot share the actual site.
The site is a .jsp login page could this be causing the issue? The macro opens the login page in IE but doesn't enter any user data into the fields or submit currently.
I also get error message "the object invoked has disconnected from it's clients" once the macro is running.
Microsoft internet controls is active and
Forms 2.0 is active in references also
I am fairly new to VBA to if i am missing anything obvious please let me know, i have lowered security settings within IE also.
EDIT I am somewhat sure this is to do with my form ID's but i can't see where i went wrong?
Sub GetTable()
Dim ieApp As InternetExplorer
Dim ieDoc As Object
Dim ieTable As Object
Dim clip As DataObject
'create a new instance of ie
Set ieApp = New InternetExplorer
'you don’t need this, but it’s good for debugging
ieApp.Visible = True
'assume we’re not logged in and just go directly to the login page
ieApp.Navigate "http://dss-gp-mida-002/MidasDS/login.jsp
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.ReadyState = READYSTATE_COMPLETE: DoEvents: Loop
Set ieDoc = ieApp.Document
'fill in the login form – View Source from your browser to get the control names
With ieDoc.forms(0)
.Username.Value = "Carterr"
.Password.Value = "password"
.submit
End With
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.ReadyState = READYSTATE_COMPLETE: DoEvents: Loop
'now that we’re in, go to the page we want
ieApp.Navigate "http://dss-gp-mida-002/MidasDS/homepage.jsp"
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.ReadyState = READYSTATE_COMPLETE: DoEvents: Loop
'get the table based on the table’s id
Set ieDoc = ieApp.Document
Set ieTable = ieDoc.all.Item("sampletable")
'copy the tables html to the clipboard and paste to teh sheet
If Not ieTable Is Nothing Then
Set clip = New DataObject
clip.SetText "" & ieTable.outerHTML & ""
clip.PutInClipboard
Sheet1.Select
Sheet1.Range("A1").Select
Sheet1.PasteSpecial "Unicode Text"
End If
'close 'er up
ieApp.Quit
Set ieApp = Nothing
End Sub
Page Source:
<input type="hidden" name="urlwanted" value=""><input type="hidden" name="sourcePageURL" value=""><input type="hidden" name="ssoiid" value="">
<div>
<div class="form-group">
<label for="username">Username</label><input name="username" id="username" type="text" class="form-control" placeholder="Enter Username">
</div>
<div class="form-group">
<label for="password">Password</label><input name="password" id="password" type="password" class="form-control" placeholder="Enter Password">
</div>
<script>
$("#username").keyup(function(event) {
if (event.which == 13) {
$("#loginform").submit();
}
});
$("#password").keyup(function(event) {
if (event.which == 13) {
$("#loginform").submit();
}
});
</script>
<div class="form-group">
<div class="btn-group-vertical-justified">
<button name="login" type="button" value="Log In" class="btn btn-primary" onclick="document.loginform.ssoiid.value="";document.loginform.submit()">Log In</button>
</div>
I used the following in something similar:
Set ie = GetIE("www.url.com")
If Not ie is Nothing Then
ie.navigate (strtarget) 'strtarget is the target url
Do Until ie.ReadyState = 4: DoEvents: Loop
If ie.LocationURL = "www.url.com/loginpage" Then
MsgBox "Login Please!!"
Else
pageText = ie.document.body.innertext
End if
Else
MsgBox "IE not found!!"
End if
It will display a messagebox which asks you to sign in if you land on the loginpage. Then you manually log in and start the script again.

Extracting data from a web page using VBA code

I am wrting a visual basic code to automatically extract some weather data. The following is the source code of the web page.
<tr><td>
<table align="center" width="100%" summary="table used for formatting"><tr>
<td align="center"><b>Example:</b></td>
<td align="center" width="40%">Latitude 33.5<br>Longitude -80.75</td>
<td align="center">OR</td>
<td align="center" width="40%">Latitude 33 30<br>Longitude -80 45</td>
</tr></table></td></tr>
<tr><td><table width="100%" summary="table used for formatting"><tr>
<td><b><label for="lat">Latitude? </label>
<input type="text" name="lat" id="lat" size="12" value=""></b></td>
<td width="30%">South: -90 to 0</td>
<td width="30%">North: 0 to 90</td>
</tr><tr>
<td><b><label for="lon">Longitude? </label>
<input type="text" name="lon" id="lon" size="12" value=""></b></td>
<td width="30%">West: -180 to 0</td>
<td width="30%">East: 0 to 180</td>
</tr></table></td></tr>
<tr><td><table align="center" summary="table used for formatting"><tr>
<td><b> <input type="submit" name="submit" value="Submit"> </b></td>
<td><b> <input type="submit" name="submit" value=" Reset "> </b></td>
<td><i> This form is "Reset" if the input is out of range. </i></td>
</tr></table>
</td></tr></table>
</form>
I am getting an error (Object variable or With block variable not set). Could anybody help me on this code? Thank you very much in advance. Here is what I have written:
Sub extractSolData()
Dim IE As Object
Dim latitude As String, longitude As String
Set IE = CreateObject("InternetExplorer.Application")
latitude = InputBox("Enter Latitude of the location")
longitude = InputBox("Enter Longitude of the location")
With IE
.Visible = True
.navigate ("https://eosweb.larc.nasa.gov/cgi-bin/sse/grid.cgi?email=skip#larc.nasa.gov")
While IE.readyState <> 4
DoEvents
Wend
IE.document.getElementsByName(“lat”).Item(0).Value = latitude
IE.document.getElementsByName(“lon”).Item.innertext = longitude
IE.document.getElementsByName("submit").Item.Value = "Submit"
Do While .Busy Or _
.readyState <> 4
DoEvents
Loop
End With
Set IE = Nothing
End Sub
The problem is with the quotation marks you are using in
IE.document.getElementsByName(“lat”).Item(0).Value = latitude
IE.document.getElementsByName(“lon”).Item.innertext = longitude
These are not real quotes, I bet you copied this from a website and somehow the quotations marks got messed up. They need to look like
IE.document.getElementsByName("lat").Item(0).Value = latitude
IE.document.getElementsByName("lon").Item.innertext = longitude
You could have shortened all of that to the following by concatenating the lat on long into URL string:
Option Explicit
Public Sub nota_ong()
Dim latitude As String, longitude As String
latitude = InputBox("Enter Latitude of the location")
longitude = InputBox("Enter Longitude of the location")
If latitude = vbNullString Or longitude = vbNullString Then Exit Sub
With CreateObject("internetexplorer.application")
.Visible = True
.navigate "https://eosweb.larc.nasa.gov/cgi-bin/sse/grid.cgi?email=skip%40larc.nasa.gov&step=1&lat=" & LATITUDE & "&lon=" & LONGITUDE & "&submit=Submit"
While .Busy Or .readyState < 4: DoEvents: Wend
'Do stuff with new page
'Quit '< Uncomment this later
End With
End Sub

Filling Internet Explorer inputbox

I read so many answers to my problem but somehow if I try to "mimic" what I see, I still am not able to do what I need.
The problem is very simple: fill an inputbox on an opened IE page.
Result: the code gets stuck on the line with getelementbyid showing runtime error 424 (object required).
Private Sub AddInfoFromIntranet()
Dim ie As Object
Set ie = CreateObject("internetexplorer.application")
Application.SendKeys "{ESC}" ' I need this to ignore a prompt
With ie
.Visible = True
.navigate "{here goes the address of my website}"
Do Until Not .Busy And .readyState = 4
DoEvents
Loop
.document.getelementbyid("Nachnamevalue").Value = "{here goes whar I want to insert}"
End With
Set ie = Nothing
End Sub
Internet Explorer libraries were naturally imported (otherwise the "internetexplorer.application" wouldn't work.
I am positive that the field I want to fill is called "Nachnamevalue" as from what I learned this morning taking a look around the internet.
The html code of my webpage (only the interesting piece) looks like this:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
'{here there are info on the style, which i'm gonna ignore}
</style>
</head>
<body bgcolor="#ffffcc"><table width="1000"><tbody><tr><td>
<form name="Suchform" action="index.cfm" method="get" target="bottom_window">
Nachname:
<select name="Nachnamepulldown" class="font09px" onchange="wait_and_search()">
<option value="BEGINS_WITH">beginnt mit
<option value="EQUAL">ist
<option value="CONTAINS">enthält
</option></select>
<input name="Nachnamevalue" onkeyup="wait_and_search()" type="text" size="8">
Abteilung:
<select name="Abteilungpulldown" class="font09px" onchange="wait_and_search()">
<option value="BEGINS_WITH">beginnt mit
<option value="EQUAL">ist
<option value="CONTAINS">enthält
</option></select>
<input name="Abteilungvalue" onkeyup="wait_and_search()" type="text" size="3">
<input name="fuseaction" type="hidden" value="StdSearchResult">
<input type="submit" value="suchen">
<script language="JavaScript" type="text/JavaScript">
document.Suchform.Nachnamevalue.focus();
</script>
</form>
</td></tr></tbody></table></body>
</html>
There is also (I don't know if it can help) an "embedded" javascript that brings results of a search up every time at least 2 characters in the "Nachnamevalue" inputbox are written.
What am I doing wrong?
EDIT:
When I try to execute the Sub step-by-step, I get the following:
Set Doc = ie.document
? Doc
[object HTMLDocument]
( in the watchlist it is an object without any variables inside )
GetElementById gets an element by its id attribute, but "Nachnamevalue" is the value of the name attribute.
To use the name:
.document.Forms("Suchform").Elements("Nachnamevalue").value = "xxx"
This worked for me. The code uses HTML from your question in file c:\Temp\page1.html.
Option Explicit
' Add reference to Microsoft Internet Controls
' Add reference to Microsoft HTML Object Library
Sub AddInfoFromIntranet()
Dim ie As SHDocVw.InternetExplorer
Dim doc As MSHTML.HTMLDocument
Dim elements As MSHTML.IHTMLElementCollection
Dim nachnameValueInput As MSHTML.HTMLInputElement
Set ie = New SHDocVw.InternetExplorer
With ie
.Visible = True
.navigate "c:\Temp\page1.html"
Do Until Not .Busy And .readyState = 4
DoEvents
Loop
Set doc = .document
Set elements = doc.getElementsByName("Nachnamevalue")
If Not elements Is Nothing Then
Set nachnameValueInput = elements(0)
If Not nachnameValueInput Is Nothing Then _
nachnameValueInput.Value = "{here goes whar I want to insert}"
End If
.Quit
End With
Set ie = Nothing
End Sub
To check the names of all input elements which exist at the momonet you execute the VBA code on the page you could use getElementsByTagName("input").
Set elements = doc.getElementsByTagName("input")
If Not elements Is Nothing Then
Dim inputElement
For Each inputElement In elements
Debug.Print inputElement.Name
Next inputElement
End If
You can try cycling all input and selecting the one is named as you need:
Set Elements = IE.document.getelementsbytagname("Input")
For Each Element In Elements
If Element.Name = "Nachnamevalue" Then
Element.Value = {Here your value}
Exit For
End If
Next Element