I'm having trouble getting to the span tag and grabbing the inner text for "1-Day Total Return".
Here is the webpage:
http://www.morningstar.com/funds/XNAS/DODFX/quote.html
Here is my code
Sub Macro1()
'
link = "http://www.morningstar.com/funds/XNAS/DODFX/quote.html"
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.navigate link
Do
DoEvents
Loop Until ie.readyState = READYSTATE_COMPLETE
Dim doc As HTMLDocument
Set doc = ie.document
While ie.readyState <> 4
Wend
On Error Resume Next
Application.Wait (Now + TimeValue("00:00:02"))
range("B5").Offset(0, 0).Value = doc.getElementById("msqt_summary")(0).getElementsByClassName("gr_colm_a2b")(0).getElementsByTagName("span")(0).innerText
End With
ie.Quit
Application.EnableEvents = True
'
End Sub
This is the way you can get your data. The data is indeed within an iframe.
Sub Web_Data()
Dim IE As New InternetExplorer, html As HTMLDocument
Dim elem As Object, post As Object
With IE
.Visible = False
.navigate "http://www.morningstar.com/funds/XNAS/DODFX/quote.html"
Do While .readyState <> READYSTATE_COMPLETE: Loop
Set elem = .document.getElementById("quote_quicktake").getElementsByTagName("iframe")(0)
.navigate elem.src
While .readyState < 4: DoEvents: Wend
Set html = .document
End With
Set post = html.getElementsByClassName("gr_text_bigprice")(1).getElementsByTagName("span")(1)
MsgBox post.innerText
IE.Quit
End Sub
Output:
-0.67
Related
I am trying to get all the buttons using queryselector and select the particular button by looping through and finding innerHTML.
After finding the particular button, when click event is passed, nothing happens.
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "https://www.spirit.com/"
Do Until IE.readyState = 4: Application.Cursor = xlDefault: DoEvents: Loop
Application.Wait (Now + TimeValue("00:00:03"))
IE.document.querySelector("label[for='radio-oneWay']").Click
Application.Wait (Now + TimeValue("00:00:03"))
IE.document.querySelector("input[id='flight-OriginStationCode']").Click
Set elems = IE.document.getElementsByTagName("button")
For Each elem In elems
If (elem.innerHTML) = " Aguadilla, Puerto Rico (BQN) " Then
elem.Click
Exit For
End If
Next elem
The two airport boxes can be assigned by simulating input using SendKeys then the click event will be triggered. The date-input and other textbox will be set separately. Here is the code which implements this function:
Private Sub CommandButton1_Click()
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "https://www.spirit.com/"
Do Until IE.readyState = 4: Application.Cursor = xlDefault: DoEvents: Loop
Application.Wait (Now + TimeValue("00:00:03"))
IE.document.querySelector("label[for='radio-oneWay']").Click
Application.Wait (Now + TimeValue("00:00:03"))
Set elems = IE.document.getElementsByTagName("button")
Set txt1 = IE.document.getElementsByName("originStationCode")(0)
txt1.Focus
SendKeys ("BQN")
Application.Wait (Now + TimeValue("00:00:01"))
Set txt2 = IE.document.querySelector("input[id='flight-DestinationStationCode']")
txt2.Focus
SendKeys ("BDL")
Application.Wait (Now + TimeValue("00:00:01"))
Application.Wait (Now + TimeValue("00:00:01"))
IE.document.querySelector("input[id='flight-Date']").Value = "2020/10/09-2020/10/19"
IE.document.querySelector("input[id='promoCode']").Value = "xx"
IE.document.querySelector("button[type='submit']").Click
End Sub
Result:
So I have been trying to scrape info from a site using the code below but am having a tough time with the part I noted. Is there an easier way to get the results I want rather than just repeating the same code over and over? You never know how many results you will get so I cannot use that info.
Dim objIE As InternetExplorer
Dim y As Integer
Dim result As String
Set objIE = New InternetExplorer
objIE.Visible = True
objIE.navigate "https://www.searchiqs.com/nyalb/Login.aspx"
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
objIE.document.getElementById("btnGuestLogin").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
objIE.document.getElementById("ContentPlaceHolder1_txtFromDate").Value = "07/01/2017"
objIE.document.getElementById("ContentPlaceHolder1_txtThruDate").Value = "07/19/2017"
objIE.document.getElementById("ContentPlaceHolder1_cboDocGroup").Value = "DBA"
objIE.document.getElementById("ContentPlaceHolder1_cmdSearch").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
y = 1
' brings up a table of results. I need to click on the view button and get the info from that page
objIE.document.getElementById("ContentPlaceHolder1_grdResults_btnView_0").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
' element ID's are hidden for those looking to help
result = Trim(objIE.document.getElementById("ContentPlaceHolder1_lblDetails2").innerText)
Sheets("Sheet1").Range("C" & y).Value = result
y = y + 1
' I would love to direct link to the next serch result here but the link does not change between pages so I click the next button
objIE.document.getElementById("ContentPlaceHolder1_btnNext").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
result = Trim(objIE.document.getElementById("ContentPlaceHolder1_lblDetails2").innerText)
Sheets("Sheet1").Range("C" & y).Value = result
y = y + 1
' and I click the next button again
objIE.document.getElementById("ContentPlaceHolder1_btnNext").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
result = Trim(objIE.document.getElementById("ContentPlaceHolder1_lblDetails2").innerText)
Sheets("Sheet1").Range("C" & y).Value = result
y = y + 1
'AND AGAIN
objIE.document.getElementById("ContentPlaceHolder1_btnNext").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
result = Trim(objIE.document.getElementById("ContentPlaceHolder1_lblDetails2").innerText)
Sheets("Sheet1").Range("C" & y).Value = result
y = y + 1
' You get the idea
objIE.document.getElementById("ContentPlaceHolder1_btnNext").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
result = Trim(objIE.document.getElementById("ContentPlaceHolder1_lblDetails2").innerText)
Sheets("Sheet1").Range("C" & y).Value = result
' I basically repeat that process til I cant press CTRL V anymore. Is there a loop I can use to tighten this up?
Let me know. You guys have been a huge help in the past. Also would it be beneficial to use the XML method as my readystate loops have been giving me issues? Thanks in advance.
Yep, a For loop for the required number of iterations if it's a static set of pages. I believe we can make it simpler.
For y = 1 to 5
result =trim(objIE.document.getElementById("ContentPlaceHolder1_lblDetails2").innerText)
Sheets("Sheet1").Range("C" & y).Value = result
objIE.document.getElementById("ContentPlaceHolder1_btnNext").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
next y
'or if you want it to keep going, something like this
Do until objIE.document.getElementById("ContentPlaceHolder1_btnNext") is nothing
result =trim(objIE.document.getElementById("ContentPlaceHolder1_lblDetails2").innerText)
Sheets("Sheet1").Range("C" & y).Value = result
objIE.document.getElementById("ContentPlaceHolder1_btnNext").Click
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
loop
Not able to fetch data
Sub differntIEsize()
Dim ie As New SHDocVw.InternetExplorer
Dim doc As HTMLDocument
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.navigate "https://en.wikipedia.org/wiki/Main_Page"
Do While .Busy
DoEvents
Loop
Do While .readyState <> 4
DoEvents
Loop
Set searchtxt = .document.getElementById("searchInput")
searchtxt.Value = "Earth"
.document.forms(0).submit
Do While .Busy
DoEvents
Loop
Do While .readyState <> 4
DoEvents
Loop
'IE.navigate "javascript:document.getElementById('.document.forms(0).submit').click();"
ThisWorkbook.Sheets(1).Range("A2") = "hgvgjjlj"
Set doc = .document
ThisWorkbook.Sheets(1).Range("A1").Value = doc.getElementById("toctitle").innerText
.Quit
End With
End Sub
I have some code that pulls data from a website, which works correctly, my issue is that you have to sign in to the website in order to get to the data I need. Everything works great until I close and reopen the sheet. If I don't do a manual pull before running the code it pulls no data from the site. Is there a way to get it to sign in for me?
Sub Search_People()
Dim Name_Of_Person As String
Dim URL As String
Dim Dashboard_Sheet As Worksheet
Set Dashboard_Sheet = ThisWorkbook.Sheets("Dashboard")
Dim Data_Sheet As Worksheet
Set Data_Sheet = ThisWorkbook.Sheets("Data")
Dim Data_Dump As Worksheet
Set Data_Dump = ThisWorkbook.Sheets("DataDump")
Dim X As Integer
Dim Y As Integer
Dim Last_Row As Long
Dim Email_Output As Range
Set Email_Output = Data_Dump.Range("A:XFD")
Dim Cell As Range
Application.EnableCancelKey = xlDisabled
Last_Row = Data_Sheet.Range("B3")
For X = 1 To Last_Row
On Error Resume Next
Name_Of_Person = Data_Sheet.Cells(2 + X, 8)
Application.StatusBar = " Pulling Data for... " & Name_Of_Person
URL = "URL;" & "https://fake.com/people/"
URL = URL & Name_Of_Person & "%40fake.com"
With Data_Dump.QueryTables.Add(Connection:= _
URL, _
Destination:=Data_Dump.Range("A1"))
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlEntirePage
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
Set Cell = Email_Output.Find("Email")
Worksheets("Data").Cells(2 + X, 9).Value = Cell
Data_Dump.Range("A:A").EntireColumn.Delete
Next X
Application.StatusBar = False
End Sub
The answer in the above link works perfectly.
Sub test()
' open IE, navigate to the desired page and loop until fully loaded
Set ie = CreateObject("InternetExplorer.Application")
my_url = ""
With ie
.Visible = True
.Navigate my_url
.Top = 50
.Left = 530
.Height = 400
.Width = 400
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
End With
' Input the userid and password
ie.Document.getElementById("uid").Value = ""
ie.Document.getElementById("password").Value = ""
' Click the "Search" button
ie.Document.getElementById("enter").Click
Do Until Not ie.Busy And ie.readyState = 4
DoEvents
Loop
End Sub
Please try this...
Dim HTMLDoc As HTMLDocument
Dim oBrowser As InternetExplorer
Sub Login_2_Website()
Dim oHTML_Element As IHTMLElement
Dim sURL As String
On Error GoTo Err_Clear
sURL = "https://www.google.com/accounts/Login"
Set oBrowser = New InternetExplorer
oBrowser.Silent = True
oBrowser.timeout = 60
oBrowser.navigate sURL
oBrowser.Visible = True
Do
' Wait till the Browser is loaded
Loop Until oBrowser.readyState = READYSTATE_COMPLETE
Set HTMLDoc = oBrowser.Document
HTMLDoc.all.Email.Value = "sample#vbadud.com"
HTMLDoc.all.passwd.Value = "*****"
For Each oHTML_Element In HTMLDoc.getElementsByTagName("input")
If oHTML_Element.Type = "submit" Then oHTML_Element.Click: Exit For
Next
' oBrowser.Refresh ' Refresh If Needed
Err_Clear:
If Err <> 0 Then
Debug.Assert Err = 0
Err.Clear
Resume Next
End If
End Sub
Also, take a look at this link.
http://vbadud.blogspot.com/2009/08/how-to-login-to-website-using-vba.html
I have the below code that pulls a table from two pages that require a login. The code opens IE, goes to the login page, puts in the credentials, then pulls the 2 tables.
However, if IE is already logged in with a user, it directly takes you to this page (and thus the code errors out because there is no login fields):
https://www.example.com/taskprocessing/manage.jsp
I need to add an IF statement that if it lands on this page, to click on this link to log out, then proceed with logging in with the credentials:
https://www.example.com/taskprocessing/logout.jsp
Sub GetTable()
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.Navigate "https://www.example.com/taskprocessing/login.jsp"
Do Until .ReadyState = 4
DoEvents
Loop
.Document.all.Item("Username").Value = "username123"
.Document.all.Item("Password").Value = "password123"
.Document.forms(0).submit
End With
With ActiveSheet.QueryTables.Add(Connection:= _
"URL;https://www.example.com/taskprocessing/report_pending_tasks.jsp", Destination:=Range("J1"))
.WebSelectionType = xlAllTables
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
With ActiveSheet.QueryTables.Add(Connection:= _
"URL;https://www.example.com/taskprocessing/report_task_processing_stats.jsp", Destination:=Range("A1"))
.WebSelectionType = xlSpecifiedTables
.WebFormatting = xlWebFormattingNone
.WebTables = """user"""
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
End With
End Sub
You can just skip the login process if not needed. To do this, you might re-structure your top-code as follows:
Set ie = CreateObject("InternetExplorer.Application")
With ie
.Visible = True
.Navigate "https://www.example.com/taskprocessing/login.jsp"
Do Until .ReadyState = 4
DoEvents
Loop
On Error Resume Next 'this will help to understand if there was an error when trying retrieving the UserName field
Set userField = .Document.getElementById("Username")
If Err.Number = 0 Then 'if there was no error when trying to search for the username...
.Document.all.Item("Username").Value = "username123"
.Document.all.Item("Password").Value = "password123"
.Document.forms(0).submit
End If
On Error GoTo 0 'turn-off the error handling once again
End With
The lines I added are:
On Error Resume Next
...to avoid the code breaking if there's an error when looking for a non-existing element;
Set userField = .Document.getElementById("Username")
...to see if the page is logged-in or logged-out. If it's logged-out, there will be no error while doing this. If it is not, then this will cause a "object does not exist error".
If Err.Number = 0 Then
...so if there was no error while doing this, we proceed with the login... otherwise we just go and keep on doing what we were doing.
On Error GoTo 0
...finally, we turn off the error handling so if there's any other error in the page you will keep on being informed regularly.
Thanks! I needed it to log out, so I added an Else statement.
On Error Resume Next 'this will help to understand if there was an error when trying retrieving the UserName field
Set userField = .Document.getElementById("Username")
If Err.Number = 0 Then 'if there was no error when trying to search for the username...
.Document.all.Item("Username").Value = "username123"
.Document.all.Item("Password").Value = "password123"
.Document.forms(0).submit
Else
.Navigate "https://www.example.com/taskprocessing/logout.jsp"
Do While ie.Busy: DoEvents: Loop
Do Until .ReadyState = 4
DoEvents
Loop
.Document.all.Item("Username").Value = "username123"
.Document.all.Item("Password").Value = "password123"
.Document.forms(0).submit
End If
On Error GoTo 0 'turn-off the error handling once again