VBA Set Dropdown value - excel

I have a macro that I have written in excel and I have navigated to a webpage using "ActiveWorkbook.FollowHyperlink", which works just as I need it!
However, I now need to update a dropdown menu on that webpage.
I have an ID for the dropdown and each selection obviously has a value. I want to set the selected option using the value, which I have in the excel sheet.
I am struggling because I don't know how to access elements on the page, once opened using .FollowHyperlink.
After .FollowHyperlink is the webpage then active, is there something like ActiveWebPage.getElementById?
Appreciate any help.
Mike

what you want to do is use com automation to call an instance of internet explorer and navigate to the page in question, this will give you the document model, from there you can do most anything, see IE (Internet Explorer) Automation using Excel VBA
Sample VBA follows
Private Sub IE_Autiomation()
Dim i As Long
Dim IE As Object
Dim objElement As Object
Dim objCollection As Object
' Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
IE.Navigate "http://www.excely.com/"
' Statusbar
Application.StatusBar = "www.excely.com is loading. Please wait..."
' Wait while IE loading...
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
' Find 2 input tags:
' 1. Text field
' <input type="text" class="textfield" name="s" size="24" value="" />
'
' 2. Button
' <input type="submit" class="button" value="" />
Application.StatusBar = "Search form submission. Please wait..."
Set objCollection = IE.document.getElementsByTagName("input")
i = 0
While i < objCollection.Length
If objCollection(i).Name = "s" Then
' Set text for search
objCollection(i).Value = "excel vba"
Else
If objCollection(i).Type = "submit" And _
objCollection(i).Name = "" Then
' "Search" button is found
Set objElement = objCollection(i)
End If
End If
i = i + 1
Wend
objElement.Click ' click button to search
' Wait while IE re-loading...
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
' Show IE
IE.Visible = True
' Clean up
Set IE = Nothing
Set objElement = Nothing
Set objCollection = Nothing
Application.StatusBar = ""
End Sub

Related

DOM VBA IE11 Automate Placing Orders on a Website - Trouble With OnChange and Picture Upload

We have a Virtual Assistant placing hundreds of orders for ball markers on this site:
https://www.golfballs.com/Golf-Misc/Tools/Classic-Photo-Poker-Chips-3-Pack.htm
I had used VBA before to get data from a website but I would like to use it to automate the placing of orders. I can get close but there are a few things tripping me up.
First of all, when you select a color with your mouse, the "Upload a Photo" box appears. I cannot get the box to show up using my VBA code.
Using VBA, I cannot make the onchange event fire for the life of me. I have tried the following four combinations:
doc.getElementById("2").selectedIndex = 2
doc.getElementById("2").FireEvent ("onchange")
doc.getElementById("2").Focus
doc.getElementById("2").selectedIndex = 2
doc.getElementById("2").FireEvent ("onchange")
doc.getElementById("2").selectedIndex = 2
doc.getElementById("2").FireEvent ("onclick")
doc.getElementById("2").Focus
doc.getElementById("2").selectedIndex = 2
doc.getElementById("2").FireEvent ("onclick")
Second, even if I can get the boxes to show and I click on "Upload a Photo", the popup box is there and I am having trouble putting the focus on it and I am unsure on how to tell the ID "fileField" what picture from my browse I want to upload. There is also a second Confirmation pop up.
If I can get the picture upload to work, I can successfully complete the automated order. Here is my code through clicking the Add to Cart button. The entirety of my "Upload Picture" section does not work and the last line under "Select the Color" does not make the "Upload a Photo" box show.
Dim IE As InternetExplorer
Dim doc As HTMLDocument
Set IE = New InternetExplorer
IE.Visible = True
'Go to the Ball Marker Page
ballMarkerURL = "https://www.golfballs.com/Golf-Misc/Tools/Classic-Photo-Poker-Chips-3-Pack.htm"
IE.navigate ballMarkerURL
'Wait for page to load
Do While IE.readyState <> READYSTATE_COMPLETE Or IE.Busy: DoEvents: Loop
Set doc = IE.document
'Select the Color
doc.getElementById("2").Focus
doc.getElementById("2").selectedIndex = 2
doc.getElementById("2").FireEvent ("onchange")
'Upload Picture
markerFilePath = "M:\Cuddle Clones Share (Team Folder)\Operations\Vendors\Pet Prints\0 - Ready to Order - Golfballs.com\"
markerFileName = "380844 - Ball Marker - 200604-Red-1-of-1-qty-1.png"
fullString = markerFilePath & markerFileName
doc.getElementById("copyright_check").Checked
doc.getElementById("fileField").Value = fullString
doc.getElementById("upload").Click
doc.getElementById("saveBtn").Click
'Update Quantity
doc.getElementById("formQty").Value = 2
'Add to Cart
doc.getElementsByClassName("buttonStatic r addCart")(0).Click
In my original posting I explained how to trigger an event. Now I explain too how to click the "Upload a photo" button and focus the popup window.
The problem now is, the needed html document is in an iframe I can't access. I know there can be different reasons but none of them solve the problem.
This is, what I have now:
Sub SelectColorForGolfballs()
Dim objShell As Object
Dim objWindow As Object
Dim browser As Object
Dim url As String
Dim nodeColorDropDown As Object
Dim nodeThreeButtons As Object
Dim browserPopUp As Object
Dim nodeFrames As Object
Dim nodeIframeDoc As Object
Set objShell = CreateObject("Shell.Application")
url = "https://www.golfballs.com/Golf-Misc/Tools/Classic-Photo-Poker-Chips-3-Pack.htm"
'Initialize Internet Explorer, set visibility,
'call URL and wait until page is fully loaded
Set browser = CreateObject("internetexplorer.application")
browser.Visible = True
browser.navigate url
Do Until browser.ReadyState = 4: DoEvents: Loop
'Select color from dropdown
Set nodeColorDropDown = browser.document.getElementByID("2")
nodeColorDropDown.selectedIndex = 6 'Pink for testing
Call TriggerEvent(browser.document, nodeColorDropDown, "change")
'Manual break for loading the page complitly
'Application.Wait (Now + TimeSerial(pause_hours, pause_minutes, pause_seconds))
Application.Wait (Now + TimeSerial(0, 0, 2))
'Open Picture Upload
'The document changed, so you can't work with the old document here
'In a first step you need the div element with the three buttons
'we get in the last step by trigger dropdown event
'
'<div class="options-gallery">
' <a href="javascript:productSelection(1, 'P');">
' <img src="https://d1tp32r8b76g0z.cloudfront.net/images/property/button/Half/Condition_P.jpg" title="Personalized" border="0">
' </a>
' <a href="javascript:productSelection(1, 'S');">
' <img src="https://d1tp32r8b76g0z.cloudfront.net/images/property/button/Half/Condition_S.jpg" title="Photo" border="0">
' </a>
' <a href="javascript:productSelection(1, 'L');">
' <img src="https://d1tp32r8b76g0z.cloudfront.net/images/property/button/Half/Condition_L.jpg" title="Novelty" border="0">
' </a>
'</div>
Set nodeThreeButtons = browser.document.getElementsByClassName("options-gallery")(0)
'The second button must be clicked
nodeThreeButtons.FirstChild.NextSibling.Click
Application.Wait (Now + TimeSerial(0, 0, 2))
'Focus popup by runnig throuhg all open windows
For Each objWindow In objShell.Windows
'Check if it's an IE
If InStr(1, UCase(objWindow.FullName), "IEXPLORE") > 0 Then
'Check if it's the right IE
If InStr(1, objWindow.document.getElementsByTagName("title")(0).innertext, "iCusomize Image Selection") Then
Set browserPopUp = objWindow
Exit For
End If
End If
Next objWindow
'Now we can work with the popup
'It has only short code over all and a very short body
'You have to access the content of an iFrame
'
'Problem: I don't know why the following don't work
'I know it can't be in the same line
'You must split the access to the iFrame
'Get a node collection of all frames/ iframes of the document
Set nodeFrames = browserPopUp.document.frames
'The following line couses the error "Access denied"
'Select the first (and only) frame from the node collection
Set nodeIframeDoc = nodeFrames(0).document
'Check the copyright checkbox
nodeIframeDoc.getElementByID("copyright_check").Click
'If you are at this point we can look ahead
End Sub
And this procedure to trigger the event you need:
Private Sub TriggerEvent(htmlDocument As Object, htmlElementWithEvent As Object, eventType As String)
Dim theEvent As Object
htmlElementWithEvent.Focus
Set theEvent = htmlDocument.createEvent("HTMLEvents")
theEvent.initEvent eventType, True, False
htmlElementWithEvent.dispatchEvent theEvent
End Sub

How to submit login credentials?

This is relating to the submit button of the login screen
HTML:
<TD background=/frontend/images/greenback.gif width=302><INPUT type=submit value="Login now" name=submit> </TD>
I enter the username and password into the box but the script stops at .Submit
Sub GetTable()
'Kills any open IE windows.
On Error GoTo Ignore
Call IE_Sledgehammer
Ignore:
Dim ieApp As InternetExplorer
Dim ieDoc As Object
Dim ieTable As Object
Dim clip As DataObject
Dim UserName As String, Password As String
'Create anew instance of ie
Set ieApp = New InternetExplorer
'Debugging
ieApp.Visible = True
'Opening this page prompts login screen
ieApp.Navigate "CANNOT SHARE, INTERNAL WORK SITE"
'When busy - wait
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.ReadyState = READYSTATE_COMPLETE: DoEvents: Loop
'Pop up window
On Error GoTo skip_Popup
ieApp.Document.all.item("submitBn").Focus
SendKeys "~"
skip_Popup:
'Login script
On Error GoTo Skip_Login
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 = "test1"
.Password.Value = "test2"
.Submit
End With
Do While ieApp.Busy: DoEvents: Loop
Do Until ieApp.ReadyState = READYSTATE_COMPLETE: DoEvents: Loop
Skip_Login:
'Copy page Info
Set ieDoc = ieApp.Document
Set ieTable = ieDoc.all.item
'Copy Paste the page
If Not ieTable Is Nothing Then
Set clip = New DataObject
clip.SetText "" & ieTable.outerHTML & ""
clip.PutInClipboard
'Location of data
Sheets("Raw Data").Range("E2").PasteSpecial "text"
End If
'Delete any form controls that make it into the sheet
Sheets("Raw Data").DrawingObjects.Delete
'Kills ALL IE windows
Call IE_Sledgehammer
Set ieApp = Nothing
End Sub
Also this is not critical, how do I just select the table on the page and not everything else? It doesn't have a name so I am stuck with this one also.
HTML:
<table cellspacing="1" cellpadding="2" align="center" border="0" width="400">
Try using attribute = value css selector
ie.document.querySelector("[name=submit]").click
For your table your best bet is to locate it by it's relationship to other elements/attributes. Impossible to advise further without seeing more html. Failing that if there is a unique attribute or attribute=value in that table (not present in other tables) then combine that to id the table
e.g.
ie.document.querySelector("table[width='400']")
This is a less robust method.
I tested your code and I am able to produce the issue.
As an alternative, you can try to loop through input elements and try to find the submit and click it.
Set objCollection = ieApp.document.getElementsByTagName("input")
i = 0
While i < objCollection.Length
If objCollection(i).Type = "submit" And _
objCollection(i).Name = "submit" Then
objCollection(i).Click
End If
i = i + 1
Wend

IE Handling in Excel macros

I am new to Excel macros and I am trying to auto-fill the text box and select the option from Dropdown and click on Submit.
Using macros I have navigated to a page and from the page, I need to enter the text in the text box, and based on the Suggestion, I need to select the option.
Once the option is selected I need to click on continue using macros.
Here is the current code (I tried with the commented line but it's not working).
Sub Create_Change()
Dim i As Long
Dim URL As String
Dim IE As Object
Dim objElement As Object
Dim objCollection As Object
Dim HWNDSrc As Long
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
URL = "URL to Navigate"
IE.Navigate URL
Application.StatusBar = URL & " is loading. Please wait..."
Do While IE.ReadyState = 4: DoEvents: Loop
Do Until IE.ReadyState = 4: DoEvents: Loop
Application.StatusBar = URL & " Loaded"
' IE.Document.All("Search for a template").Value = "text to search"
Set IE = Nothing
Set objElement = Nothing
Set objCollection = Nothing
End Sub
HTML CODE:
<input title="Search for a template"
class="change-template__search-input ng-pristine ng-untouched ng-valid"
role="combobox"
aria-expanded="false"
aria-owns="typeahead-258-8737"
aria-autocomplete="list"
type="text"
placeholder="Search for a template"
ng-enter="getRecommendedTemplates(template.search)"
ng-model="template.search"
typeahead="template as template for template in getTemplateList($viewValue)"
typeahead-focus-first="false"
typeahead-on-select="getRecommendedTemplates($item)"
typeahead-min-length="3">
I think you need to search through all the elements returned by Document.All(). Try looping through the collection that is returned. This is much easier if the control had an id, but you will have to check each element having a title = "Search for a template". Once you have found the item you can set the text.
I suggest debugging so you can see what .All returns and then you can work from there.
welcome to SO. If you need to get an element, as drHodge said, using an iterator and some sort of ID attribute is usually enough. I tried this with Google a minute ago:
Dim Item As Object
For Each Item In IE.Document.all()
If Item.getAttribute("title") = "Buscar" Then
Item.Value = "Test"
End If
Next Item
I also made it press space, down arrow and enter, for the sake of doing something with the suggestion and searching part:
SendKeys ("{ }")
Application.Wait Now + TimeSerial(0, 0, 1)
SendKeys ("{DOWN}"), True
Application.Wait Now + TimeSerial(0, 0, 1)
SendKeys ("{ENTER}"), True
(I do not recommend using SendKeys on any script, tho; it's quite unreliable.)
You could try the following:
1) Focus and change
With ie.document.querySelector("[title='Search for a template']")
.focus
.value = "abcd"
End With
2) Javascript set value
ie.document.parentWindow.execScript "document.querySelector('[title=\'Search for a template\']').value = 'abcd';"
3) Attach event and fire
Dim evt As Object
Set evt = ie.document.createEvent("HTMLEvents")
evt.initEvent "change", True, False
With ie.document.querySelector("[title='Search for a template']")
.Focus
.Value = "abcd"
.dispatchEvent evt
End With
4) FireEvent
With ie.document.querySelector("[title='Search for a template']")
.Focus
.Value = "abcd"
.FireEvent "onchange"
End With

Excel VBA: Check all check boxes on Web Page

I'm trying to check all the checkboxes available on a webpage via VBA since the name convention doesnt appear to be one in which I can be selective. However I cannot seem to get anything to work. I can login to the website and navigate to the section of the website I want but cannot cross this hurdle. Any help would be greatly appreciate. Below is the source code from the webpage.
<li data-product-family="30yr"
data-product-amortizationTerm="30"
data-product-type="Conventional"
data-product-amortizationType="Fixed"
>
<label>
<input type="checkbox"
value="154232"
class="product-Conventional product-item"
data-authorized-remittance-types="ActualActual "
/>30-Year Fixed Rate - 110k Max Loan Amount</label>
</li>
VBA I attempted to write (edited)... code I'm using presently:
Public Sub TestIE()
Dim IE As Object
Dim aNodeList As Object, i As Long
' Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")
' You can uncoment Next line To see form results
IE.Visible = False
' Send the form data To URL As POST binary request
IE.Navigate "https://"
' Statusbar
Application.StatusBar = "Page is loading. Please wait..."
' Wait while IE loading...
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
IE.Visible = True
Set aNodeList = IE.document.querySelectorAll("input[type=checkbox]")
If aNodeList Is Nothing Then Exit Sub
For i = 0 To aNodeList.Length
aNodeList.Item(i).Checked = True
Next i
End Sub
You can try to get a nodeList of the checkboxes with:
IE.document.querySelectorAll("input[type=checkbox]")
You can traverse the nodeList along its .Length property.
E.g.
Dim aNodeList As Object, i As Long
Set aNodeList = IE.document.querySelectorAll("input[type=checkbox]")
If aNodeList Is Nothing Then Exit Sub
For i = 0 To aNodeList.Length -1
On Error Resume Next
aNodeList.item(i).Checked = True
On Error GoTo 0
Next i

How to get value from webpage?

I want to get/input value to webpage.
All my effort so far works until web loading only. I have no knowledge in web. I can't provide the website link as it's an intranet web.
done lin.e 50 is the place where I want to put my input
then click save button
<td valign="top" class="s bgltgray">
<textarea id="txtResponse1" name="txtResponse1" cols="80" rows="3" class="s">done lin.e 50.</textarea>
<input type="submit" id="cmdRespond1" name="cmdRespond1" value="Save" onclick="cmdRespond_click(1);">
<br> Latest Response By: samyvelu, On: 10/23/2017
</td>
You can try this. Can't really test it since i dont have the url, but this code have worked on another url just without the textarea Tag name
Sub IEtest()
Dim ie As Object
Dim i, x As Integer
Dim objElement As Object
Dim objCollection As Object
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.navigate "" '<--- CHANGE THIS
Do While ie.busy
Application.Wait DateAdd("s", 1, Now)
Loop
Set objCollection = ie.Document.getElementsByTagName("textarea")
i = 0
While i < objCollection.Length
If objCollection(i).Name = "txtResponse1" Then
objCollection(i).Value = "Your input" '<--- CHANGE THIS
End If
i = i + 1
Wend
Set objCollection = ie.Document.getElementsByTagName("input")
i = 0
While i < objCollection.Length
If objCollection(i).Type = "submit" And objCollection(i).Name = "cmdRespond1" Then
Set objElement = objCollection(i)
End If
i = i + 1
Wend
objElement.Click
End With
End Sub
There are ids present. Use those as they are the fastest selector method. Using InternetExplorerMedium object
With ie.document
.getElementById("txtResponse1").value = "yourValue"
.getElementById("cmdRespond1").Click '.Submit
End With

Resources