Capturing the IE windows using For Each window shell application - vba

I need to capture the windows and need to navigate further, I am able to capture using the below code,
With objIE
Application.Wait (Now + TimeValue("00:00:05"))
Set TBL = .document.getElementById("payersitecredential-table")
Set PRV = TBL.getElementsByTagName("A"): PRV.Item(1).Click
'once the above code runs, it opens up an another window and i need to set that window as object.
Application.Wait (Now + TimeValue("00:00:20"))
End With
For Each WINDW In CreateObject("Shell.Application").Windows
If WINDW.Name = "Internet Explorer" Then
If InStr(WINDW.LocationURL, "newmmis") <> 0 Then
Set objIE1 = WINDW
Exit For
ElseIf InStr(WINDW.LocationURL, "https://www.example.com") <> 0 Then
Set ClsWindw = WINDW
ClsWindw.Quit
GoTo ThEnD
End If
End If
Next
With objIE1
Do While .Busy Or .readyState <> 4 'this is the place i get error as object required
DoEvents
Loop
Application.Wait (Now + TimeValue("00:00:05"))
.document.getElementById("InquireStatus").Click
End With
i have kept a wait time of 60 seconds for the URL to load, but sometimes the URL takes much time to load, at that time it is unable to set the object, could you guys let me figure out this and give me a solution.

Please see this in support of my comment
Sub ex()
Dim ie As SHDocVw.InternetExplorer
Dim wins As New SHDocVw.ShellWindows
For Each ie In wins
Debug.Print ie.Document.URL, ie.ReadyState, ie.Busy
Next ie
End Sub
EDIT
I would utilise the above, like so, this will find the IE based on URL and wait until it's ready and return, so use set IE=GetMeReadyIE("http://stackoverflow.com/questions/tagged/vba") for example.
Function GetMeReadyIE(strURL As String) As SHDocVw.InternetExplorer
Dim ie As SHDocVw.InternetExplorer
Dim wins As New SHDocVw.ShellWindows
For Each ie In wins
If ie.Document.URL = strURL Then
While ie.ReadyState <> READYSTATE_COMPLETE Or ie.Busy
DoEvents
Wend
Set GetMeReadyIE = ie
Exit For
End If
Next ie
End Function

Related

How do I get around breaking InternetExplorer Object with Application.SendKeys

I thought I was well on my way to success. What I'm attempting to do is Load a URL in IE, input some data, then run a report.
To accomplish this, I've created an InternetExplorer object, used that object to turn on visibility, and navigate to my URL.
Upon getting to the page, I have to supply some data to let the report generator do what it needs to do, then press enter. Once I'm to this point I need to do some navigation to different URLs until I arrive at the report page. To accomplish this, I'm attempting to return to using my InternetExplore object (IE) to navigate, but any time I use IE.anything the 462 error pops.
My question is two fold:
The object was good to begin with, I have to assume it was the use of Application.Send or Application.Wait that has somehow broke my object, why?
What did I do wrong?
Suggestions on how to resolve this?
Dim text As String
Dim IE
Set IE = CreateObject("InternetExplorer.Application")
'
IE.Visible = True
IE.Navigate "http://~~~~~~~~~.net/reports/views/result/reportResult.faces"
'
text = "somedata"
.
Application.Wait (Now + TimeValue("00:00:02"))
Application.SendKeys (text), True
'
Application.Wait (Now + TimeValue("00:00:02"))
Application.SendKeys vbCrLf, True
'
Application.Wait (Now + TimeValue("00:00:02"))
IE.Navigate "http://~~~~~~~~~.net/reports/views/myMrs/myFavorites.faces"
The end product was completely different than where I was headed. Thanks to those who provided input, especially Sorceri who turned me on to focusing on the elements.
Below is the finished code segment (I have more things I do after this but this gets me where I needed to go).
Private Sub OpenReport()
Dim text As String
Dim x As Integer
Dim IE
Set IE = New InternetExplorerMedium
text = "somecode"
'Load link
IE.Visible = True
IE.Navigate "http://~~~~~~~~~/reports/views/result/reportResult.faces"
'Wait for page to load
Do While IE.Busy Or IE.ReadyState <> 4
DoEvents
Loop
'fill in the pcode
IE.Document.getelementbyid("code").Value = text
'Click Submit
IE.Document.getElementsByClassName("btn btn-lg btn-primary btn-block")(0).Click
'Wait for page to load
Do While IE.Busy Or IE.ReadyState <> 4
DoEvents
Loop
'Click on Favorites
IE.Document.getElementsByClassName("myMRSFavoritesLink")(0).Click
'Wait for page to load
Do While IE.Busy Or IE.ReadyState <> 4
DoEvents
Loop
'Click on report
IE.Document.getElementsByName("myFavoritesForm:treeTable_tableId:1:infoButton101644806j_id__v_19")(0).Click
'Wait for page to load
Do While IE.Busy Or IE.ReadyState <> 4
DoEvents
Loop
Click on execute report
IE.Document.getElementsByName("setParametersForm:startReportButton")(0).Click
End Sub

VBA Macro for Internet Explorer - code run well on debugging 1 by 1 command but didn't work if i run the whole program

I'm new with VBA Macro using for automate the internet explorer.
I've used it for creating bot to follow other online shopping follower (e-commerce).
Actually the code run well if I use debug 1 by 1 command, and it worked (can do the follow thing).
But if I run the whole program, the code just operate maybe several command & stopped (but it didn't error).
I used it for e-commerce (sho.ee).
The step is:
open IE for other shop's followers
grab all the link
open the new link in new IE
follow them, close the new IE
and looping.
If I run step by step it worked.
Hope you guys could help me which wrong with the code.
Here's the code => i changed the name of the shop by xxx
Sub Followers()
Dim objIE As InternetExplorer
Dim ieAnchors As Object
Dim Anchor As Object
Set objIE = New InternetExplorer
objIE.Visible = True
objIE.Navigate "https://shopee.co.id/shop/xxx/followers/"
Do While objIE.Busy = True Or objIE.ReadyState <> 4: DoEvents: Loop
Set ieAnchors = objIE.Document.getElementsByClassName("shop-href")
For Each Anchor In ieAnchors
result = Anchor
If result <> result_prev Then
Dim objIE_1 As InternetExplorer
Dim ieBtn As Object
Dim Btn As Object
Set objIE_1 = New InternetExplorer
objIE_1.Visible = True
objIE_1.Navigate Anchor
Do While objIE_1.Busy = True Or objIE_1.ReadyState <> 4: DoEvents: Loop
Set ieBtn = objIE_1.Document.getElementsByClassName("shopee-button-outline shopee-button-outline--complement shopee-button-outline--fill ")
For Each Btn In ieBtn
Btn.Click
Next Btn
objIE_1.Quit
result_prev = Anchor
End If
Next Anchor
End Sub
Sometimes pages load in parts, registering as complete before all elements have loaded. In these cases I use application.Wait to force the program to wait a set amount of time for page loads:
'wait five seconds
Application.Wait (Now + TimeValue("0:00:05"))
If it is a simple page, I will have a Do loop a check for ReadyState to avoid slowing the program down unnecessarily:
'wait for page to load
Do Until ie.ReadyState = READYSTATE_COMPLETE or ie.ReadyState = 4
DoEvents
Loop
yes it worked. by adding Application.Wait (Now + TimeValue("0:00:05"))
Sub Followers()
Dim objIE As InternetExplorer
Dim ieAnchors As Object
Dim Anchor As Object
Set objIE = New InternetExplorer
objIE.Visible = True
objIE.Navigate "https://shopee.co.id/shop/xxx/followers/"
Do While objIE.Busy = True Or objIE.ReadyState <> 4: DoEvents: Loop
Application.Wait (Now + TimeValue("0:00:02"))
Set ieAnchors = objIE.Document.getElementsByClassName("shop-href")
For Each Anchor In ieAnchors
result = Anchor
If result <> result_prev Then
Dim objIE_1 As InternetExplorer
Dim ieBtn As Object
Dim Btn As Object
Application.Wait (Now + TimeValue("0:00:02"))
Set objIE_1 = New InternetExplorer
objIE_1.Visible = True
objIE_1.Navigate Anchor
Do While objIE_1.Busy = True Or objIE_1.ReadyState <> 4: DoEvents: Loop
Set ieBtn = objIE_1.Document.getElementsByClassName("shopee-button-outline shopee-button-outline--complement shopee-button-outline--fill ")
For Each Btn In ieBtn
Btn.Click
Next Btn
objIE_1.Quit
result_prev = Anchor
End If
Next Anchor
End Sub

Unable to fill in some date inputs to perform a customized search

I'm trying to create a script in vba to select dates according to my preferable input date, as in 03/11/2019 and output date, as in 05/11/2019 for the two fields check-in and chek-out. the macro that I've written so far can click on those fields but can't fill in the inputs with the aforesaid dates.
Website address
I've tried:
Sub FillInTheForm()
Dim IE As New InternetExplorer, HTML As HTMLDocument
Dim post As Object, elem As Object, guest As Object
Dim findbtn As Object, URL$
URL = "https://www.discoverqatar.qa/"
With IE
.Visible = True
.navigate URL
While .Busy = True Or .readyState < 4: DoEvents: Wend
Application.Wait Now + TimeValue("00:00:05")
Set post = .document.querySelector("[class='rsp_s_checkindate_input'] > #lpPannel_txtFromDate")
post.Focus
post.Click
Application.Wait Now + TimeValue("00:00:05")
Set elem = .document.querySelector("[class='rsp_s_checkoutdate_input'] > #lpPannel_txtToDate")
elem.Focus
elem.Click
Application.Wait Now + TimeValue("00:00:05")
Set guest = .document.querySelector("#lblPaxInfo")
guest.Focus
guest.Click
Application.Wait Now + TimeValue("00:00:05")
Set findbtn = .document.querySelector("input#btnSearch")
findbtn.Focus
findbtn.Click
End With
' IE.Quit
End Sub
Some intentional delays are there within the script which I can kick out later defining any timed loop.
How can I fill in the dates in those boxes to perform a customized search?
Just set the value attributes
Option Explicit
Public Sub SetDates()
Dim ie As InternetExplorer
Set ie = New InternetExplorer
With ie
.Visible = True
.Navigate2 "https://www.discoverqatar.qa/"
While .Busy Or .readyState <> 4: DoEvents: Wend
With .document
.querySelector("#lpPannel_txtFromDate").Value = "03/11/2019"
.querySelector("#lpPannel_txtToDate").Value = "05/11/2019"
.querySelector("#btnSearch").Click
Stop
End With
End With
End Sub

Select option from dropdown menu with VBA

I am trying to scrape data from this website: https://portal.emsa.europa.eu/widget/web/thetis/inspections/-/publicSiteInspection_WAR_portletpublic
I need to input three values, the "Period" dates (which is ok) and select the "Flag" (in this case Portugal). This last one has proven to be a huge difficulty since typing is not an option.
Private Sub Run()
Dim objIE As Object
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
objIE.navigate ("https://portal.emsa.europa.eu/widget/web/thetis/inspections/-/publicSiteInspection_WAR_portletpublic")
Application.Wait (Now + TimeValue("0:00:13"))
objIE.document.getElementById("tdate-1028-inputEl").Value = "01/01/2019"
objIE.document.getElementById("tdate-1029-inputEl").Value = "01/09/2019"
objIE.document.getElementById("checkcombo-1014-trigger-picker").Click
If objIE.document.getElementByClass("x-boundlist-item") = """Portugal""" Then objIE.document.getElementBy("x-combo-checker").Click
End Sub
You want a timed loop waiting for presence of element to click on as well as to click parent first. Sadly, I can't see an easy way to knock out the current explicit wait time used at beginning for page load to complete
Option Explicit
Public Sub SelectFlag()
Dim ie As SHDocVw.InternetExplorer, t As Date
Const MAX_WAIT_SEC As Long = 5 '<==adjust time here
Set ie = New SHDocVw.InternetExplorer
With ie
.Visible = True
.Navigate2 "https://portal.emsa.europa.eu/widget/web/thetis/inspections/-/publicSiteInspection_WAR_portletpublic"
While .Busy Or .readyState <> 4: DoEvents: Wend
With .document
Application.Wait Now + TimeSerial(0, 0, 5)
.querySelector("#checkcombo-1014-trigger-picker").Click
Dim ele As Object
t = Timer
Do
On Error Resume Next
Set ele = .querySelector("[data-recordid='246']")
On Error GoTo 0
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop While ele Is Nothing
If Not ele Is Nothing Then ele.Click
End With
Stop '<==Delete me later
'.quit
End With
End Sub
I have meanwhile tried another option but still without success:
Private Sub Run()
Dim objIE As Object
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
objIE.navigate ("https://portal.emsa.europa.eu/widget/web/thetis/inspections/-/publicSiteInspection_WAR_portletpublic")
Application.Wait (Now + TimeValue("0:00:13"))
Dim iL As IHTMLElement
Dim e As IHTMLElementCollection
Set e = appIE.document.getElementById("checkcombo-1014-picker").getElementsByClass("x-boundlist-item")
For Each iL In e
If iL.innerText = "Portugal" Then
iL.Click
End If
Next iL
End Sub

VBA Object Required Error Trying To Get InnerText

I am trying to create a code that will go to a website, put in data, submit it, and then return the answer to a cell in excel. When I step through it, it works fine, but when I just try to run it, I get run-time error 424; Object Required.
I tried looking for a good answer, but I am just not grasping on how to quite fix this. Where is my issue? How do I correct it?
Sub Distance()
Dim IE As Object
' Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")
' Make visible
IE.Visible = True
' Go to site
IE.Navigate "http://www.distance-cities.com/"
' Wait while IE loading...
Do Until IE.READYSTATE = 4
DoEvents
Loop
IE.Document.getelementbyId("from").Value = "Stillwater, OK"
IE.Document.getelementbyId("to").Value = "Hollis, OK"
IE.Document.forms(0).submit
Do Until IE.READYSTATE = 4
DoEvents
Loop
'*Below is where I get my error
Sheet1.Range("E5").Value = IE.Document.getelementbyId("routemi").InnerText
IE.Quit
End Sub
I apologize if this is a bit messy.
Thanks for you help!
Something like this (untested):
Dim el as object
'...
Set el = WaitForElement(IE.Document, "routemi", 1)
If Not el is Nothing Then
Sheet1.Range("E5").Value = el.innerText
Else
Msgbox "Element 'routemi' not found!"
Exit Sub
End if
Utility function to get an element by id, waiting until it appears:
Function WaitForElement(doc As Object, id As String, maxWaitSec As Double) As Object
Dim rv As Object, t
t = Timer
Do
Set rv = doc.getElementById(id)
DoEvents
Loop While rv Is Nothing And (Timer - t) < maxWaitSec
Set WaitForElement = rv
End Function
You need to leave proper waits at each point (after .Navigate2 and .Click) to allow for page loading. I use CSS selectors to target ids as modern browsers are optimized for CSS. Also, I updated method for page navigation to .Navigate2.
Option Explicit
Public Sub Distance()
Dim ie As New InternetExplorer
With ie
.Visible = True
.Navigate2 "http://www.distance-cities.com/"
While .Busy Or .readyState < 4: DoEvents: Wend
With .document
.querySelector("#from").Value = "Stillwater, OK"
.querySelector("#to").Value = "Hollis, OK"
.querySelector("[type=submit]").Click
End With
While .Busy Or .readyState < 4: DoEvents: Wend
Debug.Print .document.querySelector("#routemi").innerText
.Quit
End With
End Sub