GetElementID("button").click won't activate open dialogue - vba

Hoping someone might understand what might be going on. What I'm aiming for is using Excel VBA to open my PayPal Multi-Order Shipping page, then open the "Create Shipment" dialogue box and populate the basic name and address fields using data from a row in my excel spreadsheet. My current trouble is with clicking the "Create Shipment" button to open the dialogue box so I can populate the fields ... the code seems to ignore the GetElementByID("createNewOrder").click command and does absolutely nothing. Here's my code so far if anyone would care to take a look ... any help is much appreciated.
Sub PayPalMultiShip()
Dim IE As New SHDocVw.InternetExplorerMedium
IE.Visible = True
IE.Navigate ("https://www.paypal.com/shiplabel/createbulk")
Do While IE.ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
IE.Document.getElementById("createNewOrder").click
Debug.Print "All Done"
End Sub
Here is a screenshot of the html code for the button that I'm trying to access ...
This screenshot comes from the Event Listener tab in the DOM Explorer ...
Event Listener Screenshot
I apologize, but since I'm new to the forum it won't allow me to embed pictures unless someone else suggests the edit

Related

Activate a Button on a WebPage using VBA on MsAccess

Hi I am trying to write a scraper to get data from this website (www.coned.com/tcisng) and dump data into my Ms Access Backend. When I navigate to it and enter in my credentials (username and password), it does not activate the "Log In" button which I want to click next as it is the next step on my scraper. Also this "Log In" button has no name or ID. How to activate and make it click using VBA in Ms Access 2016.
Updated Code Snippet -
Dim ie As Object
Set ie = CreateObject("internetexplorer.application")
ie.Visible = True
ie.Navigate "www.coned.com/tcisng"
While ie.Busy
DoEvents
Wend
Do
DoEvents
Loop Until ie.ReadyState = READYSTATE_COMPLETE
ie.Document.all("LoginEmail").Value = "myemail"
ie.Document.all("LoginPassword").Value = "myPassword"
Do
DoEvents
Loop Until ie.ReadyState = READYSTATE_COMPLETE
While ie.Busy
DoEvents
Wend
'ie.Document.all(48).Click
'ie.Document.querySelector("[type=submit]").Click
ie.Document.querySelector("button[title*='Log in']").Click
In the last 3 line I am trying to select the "Log In" button but it is disabled, also it has no name or ID, can you also help what exact code to replace in order to activate the button and click it later.
Instead of trying to "click" the button, try submitting the form. The Javascript for that ConEdison page would be:
document.getElementById("form-login-email").form.submit()
In the "old days", with just a plain form, this would work fine.
But on that website there is a lot more going on. That email input element has nine events attached to it. By just filling in the value, you aren't triggering any of those events.
With forms built with ReactJS, for example, the user's interaction with the Input element is monitored, and the value is extracted and stored in a non-displaying object in the DOM tree. When the Submit button is clicked, the form's visible Input elements may not be used at all. In order to feed inputs into such forms, you need to understand ReactJS data structures, and manipulate them directly.
I recently built a scraper based on Chromedriver, which allows a Chrome browser window to be controlled from an external program, such as Access VBA. Once started, Chromedriver runs as a mini-webserver on localhost, and commands sent to it from Access VBA (through a ServerXMLHTTP60 object) cause it to launch Chrome, visit a URL, send keystrokes to input elements etc. Within the browser, the keystrokes fire all the events that human keystrokes would do. The target website was ReactJS-based, but I was able to ignore all of the internal complexity of ReactJS.
Since the website runs in a regular Chrome browser, I was able to use F12 Developer Tools in the development process.
The technology is Webdriver, and was developed for building website testing tools. There are Firefox and MS Edge Chromium versions as well.

Pause and Resume Macro

I've coded a excel macro which feeds data from different columns and same row to a website. Once all the data is put in website's fields, there is a submit button which needs to be clicked. This same process has to happen for each row. Loop is there but the requirement is to click the
SUBMIT BUTTON
manually not with codes.
Since macro loops for all the rows, how can I pause it and let the user click on submit button and when post submitting webpage is ready, resume the loop again.
Please help me....
I have two suggestions for you.
(1) invoking a MsgBox will pause the code.
User can be prompt to click Ok on the MsgBox for the code to continue to run, hence before click Ok, they can click submit on the website. When the website is ready for user input again, then Ok button can be click. Drawback is they have to do two clicking instead of one, and user need to know when to click it (not too early before website is ready). Anyway the good thing is deploying this is just peace of pancake.
(2) add an event listener
Generally like this
Dim ResumeEventListener as Boolean
ResumeEventListener = False
Do While Not ResumeEventListener
ResumeEventListener = ...'<some code to set it to true when the website is ready>
DoEvents
Loop
Drawback... hmm... not easy but worth it :)

VB Form Filling

I may be missing a very basic thing, but i just dont understand why this isnt working.
I am looking to fill out some web forms based on some user input.
I have already written this in vbscript where its working flawlessly. Now i want to import it to VB.
My 2 main issues atm.
Before, i would have a piece of code:
For Each wnd In CreateObject("Shell.Application").Windows
If InStr(1, wnd.FullName, "iexplore.exe", vbTextCompare) > 0 Then
Set IE = wnd
Exit For
End If
Next
For deciding what Internet Explore window to use. However, if i use this form in VB, i miss out on pretty much any type of event handling. I cant use IsBusy, i cant use DocumentCompleted or anything.
So instead i have to declare IE as a browser.
Dim IE As New WebBrowser
Which seems fine.. Except.. Now i cant navigate anywhere, no browsers are created, theres nothing happening. So when i run my code:
IE.Navigate("www.awebwithusernameandpasswordform.org")
IE.Visible = True
Helem = IE.Document.GetElementById("username")
Helem.Value = "xxxx"
Helem = IE.Document.GetElementById("password")
Helem.Value = "xxxx"
Helem = IE.Document.Forms("signupForm")
Helem.Submit()
It just fails at the element "Username" because it never gets to navigate to the website.
It like it just ignores the IE.Navigate. I have tryed running a new process with process.start() but that doesnt work either, it still isnt opening a webpage for me or anything.
Secondly, i am having major issues having vb checking when a document is completely loaded.
In VBS i used
Do while ie.readystate <> 4 or ie.busy or ie.document.readystate <> "complete"
wscript.sleep 500
Loop
Do until ie.document.readystate = "complete"
wscript.sleep 500
Loop
And that works like a charm.
In VB, ie.document.readystate is not recognised, and i cant seem to get DocumentCompleted event handling to work. I have attempted several thing from this website, but either they just make everything hang, or it just doesnt work for various reasons. I have attempted the 2 solutions from How to wait until WebBrowser is completely loaded in VB.NET? but they both just make the script hang.
Any tips would be greatly appreciated..
What is happening is that your code runs way faster than the browser can navigate, meaning that you try to get elements before it has loaded any, as Bjørn-Roger Kringsjå tried to say.
What you need to do is to wait between .Navigate and .GetElementById :
IE.Navigate("www.awebwithusernameandpasswordform.org")
'WAIT BEFORE COMPLETION
'Continue
Helem = IE.Document.GetElementById("username")
Helem.Value = "xxxx"
However, this is really tricky to do in-line and is not recommended. It is much better to use the DocumentCompleted event handler for the browser control to run code after a page is loaded. Hope this clears it up enough.

Dealing with the open/save/cancel dialogue window in IE when using VBA

First and foremost, thank you for taking the time and interest into this question. I have been using VBA to automate manual tasks within Excel for sometime now, but just recently started exploring accessing the web using VBA.
Goal: automate file downloads (about 15-20 xlsx files daily) from a website where the file url is nowhere to be found in the page's source code.
Below are the steps that I usually take when downloading these manually.
Open login page and enter login credential to access webpage of interest (i.e. the one with all the reports)
After login in, navigate to the webpage with the report
note1: it is setup so that 1 webpage (unique URL) = displays top 55 results in the first page
note2: the same page also has a button to export/save the entire report in different formats
Download the report
Navigate to next webpage (within the same website) and repeat steps 2 and 3 (there's about 15-20 reports/webpages to navigate)
I have gotten as far as downloading the first report by clicking save using the SendKeys. Although sometimes it stops as soon as the dialogue window appears, this has worked up to this point the farthest. It is after this that I have not been able to navigate to another webpage and repeat the same steps to download. My gut feeling is that the Open/Open file/View downloads dialogue window that appears after clicking on the save button is not allowing me to repeat the download/saving process...
I tried looking at the source code of the website to see if I could find the url to the file, but could not find it (not sure if it has to do that the export only occurs after clicking on the submit button which hides the file url or something else like running a script). I'm not very familiar with WinHttpRequest, but seems to be the preferred method after doing my google research. It also looks like this would require to have a file URL, but not sure on this either...
Below is the code that I put together so far. Any help would be very very much appreciated. Thank you! :)
Sub webMacro()
Dim IE As New InternetExplorer
IE.Visible = True 'change False --> True to open the IE window
IE.navigate "https://websiteURL.net//apps/login.aspx"
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Dim Doc As HTMLDocument: Set Doc = IE.document
Doc.getElementById("username").Value = "myusername" 'login to the website
Doc.getElementById("pass").Value = "mypassword"
Doc.getElementById("Enter").Click
Sleep (1000)
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
IE.navigate "https://firstReportWebPage.net//apps/....." 'navigates to the first webpage (report) to download after login
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Doc.getElementById("##########").Click 'ID of the Export/Save button
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Doc.getElementById("###########").Click 'ID of the Submit button
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Doc.getElementById("############").Click 'ID of the field right before it enters the Open/Save/Cancel dialogue window
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Application.Wait (Now + TimeValue("0:00:02")) 'here I'm using the SendKeys to mimic what I would manually do on the keyboard to get to the "Save" button
SendKeys "{TAB}", True
SendKeys "{TAB}", True
SendKeys "{DOWN}", True
SendKeys "{ENTER}", True
Sleep (1000)
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Sleep (1000)
''***This is where it almost always gets stuck...here I'm attempting to get to the Open/Open file/View downloads dialogue window by clicking on the field right before entering the dialogue window using the tab key; same as above when trying to click on the "Save" button in the Open/Save/Cancel dialogue window.
Doc.getElementById("############").Click 'ID of the field right before it enters the Open/Open File/View Downloads dialogue window
Sleep (1000)
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Sleep (1000)
Application.Wait (Now + TimeValue("0:00:02"))
Sleep (1000)
SendKeys "{TAB}", True
Sleep (1000)
SendKeys "{TAB}", True
Sleep (1000)
SendKeys "{TAB}", True
Sleep (1000)
SendKeys "{TAB}", True
Sleep (1000)
SendKeys "{ENTER}", True
Sleep (1000)
'some other code to go here...
End Sub
I had always seen 'dont use sendkeys' advised by others, but i didnt truly know what they meant when i tried to do something similar to this.
SendKeys will randomly duplicate a key send sometimes (i was using it to control 16 windows at the same time), 1 set of instructions per window and 18,000 instructions that had to be processed.
It happened about 2-3 times for every 500 instructions that were parsed by the browsers, and i couldnt find a workaround.
The navigating the website, i wrote something that does that, and then i also wrote something that downloads the HTML of the page.
Are you able to download the HTML source of the page with the Open/Save/Cancel dialog, and see if the URL to the file exists on that page within the button etc?
If it does, you could perhaps automate navigating to that page, then downloading the HTML (i have code you can have IF the url is in the source), and then parsing the HTML within VBA to calculate the download URL?

What is the bare minimum VBA "I'm busy" dialog?

I've got a macro in PowerPoint 2010 that links audio files to each and every slide. However, this takes some time, and although there is a status bar "linking files" progress, I would like something more In your face.
Caveat: I'm really not familiar with VBA or it's API.
What I want:
ImBusyDialog("Linking Files...").Open()
// Call Sub that does real work.
ImBusyDialog.Close();
and that's it. If there's something built in like the page loading spinner in IE, then great, if not, I'm happy with a simple message box. The important thing is that it require no user intervention.
Use the same logic as you do to set the status bar. Where you set the statusbar text, you'll simply add the appropriate code to call a status dialog box.
O'Reilly has a rather detailed description on how to build a status bar dialog box with a progress bar and everything. It is probably a bit overkill for what you want, but more to see what is possible in VBA: http://oreilly.com/pub/h/2607
Stackoverflow has dealt with this issue before as well with a relatively simple box you could easily modify to show which file is being worked on an any given moment: How do I create a status dialog box in Excel
The important code from the previous post:
Sub ShowForm_DoSomething()r
Load frmStatus
frmStatus.Label1.Caption = "Starting"
frmStatus.Show
frmStatus.Repaint
'Load the form and set text
frmStatus.Label1.Caption = "Doing something"
frmStatus.Repaint
'code here to perform an action
frmStatus.Label1.Caption = "Doing something else"
frmStatus.Repaint
'code here to perform an action
frmStatus.Label1.Caption = "Finished"
frmStatus.Repaint
Application.Wait (Now + TimeValue("0:00:01"))
frmStatus.Hide
Unload frmStatus 'hide and unload the form
End Sub
The O'Reilly solution certainly is an involved solution, but it seems the "prettiest" and would probably be very user-friendly. The SO solution appears to be much easier to implement though.