VBA IE Automation - vba

I am trying to automate a process where I must query a website: http://rgl.faa.gov/Regulatory_and_Guidance_Library/rgAD.nsf/MainFrame?OpenFrameset
There is a input text field <input name="query size="20"/>" that I want to populate but I am struggling to do so. Currently I am testing my code to see if I can even reference the tag.
Sub fill()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.navigate "http://rgl.faa.gov/Regulatory_and_Guidance_Library/rgAD.nsf/MainFrame?OpenFrameset"
IE.Visible = True
While IE.busy
DoEvents
Wend
For Each it In IE.Document.getElementsByTagName("input")
If it.Name = "newquery" Then
MsgBox ("yup")
End If
Next
End Sub
I think my issue is that the input field is in 2 framesets and a frame...
Any ideas if this is even possible to do?

Unless you know exactly which frame the input is in, this is a classical situation for a recursive search:
Sub fill()
Dim IE As Object, elem As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.navigate "http://rgl.faa.gov/Regulatory_and_Guidance_Library/rgAD.nsf/MainFrame?OpenFrameset"
IE.Visible = True
While IE.Busy: DoEvents: Wend
While IE.document.readyState <> "complete": DoEvents: Wend
Set elem = FindInputByName(IE.document, "newquery")
If Not elem Is Nothing Then
elem.Value = "It works!"
End If
End Sub
Function FindInputByName(document As Object, name As String) As Object
Dim i As Integer, subdocument As Object, elem As Variant
Set FindInputByName = Nothing
For i = 0 To document.frames.Length - 1
Set subdocument = document.frames.Item(i).document
Set FindInputByName = FindInputByName(subdocument, name)
If Not FindInputByName Is Nothing Then Exit Function
Next i
For Each elem In document.getElementsByTagName("INPUT")
If elem.name = name Then
Set FindInputByName = elem
Exit Function
End If
Next elem
End Function

You should try to install and use opentwebst Library : http://codecentrix.com/download.html
Don't forget to add opentwebst in project references.
It took me less time to generate the code below then writing this post :
Sub OpenTwebstMacro
Dim core As ICore
Set core = New OpenTwebstLib.core
Dim browser As IBrowser
Set browser = core.StartBrowser("http://rgl.faa.gov/Regulatory_and_Guidance_Library/rgAD.nsf/MainFrame?OpenFrameset")
Call browser.FindElement("input text", "name=newquery").InputText("YOUR QUERY")
Call browser.FindElement("input button", "uiname=Go").Click
End Sub

Related

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

Modifying to Google Chrome

I have a code that works fine. The thing is it opens Internet Explorer for results. I want the results in Google Chrome. Modification would be helpful.
Option Explicit
Sub GetResults(r As Range)
Dim IE As Object
Dim frm As Object
Dim srch As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "http://www.google.com"
Do While IE.Busy: DoEvents: Loop
Do While IE.ReadyState <> 4: DoEvents: Loop
Set frm = IE.Document.forms("f")
Set srch = frm.Document.all("q")
srch.Value = r.Value
frm.submit
End Sub
This would be something similar written for selenium basic vba wrapper. After installing selenium you need to go tools > references > add reference to selenium type library.
This is literally written to follow what you have written. You may wish to consider targeting by id not name, also, whether you want a function to return something from the results specifically.
Option Explicit
Public Sub test()
Dim r As Range
Set r = [A1] '<== you really want a test that a single cell is passed or you will end up with an array later
GetResults r
End Sub
Public Sub GetResults(ByVal r As Range)
Dim d As WebDriver, frm As Object, srch As Object
Set d = New ChromeDriver
Const URL = "http://www.google.com"
With d
.Start "Chrome"
.get URL
Set frm = .FindElementByName("f")
Set srch = frm.FindElementByName("q")
srch.SendKeys r.Value
frm.submit
Stop '<=Delete me later
.Quit
End With
End Sub

Unable to fetch some content using createDocumentFromUrl in vba

I've written some code in vba to get the movie names from a torrent website using .createDocumentFromUrl() method. As I've never worked with this method and haven't found any remarkable information either on it to successfully go with, I get stuck. I have tried to create a script, though.
Here is my try:
Sub Fromurl_Method()
Const URL As String = "https://yts.am/browse-movies"
Dim hStart As HTMLDocument, hdoc As HTMLDocument
Set hStart = New HTMLDocument
Set hdoc = hStart.createDocumentFromUrl(URL, vbNullString)
Do While hdoc.readyState = "loading" Or hdoc.readyState = "interactive": DoEvents: Loop
Debug.Print hdoc.DocumentElement.innerHTML
End Sub
When I execute the above script, it fetches some html elements which are not from that website. I took a closer look into the elements I have parsed and noticed this line on the top This content cannot be displayed in a frame. It is behaving the same way with most of the sites. How can I make it successful? Thanks in advance.
Once again, my intention is to parse all the movie names from that site using .createDocumentFromUrl().
Sub Get_Info()
Dim Elems, e As Variant
Const READYSTATE_COMPLETE& = 4&
Dim ie As Object
Set ie = Nothing
DoEvents
Set ie = CreateObject("InternetExplorer.Application")
DoEvents
With ie
.Visible = false
.Navigate "https://yts.am/browse-movies"
While Not .readyState = READYSTATE_COMPLETE
DoEvents
Wend
End With
Dim i As Double
With ie.Document
Set Elems = .getElementsByTagName("a")
DoEvents
i = 2
For Each e In Elems
If e.getAttribute("class") = "browse-movie-title" Then
Range("A" & i).Value = e.innerText
i = i + 1
End If
Next e
End With
Set Elems = Nothing
Set e = Nothing
ie.Quit
Set ie = Nothing
End Sub
The code above will give you a list of all movies. Just modify the code to adapt it to your needs of getting the first one if you only need the first one.

Error received when downloading a file from web when only submit button is present

I need to download a file from web, but only a submit button is present.
There is no url for reaching the file directly.
I tried to catch the button by its id, but VBA drops run-time error '424' (Object required).
Here is the code:
Sub keler_submit()
Application.ScreenUpdating = False
Set IE = CreateObject("InternetExplorer.Application")
IE.navigate "https://www.keler.hu/T%C3%A1rsas%C3%A1gi%20esem%C3%A9nyek/"
While IE.Busy
DoEvents
Wend
Set doc = IE.document
gomb = doc.getElementById("ctl00_wpm_UserControlPortlet1682286671_ctl00_wpm_UserControlPortlet1682286671_userControlPortlet_DownloadButton1")
gomb.submit
Set IE = Nothing
Application.ScreenUpdating = True
End Sub
Thank you in advance
These lines are incorrect:
gomb = doc.getElementById("ctl00_wpm_UserControlPortlet1682286671_ctl00_wpm_UserControlPortlet1682286671_userControlPortlet_DownloadButton1")
gomb.submit
doc.getElementById returns an object type so you need to use Set to assign it to a variable. The element you are trying to access should then be clicked instead of submitted. There's a high probability that IE will display a "Do you wish to open or save this file" dialog so start by making the IE object visible to show this:
IE.visible = True
Set gomb = doc.getElementById("ctl00_wpm_UserControlPortlet1682286671_ctl00_wpm_UserControlPortlet1682286671_userControlPortlet_DownloadButton1")
gomb.click
You need a loop in there as well to ensure page has loaded. The following works:
Option Explicit
Public Sub GetInfo()
Dim IE As New InternetExplorer
With IE
.Visible = True
.navigate "https://www.keler.hu/T%C3%A1rsas%C3%A1gi%20esem%C3%A9nyek/"
While .Busy Or .readyState < 4: DoEvents: Wend
Do
Dim b As Object
On Error Resume Next
Set b = .document.getElementById("ctl00_wpm_UserControlPortlet1682286671_ctl00_wpm_UserControlPortlet1682286671_userControlPortlet_DownloadButton1")
On Error GoTo 0
Loop While b Is Nothing
b.Click
'Handle save button
'Quit '<== Remember to quit application
End With
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