EXCEL VBA: Web Page Button Click - excel

I have tried numerous variations of codes on this site to get my VBA to click on a button on a webpage and with the exception of one time have not been able to get any code to work. The one time was either a fluke or in an attempt to add the next step of the code I somehow inadvertently changed what was happening previously. Below is both the source code of the website and the code I'm using currently. Right now I do not get any errors, but instead of loading the next page when I include the button click code if just clears the form and stays on the present web page.
CODE:
Public Sub TestIE()
Dim IE As Object
Dim aNodeList As Object, i As Long
Dim bNodeList As Object, p 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://pe.fanniemae.com/pe/pricing/search"
' 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 18
aNodeList.Item(i).Checked = True
Next i
'IE.document.querySelector("button[type=submit]").Click
Set bNodeList = IE.document.querySelectorAll("button[type=submit]")
If bNodeList Is Nothing Then Exit Sub
For p = 1 To 1
bNodeList.Item(p).Click
Next p
End Sub
Page Source:
<div class="row submit">
<button id="get-price" tabindex="3" type="submit" class="cell-right-
2">Get Prices</button>
<div class="pricing-error-message"></div>
When I inspect element on the button it does appear there is a clear form part of the code, which I would expect, but for whatever reason it is clearing the form instead of loading the new page. When I click on the button manually in IE it loads as expected.
Script that I believe is running:
<script type="text/javascript">
define('pageConf', function() {
return null || JSON.parse('{\"lastPricingFactors\":
{\"priceIncrement\":\"18\",\"priceView\":\"total\",\"executionType\
":\"Mandatory\",\"levelType\":\"Product\",\"remittanceType\":\"ActualActual
\",\"products\":\"160958\",\"1036FR\",\"102422\",\"163053\",\"160639\",\"
160058\",\"155509\",\"154232\",\"143846\",\"0005FR\",\"125331\",\"102301\",
\"114921\",\"115446\",\"144854\"],\"underwrittenWithDu\":false,\"
servicingReleased\":false,\"displayMarketFrozenMessage\":false,\"windows\":
[10,30,60,90],\"requestTimeMs\":1531424470700}}')
});
</script>

I was able to utilize a Select Case that inserted the criteria I wanted selected in the URL that was generated by the button vs. having to actually press the button which seems to be a working work around. Thanks for taking a look at this.

Related

Filling Internet Explorer Forms from Excel

I want to fill information onto the site 'select picker' section on the left side of the picture.
SITE
There is an element name 'picker' but it won't work.
The search bar is being completed using jQuery auto-complete which submits a form that navigates to an associate from the auto-complete box has been selected
I tried
IE.Document.All("picker").Value = "Testing"
IE.Document.GetElementByID("pickerCtrl.currentPicker").Value = "Testing"
IE.Document.GetElementsByClassName("input-group input-group-sm").Item(0).Value = "Testing"
PS.
Is there way to just copy and paste the row at the current position where cursor is positioning at?
I can sendkeys tab 18 times to get to that specific search bar but do not know how to insert the entire row from my Excel sheet.
eg. IE.Document.all("picker").Value = ThisWorkbook.Sheets("Main_1").Range("B" & intRow).Value
I am completely new to this.
Try to make a test with example below may help to solve the issue.
Sub demo1()
Dim i As Long
Dim URL As String
Dim IE As Object
Dim HWNDSrc As Long
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
URL = "D:\Backup20190913\tests\367.html"
IE.Navigate URL
Do While IE.ReadyState = 4: DoEvents: Loop
Do Until IE.ReadyState = 4: DoEvents: Loop
IE.Document.querySelector("[name='picker']").Value = "test value"
Stop
Set IE = Nothing
End Sub
HTML
<input class="form-control ng-valid ng-isolate-scope ng-touched ng-dirty" ng-model="pickerCtrl.currentpicker" name="picker" type="text" typeahead="" typeahead-source="pickerCtrl.getpickerStrings()" ng-disabled="pickerCtrl.errorLoadingPickers || pickerCtrl.noPickerstrings" ng-hide="pickerCtrl.disableTypeahead" autocomplete="off">
Output:

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

Why Can't I Get My Web Page to Jump To The Requested Page Thru VBA Excel

I am trying to get VBA Excel to navigate thru the data table on a web page.
The web page opens at page # 1. I can update the web page number with VBA Excel code. (At least it looks like its working.)
But I can not seem to get the data which applies to my requested page to display on the screen. If I click on the drop down page button with my mouse, the button seems "dead". I can select another page successfully with the mouse OK and then I can select the page number which I tried to pick with Excel VBA OK also.
I am using IE. Version 11 which I believe uses the dispatch event.
I have been trying all sorts of tricks which I researched on the net without success.
The following code is my latest attempt. I hope someone with more experience than me can help. Thanks in advance.
Sub ExtractTablesData()
Dim IE As Object
Dim obj As Object
Dim elemCollection As Object
Dim evt
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.navigate ("http://My Web Page")
While IE.readystate <> 4 ' wait for pages to download
DoEvents
Wend
Do While IE.busy: DoEvents: Loop ' make sure page has downloaded
Set elemCollection = IE.Document.getelementsbytagname("TABLE")
Set evt = IE.Document.createEvent("HTMLEvents")
evt.initEvent "change", False, True
IE.Document.getElementsbyClassName("pager-select")(0).selectedIndex = 5
' trying to get the 6th page of data
IE.Document.getElementsbyClassName("pager-select")(0).Click
IE.Document.getElementsbyClassName("pager-select")(0).dispatchEvent (evt)
Application.Wait (Now + TimeValue("0:00:02"))
Do While IE.busy: DoEvents: Loop ' make sure page has downloaded
While IE.readystate <> 4 ' wait for pages to download
DoEvents
Wend
End With ' IE
Had True False reversed.
Accidentally found correct answer on another webpage.
Works like a charm now.
evt.initEvent "change", True, False

VBA: It only shows ID at Ispect Element

I'm a newbie at VBA programming, and I use it to build macro a in excel. Here is this webpage: http://www.eppraisal.com/home-values/property/14032-s-atlantic-ave-riverdale-il-60827-59143864/
I want to extract the value of $52,920 on the right upper corner. When I select the Inspect Element, this is the following:
<p id="eppraisalval">$52,920</p>
I checked the Page Source, but I couldn't find it. The closest thing I found:
<span id="eppraisal_val" class="valuation-estimates-price ajaxload" data-url="/home-values/property_lookup_eppraisal?a=14032%20S%20Atlantic%20Ave&z=60827&propid=59143864">loading...</span>
I tried the get getElementById("eppraisal_val") and getElementById("eppraisalval"), but none of those worked.
How can I address my code to get that element?
Here is more from the inspect element window, aroun that code:
<span id="eppraisal_val" class="valuation-estimates-price ajaxload" data-url="/home-values/property_lookup_eppraisal?a=14032%20S%20Atlantic%20Ave&z=60827&propid=59143864"><p id="eppraisalval">$52,920</p><p class="main-page-description-small valuation_details" style="display:none;margin-top:5px">Low: $44,982 <br>High: $60,858</p></span>
Here is the shorter version of code I tried:
Sub macroID()
On Error Resume Next
Dim ie As Object
Set ie = CreateObject("internetexplorer.application")
Dim doc As HTMLDocument
Dim valuation As String
Dim val1 As String, val2 As String
Set doc = ie.Document
ie.Visible = True
ie.navigate "http://www.eppraisal.com/home-values/property/14032-s-atlantic-ave-riverdale-il-60827-59143864/"
Do
DoEvents
Loop Until ie.readyState = READYSTATE_COMPLETE
Set doc = ie.Document
valuation = doc.getElementById("eppraisalval")
Cells(1, 4).Value = valuation
Application.Wait (Now + TimeValue("0:00:03"))
End Sub
The issue with scraping from that URL is that there is a verification page before hand which requires you to confirm you "are not a robot" which makes it hard to scrape anything from it.
If you manually do this first it may save this in your cache and then allow you to run macros freely to scrape the website however you'd have to try this out.
In the meantime, the only issue I could see with your code is that you haven't included .innertext after .getElementById("eppraisalval"). The valuation line should look like this:
valuation = doc.getElementById("eppraisalval").innerText

Excel VBA: Wait for JavaScript execution in Internet Explorer

I am trying to do some web scraping in Excel VBA. Here is the part of the code that I am having trouble with:
IE.Navigate URL
Do
DoEvents
Loop While IE.ReadyState <> 4 Or IE.Busy = True
Set doc = IE.document
After running this doc contains html that still has unexecuted JavasScript in it.
This is the signature of the script that has not been executed:
<SCRIPT type=text/javascript>
goosSearchPage.Initialize(...)...;
</SCRIPT>
I can wait for execution by doing Application.Wait(Now + TimeValue(x)) but that really is not satisfactory, as the amount of time the script takes to execute is quite variable depending on input.
Is there a way to either wait for the script to finish evaluating or to just evaluate the script directly in the doc object?
I found code that does wait for a page to complete. per the notes here, it requires the Microsoft Internet Controls as a reference in your code.
Code reproduced here, just in case the link dies:
'Following code goes into a sheet or thisworkbook class object module
Option Explicit
'Requires Microsoft Internet Controls Reference Library
Dim WithEvents ie As InternetExplorer
Sub start_here()
Set ie = New InternetExplorer
'Here I wanted to show the progress, so setting ie visible
ie.Visible = True
'First URL to go, next actions will be executed in
'Webbrowser event sub procedure - DocumentComplete
ie.Navigate "www.google.com"
End Sub
Private Sub ie_DocumentComplete(ByVal pDisp As Object, URL As Variant)
'pDisp is returned explorer object in this event
'pDisp.Document is HTMLDocument control that you can use
'Following is a choice to follow,
'since there is no do-loop, we have to know where we are by using some reference
'for example I do check the URL and do the actions according to visited URL
'In this sample, we use google entry page, set search terms, click on search button
'and navigate to first found URL
'First condition; after search is made
'Second condition; search just begins
If InStr(1, URL, "www.google.com/search?") > 0 Then
'Open the first returned page
ie.Navigate pDisp.Document.getelementsbytagname("ol")(0).Children(0).getelementsbytagname("a")(0).href
ElseIf InStr(1, URL, "www.google.com") > 0 Then
pDisp.Document.getelementsbyname("q")(0).Value = "VB WebBrowser DocumentComplete Event"
pDisp.Document.getelementsbyname("btnG")(0).Click
End If
End Sub
You actually can evaluate the javascript function with the ie window. But you gotta set up a Callback because the function will be evaluated async.
This post is quite old, but I'll answer this also as a reply to myself, now that I've discovered how to do this.
Simply point to a content you expect to be there after the jQuery script has run, trigger the desired event using JavaScript ran through IE automation, and do a Loop to wait until the desired content appears.
'This will trigger the jQuery event.
Doc.parentWindow.execScript "$('#optionbox').trigger('change')"
'This is the code that will make you wait. It's surprisingly efficient
Do While InStrB(Doc.getElementById("optionbox").innerHTML, "<desired html tag>") = 0
DoEvents
Loop

Resources