Search on website conditional of changing different cells - html

I am currently trying to write a code in VBA, the purpose of this code is in general:
Type input into a cell "A" in a defined range.
Left from this particular cell (within the range) i want different information from a website-search to be printed next to the input-cell "A".
More specifically I want to write a code, where I can type in specific stock tickers in a column (ie. "IBM"), and when I do this, a procedure begins, which goes to finance.yahoo.com, collects different information about this specifik stock (ie. "International Business Machines"), and prints this information "to the right" of the cell where i typed the stock ticker in the first place.
The goal is to be able to type in 20-30 stock tickers, and make it retrieve the information for every ticker and print it to the right of those stock tickers.
I have already figured out how to type in one ticker in a specific cell, and make it retrieve the desired data from the website, and then print it into specific cells "to the right" of the input-cell.
My challenge now, is to be able to do this for a large range of cells below the first input-cell.
My code as of now:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = Range("Sheet1!$A$2").Row And _
Target.Column = Range("Sheet1!$A$2").Column Then
Dim IE As New InternetExplorer
IE.Visible = False
IE.navigate "http://finance.yahoo.com/q;_ylt=AiMiBWm16z_q5Ai0SlNb3jaiuYdG;_ylu=X3oDMTBxdGVyNzJxBHNlYwNVSCAzIERlc2t0b3AgU2VhcmNoIDEx;_ylg=X3oDMTBsdWsyY2FpBGxhbmcDZW4tVVMEcHQDMgR0ZXN0Aw--;_ylv=3?s=" & Range("Sheet1!$A$2").Value 'This types in the value from my input-cell into the website, so i get directed to the webpage for this particular company.
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Dim Doc As HTMLDocument
Set Doc = IE.document
Dim Name_001 As String 'Info-cell with name of the company
Dim Ticker_001 As String 'Info-cell with current price of the company
Name_001 = Trim(Doc.getElementsByClassName("title")(0).innerText)
Ticker_001 = Trim(Doc.getElementsByClassName("yfi_rt_quote_summary_rt_top sigfig_promo_1")(0).innerText)
IE.Quit
Dim Nam_001 As Variant
Dim Tic_001 As Variant
Nam_001 = Split(Name_001, "(")
Tic_001 = Split(Ticker_001, " ")
Range("Sheet1!$B$2").Value = Nam_001(0)
Range("Sheet1!$C$2").Value = Tic_001
End If
End Sub
"Sheet1!$A$2": The input-cell
"Sheet1!$B$2": First output cell for the name of the stock ticker.
"Sheet1!$C$2": Second output cell for the current price of the stock ticker.
Right now my code only works for one row, i want it to work for all the rows beneath the current input-cell:
I hope my question is clear, and that you can help me with my problem (I am not allowed to post any pictures, so I cant show you my work book, however I have tickers in column "A", name in column "B" and price in column "C").
Thanks in advance - Juhlers.

I modified your code: (1) changed sheet name; (2) Removed anchored row ($2) and replaced with 'Target.Row'; (3) Added Error Trap - sometimes get error; (4) Changed Cursor to 'Busy' since it takes a few seconds. Try The following:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim IE As New InternetExplorer
Dim Doc As HTMLDocument
Dim Name_001 As String 'Info-cell with name of the company
Dim Ticker_001 As String 'Info-cell with current price of the company
Dim Nam_001 As Variant
Dim Tic_001 As Variant
On Error GoTo Error_Trap
If Target.column <> 1 Then
Exit Sub
End If
Application.Cursor = xlWait
IE.Visible = False
IE.navigate "http://finance.yahoo.com/q;_ylt=AiMiBWm16z_q5Ai0SlNb3jaiuYdG;_ylu=X3oDMTBxdGVyNzJxBHNlYwNVSCAzIERlc2t0b3AgU2VhcmNoIDEx;_ylg=X3oDMTBsdWsyY2FpBGxhbmcDZW4tVVMEcHQDMgR0ZXN0Aw--;_ylv=3?s=" & Range("Stocks!$A" & Target.row).value 'This types in the value from my input-cell into the website, so i get directed to the webpage for this particular company.
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Set Doc = IE.document
Name_001 = Trim(Doc.getElementsByClassName("title")(0).innerText)
Ticker_001 = Trim(Doc.getElementsByClassName("yfi_rt_quote_summary_rt_top sigfig_promo_1")(0).innerText)
IE.Quit
Nam_001 = Split(Name_001, "(")
Tic_001 = Split(Ticker_001, " ")
Range("Stocks!$B" & Target.row).value = Nam_001(0)
Range("Stocks!$C" & Target.row).value = Tic_001
Application.Cursor = xlNormal
Exit Sub
Error_Trap:
Application.Cursor = xlNormal
MsgBox "Error: " & Err.Number & vbTab & Err.Description
Exit Sub
End Sub

Related

Trying to only extract a piece of innertext

Option Explicit
Sub VBAWebscraping2()
Dim IEObject As Object
Set IEObject = New InternetExplorer
IEObject.Visible = True
IEObject.navigate url:="https://streeteasy.com/building/" & Cells(2, 4).Value
Do While IEObject.Busy = True Or IEObject.readyState <> READYSTATE_COMPLETE
Application.Wait Now + TimeValue("00:00:01")
Loop
Dim IEDocument As HTMLDocument
Set IEDocument = IEObject.document
'GRAB by classname'
Dim IEElements As IHTMLElementCollection
Dim IEElement As IHTMLElement
Set IEElements = IEDocument.getElementsByClassName("details")
For Each IEElement In IEElements
If IEElement.innerText = "price" Then
Debug.Print (IEElement.innerText)
End If
Exit For
Next
'Dim lastRow As Long
'lastRow = Range("A" & Rows.count).End(xlUp).row
End Sub
It goes to the desired location, but when it's trying to extract the price it either doesn't print in the debug menu or grabs too much. Trying to figure out a more precise way to only grab the price, a lot of the tutorials mention id tags but there aren't many on the website.
This is the website I'm trying to scrape https://streeteasy.com/building/the-cambridge-500-east-85-street-new_york/15l?card=1
Also trying to retrieve number of rooms, baths, and neighborhood
Price you can use class
IEDocument.querySelector(".price").innerText
Same for rooms
IEDocument.querySelector(".first_detail_cell").innerText
Beds
IEDocument.querySelector("[class='detail_cell ']").innerText
Baths
IEDocument.querySelector("last_detail_cell").innerText
Looking at how the classes are named, your mileage with different pages will almost certainly vary if any of these items are missing or in a different order. You will then need to loop the element list returned by selecting for class .detail_cell and test the .innerText for the presence of the text "room", "bed" or "bath", and assign accordingly.

Excel VB Searching for text on a webpage and Copying information in the same Element

I am relatively new VBA.
I am trying to use this code to grab a bit of information from a website. When I do it by Element I have to search for the tag name which is tr and use a number next to it to define which one I want to use. The problem with that is it changes frequently with the position on the website. Currently the Keyword I want to search for and the information it contains is like so:
<tr>
<td class="nt">Operations</td>
<td>Windows</td>
</tr>
So if I can search by the class "Operations", and get the information "Windows", that would help. Also, I currently having an error
Next without For
If possible, is there a way I can use this to do multiple searches before I close the page? So I look for multiple specific words and input that data into different cells before moving onto the next column where it would repeat until completed at the end of the x value. I currently only have it set to x=2 To 5 but I would like to increase that to 10 or higher in the future.
The current code looks like this.
Private Sub Worksheet_Change(ByVal Target As Range)
For x = 2 To 5
If Target.Row = Cells(x, 35).Row And _
Target.Column = Cells(x, 35).Column Then
'If Target.Row = Range("ManufacturerPartNumber").Row And _
'Target.Column = Range("ManufacturerPartNumber").Column Then
Dim IE As New InternetExplorer
'IE.Visible = True
'For x = 2 To 5
'IE.navigate "" & Range("Website_1").Value
IE.navigate "" & Cells(x, 35).Value
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Dim Doc As HTMLDocument
Set Doc = IE.document
Dim sDD As String
sDD = InStr(1, IE.document.body.innerHTML, "Processor Model")
'sDD = Trim(Doc.getElementsByTagName("Processor Model")(1).innerText) 'Use this with tag like dd and number for which it appears like 0 or 1
IE.Quit
Dim aDD As Variant
aDD = Split(sDD, ",")
Cells(x, 44).Value = aDD(0)
'Range("ProcessorNumberCd").Value = aDD(0)
'Range("OSProvided").Value = aDD(0)
Next x
End If
'MsgBox "Complete"
End Sub
I think you want to grab the 'inner text'. Take a look at the example below.
Sub Scraper()
Dim item As Long
Dim priceStr As String
Dim priceTag As Object
Dim priceTable As Object
item = "10011" 'this will eventually be placed in a loop for multiple searches
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
' navigate and download the web page
objIE.Navigate "www.google.com"
Do While objIE.ReadyState <> 4 Or objIE.Busy
DoEvents
Loop
'objIE.Document.getElementsByTagName("input")(0).Value = item
'objIE.Document.getElementByID("FDI").Click
Set priceTable = objIE.Document.getElementByID("price_FGC")
Set priceTag = priceTable.getElementsByTagName("u")(3)
priceStr = priceTag.innerText
Sheet1.Range("A1").Value = priceStr
objIE.Quit
End Sub
Also, check out this link for several other ways of how to do other, similar things.
http://www.tushar-mehta.com/publish_train/xl_vba_cases/vba_web_pages_services/index.htm

Copying columns of values from Excel worksheet to an HTML table in a website

I'm hoping to copy values from an excel table into an html table. If anyone has experience doing this between Excel 2013 and Internet Explorer 11, please let me know and I can give details. Thank you
The following is a little section of the code for the website that I am trying to automate the fill-in process for:
Table and Source Code for Charge Numbers for the Site
This is showing just one part of the process (the charge numbers), which we have anywhere from 10-25 each week with their corresponding hours charged to them each day (as seen in the table matrix).
There are 7 charge numbers on each page and Charge Numbers all have name="chargeNo" and increase id names with each box downward like so:
'1) id="chargeNo0"
'2) id="chargeNo1"
'3) id="chargeNo2"
'4) id="chargeNo3"
'5) id="chargeNo4"
'6) id="chargeNo5"
'7) id="chargeNo6"
Each day of the week also has set names as follows:
Table and Source Code for Hours Charged Each Day
'Saturday: name="hrs0"
'Sunday: name="hrs1"
'Monday: name="hrs2"
'Tuesday: name="hrs3"
'Wed: name="hrs4"
'Thurs: name="hrs5"
'Fri: name="hrs6"
I'm trying to automate the process of pulling the arrays of charge times I have from Excel and inputting them into their respective textboxes.
This script will convert elements in ColumnA into an array.
Sub MakeArray()
Dim arr As Variant
With ActiveSheet
arr = WorksheetFunction.Transpose(.Range(.[A1], .Cells(Rows.Count, "A").End(xlUp)))
End With
End Sub
Sub MakeString()
Dim s As String
Const DELIMITER = ","
With ActiveSheet
s = Join(WorksheetFunction.Transpose(.Range(.[A1], .Cells(Rows.Count, "A").End(xlUp))), DELIMITER)
End With
End Sub
If you want to pass the array to an HTML TextBox, try this.
Sub CreateArrayAndPassToHTMLTextbox()
Dim ie As Object
Dim arr As Variant
Const DELIMITER = ","
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.navigate "http://home.arcor.de/peter.schleif/SearchForTDelement.html"
While ie.Busy: DoEvents: Wend
With ActiveSheet
arr = WorksheetFunction.Transpose(.Range(.[A1], .Cells(Rows.Count, "A").End(xlUp)))
If Not IsArray(arr) Then arr = Array(arr)
ie.document.getElementById("trackField").Value = Join(arr, DELIMITER)
End With
End Sub
If, for instance, you want to pass data to a ComboBox, try this.
Sub passValueToComboBox1()
Dim ie As Object
Dim oHTML_Element As IHTMLElement
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.navigate "http://peterschleif.bplaced.net/excel/combobox/index.php"
While ie.Busy Or ie.readyState <> 4: DoEvents: Wend
Set oHTML_Element = ie.document.getElementsByName("selectedReportClass")(0)
If Not oHTML_Element Is Nothing Then oHTML_Element.Value = "com.db.moap.report.FUBU7"
For Each oHTML_Element In ie.document.getElementsByTagName("input")
If oHTML_Element.Type = "submit" Then oHTML_Element.Click: Exit For
Next
End Sub

I need help inputting a column from excel in VBA with html macro.

I selected 2 cells and named them "perch" and "stats". using what i inputted in the cell, i was able to run a search and retrieve the data i wanted from the html code(which i changed for safety). But my problem is want to input an entire column not just a single cell. And produce multiple results in a single column. Also the number of inputs will change periodically ~300, so i can't stipulate a specific range.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = Range("perch").Row And _
Target.Column = Range("perch").Column Then
Dim IE As New InternetExplorer
'IE.Visible = True
IE.navigate "http://"google/not_real_link"
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Dim Doc As HTMLDocument
Set Doc = IE.document
Dim sTD As String
sTD = Trim(Doc.getElementsByTagName("td")(33).innerText)
IE.Quit
Range("stats").Value = sTD
End If
End Sub
You'll usually see the Worksheet_SelectionChange event used instaed of the Worksheet_Change.
Here are some tips on using these events:
Turn off EnableEvents. If you don't you might re-trigger the event and get stuck in an infinite loop
Use the Intersect method to test to see if your range and the Target intersect.
You should use Target.Cells.Count to see if multiple cells are being effected.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Range("perch")) Is Nothing Then
Application.EnableEvents = False
Application.EnableEvents = True
End If
End Sub
I'm not really sure how you want to handle multiple values.
Creating a function to add value(s) to the end of a list often helps.
Sub AddStatusRow(value As Variant)
Const StatColumn = 5
Dim lastRow As Long
lastRow = Range(Cells(1, StatColumn), Cells(Rows.count, StatColumn)).End(xlUp).Row + 1
Cells(lastRow, StatColumn) = value
End Sub
You might want to consider iterating over the rows of the table instead of Doc.getElementsByTagName("td")(33).innerText.
You can find lots of great examples of what you want to do from the URL below.
http://www.tushar-mehta.com/publish_train/xl_vba_cases/vba_web_pages_services/index.htm

Issue With Looping/Variables Through HTML Table Elements

I have this project I'm working on which involves tracking the order statuses of individual shipments from a list of URLs on an Excel sheet. Currently, the code is able to loop through the URLs fine and extract information from them, but when I try to add exceptions and variables to the loop for each different URL, I get a type mismatch. Currently, there are 3 variables I need in order to extract the HTML information from the HTMLCollection/Table. What I'm trying to do here is:
Cycle through each URL (inserts URL in IE and keeps going without opening new tabs)
Obtain the status of the item for each URL from the HTML element
FedEx: Delivered (td class="status")
UPS: Delivered (id="tt_spStatus")
USPS: Arrived at USPS Facility (class= "info-text first)
My code:
Sub TrackingDeliveryStatusUpdate()
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = True
Dim rngURL As Range
Dim wb1 As Workbook, ws1 As Worksheet, ws2 As Worksheet
Dim MyURL As String
Dim Rows As Long, links As Variant, IE As InternetExplorer, link As Variant
Dim i As Long
Dim sID As String
Dim rngLinks As Range, rngLink As Range
Dim filterRange As Range
Dim copyRange As Range
'Dim doc As Object
Set wb1 = Application.Workbooks.Open("\\S51\Store51\Employee Folders\Jason\TrackingDeliveryStatus.xls")
Set ws1 = wb1.Worksheets("TrackingDeliveryStatusResults")
'Set rngURL = ws1.Range("C2:C" & lastRow)
'Arr = rngURL
Set IE = New InternetExplorer
Rows = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
Set rngLinks = ws1.Range("C2:C" & Rows)
'Loop through each used cell in column C on sheet URLs
'For Each rngURL In Worksheets("TrackingDeliveryStatusResults").Range("C2", Worksheets("TrackingDeliveryStatusResults").Range("C" & Rows.Count).End(xlUp))
'Set HTMLDoc = IE.Document
With IE
.Visible = True
i = 2
For Each rngLink In rngLinks
.Navigate (rngLink)
While .Busy Or .ReadyState <> 4: DoEvents: Wend
'If InStr(1, URL.Value, "fedex") Then sID = "status"
Dim doc As Object
Set doc = IE.Document
'I know this line right below is a big mess. Not sure what to do here.
If InStr(1, rngLink.Value2, "ups") Then
sID = "tt_spStatus"
'If InStr(3, URL.Value, "usps") Then sID = "info-text first"
ws1.Range("D" & i).Value = doc.getElementById(sID).Items(0).Value
'ws1.Range("D" & i).Value = .Document.body.innerText
End If
Next rngLink
i = i + 1
End With
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
I figured this would work, but apparently it doesn't with referencing URLs from an Excel spreadsheet.
You should dim Link and Links as range and change:
links = ws1.Range("C2:C" & Rows)
to:
Set Links = ws1.Range("C2:C" & Rows)
You are trying to make a Variant equal a Range which can't happen. But once you set Links to the range of cells, then when you're looping through each cell reference the URL with link.Value2.
The reason is not working is because you have several concepts mixed up in your statements. I have refactored the relevant parts of the code and made some suggestions on variable type and name changes
Dim rngLinks as Range, rngLink as Range
Set rng Links = ws1.Range("C2:C" & Rows)
For each rngLink in rngLinks
Just because here you are looping through cells in a worksheet range.
Then inside the For each rngLink in rngLinks statement, after the statement where the code waits for IE to load.
Dim doc as Object
Set doc = .document
If InStr(1, rngLink.Value2, "ups") Then
sID = "tt_spStatus"
ws1.Range("D" & I).Value = doc.getElementById(sID).Items(0).Value
End If
You can also delete the For Each TDelement In sID block. It is not needed.