I use this code to retrieve historical stock prices for about 40 tickers. I found it here http://www.mathfinance.cn/download-multiple-stock-quotes-from-yahoo-finance
It downloads about half of the symbols before a Run-time Error '1004' pops up. "Unable to open http://table.finance.yahoo.com/table.csv?s=Tickersymbol&a=11&b=21&c=1998 The internet site reports that the item you requested cannot be found (HTTP/1.0 404)
Can I change the code so this error won't happen? The code is below
Sub Get_Yahoo_finance()
Dim Sh As Worksheet
Dim Rng As Range
Dim Cell As Range
Dim Ticker As String
Dim StartDate As Date
Dim EndDate As Date
Dim a, b, c, d, e, f
Dim StrURL As String
Set Sh = Worksheets("Input")
Set Rng = Sh.Range("A2:A" & Sh.Range("A65536").End(xlUp).Row)
For Each Cell In Rng
Ticker = Cell.Value
StartDate = Cell.Offset(0, 1).Value
EndDate = Cell.Offset(0, 2).Value
a = Format(Month(StartDate) - 1, "00") ' Month minus 1
b = Day(StartDate)
c = Year(StartDate)
d = Format(Month(EndDate) - 1, "00")
e = Day(EndDate)
f = Year(EndDate)
StrURL = "URL;http://table.finance.yahoo.com/table.csv?"
StrURL = StrURL & "s=" & Ticker & "&a=" & a & "&b=" & b
StrURL = StrURL & "&c=" & c & "&d=" & d & "&e=" & e
StrURL = StrURL & "&f=" & f & "&g=d&ignore=.csv"
If WorksheetExists(Ticker, ActiveWorkbook) Then
Application.DisplayAlerts = False
Sheets(Ticker).Select
ActiveWindow.SelectedSheets.Delete
ActiveWorkbook.Worksheets.Add.Name = Ticker
Else
ActiveWorkbook.Worksheets.Add.Name = Ticker
End If
With ActiveSheet.QueryTables.Add(Connection:=StrURL, Destination:=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 = xlAllTables
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.Refresh BackgroundQuery:=False
End With
Columns("A:A").TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=True, Space:=False, Other:=False, FieldInfo _
:=Array(Array(1, 4), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), _
Array(7, 1))
Range("A2").Select
Range(Selection, Selection.End(xlDown)).NumberFormat = "d-mmm-yy"
Columns("A:F").EntireColumn.AutoFit
Next Cell
End Sub
Function WorksheetExists(SheetName As String, _
Optional WhichBook As Workbook) As Boolean
'from Chip Pearson
Dim WB As Workbook
Set WB = IIf(WhichBook Is Nothing, ThisWorkbook, WhichBook)
On Error Resume Next
WorksheetExists = CBool(Len(WB.Worksheets(SheetName).Name) > 0)
End Function
EDIT: The code below fixes the issue you reported but runs out of memory very quickly. I have created another answer which I think is much better and robust
It looks like your query is not recognised by the server. You can add some error checks to continue if such an error is encountered.
Sub Get_Yahoo_finance()
Dim Sh As Worksheet
Dim Rng As Range
Dim Cell As Range
Dim Ticker As String
Dim StartDate As Date
Dim EndDate As Date
Dim a, b, c, d, e, f
Dim StrURL As String
Dim errorMsg As String
Set Sh = Worksheets("Input")
Set Rng = Sh.Range("A2:A" & Sh.Range("A65536").End(xlUp).Row)
For Each Cell In Rng
Ticker = Cell.Value
StartDate = Cell.Offset(0, 1).Value
EndDate = Cell.Offset(0, 2).Value
a = Format(Month(StartDate) - 1, "00") ' Month minus 1
b = Day(StartDate)
c = Year(StartDate)
d = Format(Month(EndDate) - 1, "00")
e = Day(EndDate)
f = Year(EndDate)
StrURL = "URL;http://table.finance.yahoo.com/table.csv?"
StrURL = StrURL & "s=" & Ticker & "&a=" & a & "&b=" & b
StrURL = StrURL & "&c=" & c & "&d=" & d & "&e=" & e
StrURL = StrURL & "&f=" & f & "&g=d&ignore=.csv"
If WorksheetExists(Ticker, ActiveWorkbook) Then
Application.DisplayAlerts = False
Sheets(Ticker).Select
ActiveWindow.SelectedSheets.Delete
ActiveWorkbook.Worksheets.Add.Name = Ticker
Else
ActiveWorkbook.Worksheets.Add.Name = Ticker
End If
With ActiveSheet.QueryTables.Add(Connection:=StrURL, Destination:=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 = xlAllTables
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
On Error Resume Next
.Refresh BackgroundQuery:=False
errorMsg = IIf(Err.Number = 0, "", Err.Description)
On Error GoTo 0
End With
If errorMsg = "" Then
Columns("A:A").TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=True, Space:=False, Other:=False, FieldInfo _
:=Array(Array(1, 4), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), _
Array(7, 1))
Range("A2").Select
Range(Selection, Selection.End(xlDown)).NumberFormat = "d-mmm-yy"
Columns("A:F").EntireColumn.AutoFit
Else
Range("A1") = errorMsg
End If
Next Cell
End Sub
Function WorksheetExists(SheetName As String, Optional WhichBook As Workbook) As Boolean '
'from Chip Pearson
Dim WB As Workbook
Set WB = IIf(WhichBook Is Nothing, ThisWorkbook, WhichBook)
On Error Resume Next
WorksheetExists = CBool(Len(WB.Worksheets(SheetName).Name) > 0)
End Function
You might want to delete the sheet instead of putting an error message in it or maybe send a MsgBox instead...
I can't get your method to work properly (I get out of memory errors after a few 100s of tickers).
So I got interested and dug a bit further. I propose another approach below which is more complex but yields better results (I uploaded the 500 stocks of the S&P in 3 minutes (about 3 seconds for the actual job in Excel, the rest is connection / download time). Just copy paste the whole code in a module and run the runBatch procedure.
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMillisecond As Long)
Private Declare Function URLDownloadToCacheFile Lib "urlmon" _
Alias "URLDownloadToCacheFileA" (ByVal lpUnkcaller As Long, _
ByVal szURL As String, ByVal szFileName As String, _
ByVal dwBufLength As Long, ByVal dwReserved As Long, _
ByVal IBindStatusCallback As Long) As Long
Public Sub runBatch()
'Assumes there is a sheet called "Input" with 3 columns:
'Ticker, Start Date, End Date
'Actual data starts from Row 2
Dim tickerData As Variant
Dim ticker As String
Dim url As String
Dim i As Long
Dim yahooData As Variant
On Error GoTo error_handler
Application.ScreenUpdating = False
tickerData = Sheets("Input").UsedRange
For i = LBound(tickerData, 1) + 1 To UBound(tickerData, 1) 'skip first row
ticker = tickerData(i, 1)
url = getYahooUrl(ticker, tickerData(i, 2), tickerData(i, 3))
yahooData = getCsvContent(url)
If isArrayEmpty(yahooData) Then
MsgBox "No data found for " + ticker
Else
copyDataToSheet yahooData, ticker
End If
Next i
Application.ScreenUpdating = True
Exit Sub
error_handler:
MsgBox "Error found while reading ticker [" + ticker + "]: " + Err.Description
Application.ScreenUpdating = True
End Sub
Private Function getYahooUrl(ByVal ticker As String, ByVal startDate As Date, ByVal endDate As Date) As String
Dim a As String
Dim b As String
Dim c As String
Dim d As String
Dim e As String
Dim f As String
a = Format(Month(startDate) - 1, "00") ' Month minus 1
b = Day(startDate)
c = Year(startDate)
d = Format(Month(endDate) - 1, "00")
e = Day(endDate)
f = Year(endDate)
getYahooUrl = "http://table.finance.yahoo.com/table.csv?" & _
"s=" & ticker & "&" & _
"a=" & a & "&" & _
"b=" & b & "&" & _
"c=" & c & "&" & _
"d=" & d & "&" & _
"e=" & e & "&" & _
"f=" & f & "&" & _
"g=d&ignore=.csv"
End Function
Private Function getCsvContent(url As String) As Variant
Const RETRY_NUMS As Long = 3 'How m any times do we retry the download before giving up
Dim szFileName As String
Dim i As Long
For i = 1 To RETRY_NUMS
szFileName = Space$(300)
If URLDownloadToCacheFile(0, url, szFileName, Len(szFileName), 0, 0) = 0 Then
getCsvContent = getDataFromFile(Trim(szFileName), ",")
Kill Trim(szFileName) 'to make sure data is refreshed next time
Exit Function
End If
Sleep (500)
Next i
End Function
Private Sub copyDataToSheet(data As Variant, sheetName As String)
If Not WorksheetExists(sheetName) Then
Worksheets.Add.Name = sheetName
End If
With Sheets(sheetName)
.Cells.ClearContents
.Cells(1, 1).Resize(UBound(data, 1), UBound(data, 2)) = data
.Columns(1).NumberFormat = "d-mmm-yy"
.Columns("A:F").AutoFit
End With
End Sub
Private Function WorksheetExists(sheetName As String, Optional WhichBook As Workbook) As Boolean '
'from Chip Pearson
Dim WB As Workbook
Set WB = IIf(WhichBook Is Nothing, ThisWorkbook, WhichBook)
On Error Resume Next
WorksheetExists = CBool(Len(WB.Worksheets(sheetName).Name) > 0)
End Function
Private Function isArrayEmpty(parArray As Variant) As Boolean
'Returns false if not an array or dynamic array that has not been initialised (ReDim) or has been erased (Erase)
If IsArray(parArray) = False Then isArrayEmpty = True
On Error Resume Next
If UBound(parArray) < LBound(parArray) Then isArrayEmpty = True: Exit Function Else: isArrayEmpty = False
End Function
Private Function getDataFromFile(parFileName As String, parDelimiter As String, Optional parExcludeCharacter As String = "") As Variant 'V.20081021
'parFileName is supposed to be a delimited file (csv...)
'Returns an empty array if file is empty or can't be opened
'20081021: number of columns based on the line with the largest number of columns, not on the first line
' parExcludeCharacter: sometimes csv files have quotes around strings: "XXX" - if parExcludeCharacter = """" then removes the quotes
'20081022: Error Checks in place
Dim locLinesList() As Variant
Dim locData As Variant
Dim i As Long
Dim j As Long
Dim locNumRows As Long
Dim locNumCols As Long
Dim fso As Variant
Dim ts As Variant
Const REDIM_STEP = 10000
Set fso = CreateObject("Scripting.FileSystemObject")
On Error GoTo error_open_file
Set ts = fso.OpenTextFile(parFileName)
On Error GoTo unhandled_error
'Counts the number of lines and the largest number of columns
ReDim locLinesList(1 To 1) As Variant
i = 0
Do While Not ts.AtEndOfStream
If i Mod REDIM_STEP = 0 Then
ReDim Preserve locLinesList(1 To UBound(locLinesList, 1) + REDIM_STEP) As Variant
End If
locLinesList(i + 1) = Split(ts.ReadLine, parDelimiter)
j = UBound(locLinesList(i + 1), 1) 'number of columns
If locNumCols < j Then locNumCols = j
i = i + 1
Loop
ts.Close
locNumRows = i
If locNumRows = 0 Then Exit Function 'Empty file
ReDim locData(1 To locNumRows, 1 To locNumCols + 1) As Variant
'Copies the file into an array
If parExcludeCharacter <> "" Then
For i = 1 To locNumRows
For j = 0 To UBound(locLinesList(i), 1)
If Left(locLinesList(i)(j), 1) = parExcludeCharacter Then
If Right(locLinesList(i)(j), 1) = parExcludeCharacter Then
locLinesList(i)(j) = Mid(locLinesList(i)(j), 2, Len(locLinesList(i)(j)) - 2) 'If locTempArray = "", Mid returns ""
Else
locLinesList(i)(j) = Right(locLinesList(i)(j), Len(locLinesList(i)(j)) - 1)
End If
ElseIf Right(locLinesList(i)(j), 1) = parExcludeCharacter Then
locLinesList(i)(j) = Left(locLinesList(i)(j), Len(locLinesList(i)(j)) - 1)
End If
locData(i, j + 1) = locLinesList(i)(j)
Next j
Next i
Else
For i = 1 To locNumRows
For j = 0 To UBound(locLinesList(i), 1)
locData(i, j + 1) = locLinesList(i)(j)
Next j
Next i
End If
getDataFromFile = locData
Exit Function
error_open_file: 'returns empty variant
unhandled_error: 'returns empty variant
End Function
I ran it once and it failed. Put a breakpoint on the query line, loaded the yahoo address into my browser to make sure it was valid, then the script worked. I also made sure that there were no other worksheets in the project. Here's a screenshot of the VBA editor and where the breakpoint goes:
You can stick the variable into a watch window and then fool around with it to see what it does. If you come up with any applications for this I'd love to hear about them!
Attached is a "simpler" solution using the original code modified to retry retrieving the ticker data upto 3 times (waiting a few seconds between attempts) before finally admitting failure by messagebox. My 2 cents :-)
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMillisecond As Long)
Sub Get_Yahoo_finance_history()
Dim Sh As Worksheet
Dim Rng As Range
Dim Cell As Range
Dim Ticker As String
Dim StartDate As Date
Dim EndDate As Date
Dim a, b, c, d, e, f
Dim StrURL As String
Dim RetryCount As Integer
'turn calculation off
'Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
Set Sh = Worksheets("Input")
Set Rng = Sh.Range("A2:A" & Sh.Range("A65536").End(xlUp).Row)
For Each Cell In Rng
Ticker = Cell.Value
StartDate = Cell.Offset(0, 1).Value
EndDate = Cell.Offset(0, 2).Value
a = Format(Month(StartDate) - 1, "00") ' Month minus 1
b = Day(StartDate)
c = Year(StartDate)
d = Format(Month(EndDate) - 1, "00")
e = Day(EndDate)
f = Year(EndDate)
StrURL = "URL;http://table.finance.yahoo.com/table.csv?"
StrURL = StrURL & "s=" & Ticker & "&a=" & a & "&b=" & b
StrURL = StrURL & "&c=" & c & "&d=" & d & "&e=" & e
StrURL = StrURL & "&f=" & f & "&g=d&ignore=.csv"
If WorksheetExists(Ticker, ActiveWorkbook) Then
Sheets(Ticker).Select
ActiveWindow.SelectedSheets.Delete
ActiveWorkbook.Worksheets.Add.Name = Ticker
Else
ActiveWorkbook.Worksheets.Add.Name = Ticker
End If
RetryCount = 0 Retry:
If RetryCount > 3 Then
Range("A1") = errorMsg
MsgBox "After 3 attempts: Could not retrieve data for " + Ticker
End
End If
RetryCount = RetryCount + 1
With ActiveSheet.QueryTables.Add(Connection:=StrURL, Destination:=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 = xlAllTables
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
On Error Resume Next
.Refresh BackgroundQuery:=False
errorMsg = IIf(Err.Number = 0, "", Err.Description)
On Error GoTo 0
End With
If errorMsg = "" Then
Columns("A:A").TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=True, Space:=False, Other:=False, FieldInfo _
:=Array(Array(1, 4), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), _
Array(7, 1))
Columns("A").EntireColumn.NumberFormat = "mm/dd/yyyy"
Columns("B:E").EntireColumn.NumberFormat = "$###,##0.00"
Columns("F").EntireColumn.NumberFormat = "###,##0"
Columns("B:E").EntireColumn.NumberFormat = "$###,##0.00"
Columns("A:F").EntireColumn.AutoFit
Else
Sleep (500)
Sheets(Ticker).Cells.ClearContents
GoTo Retry
End If
Next Cell
'turn calculation back on
'Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
End Sub
Function WorksheetExists(SheetName As String, _
Optional WhichBook As Workbook) As Boolean
'from Chip Pearson
Dim WB As Workbook
Set WB = IIf(WhichBook Is Nothing, ThisWorkbook, WhichBook)
On Error Resume Next
WorksheetExists = CBool(Len(WB.Worksheets(SheetName).Name) > 0)
End Function
Related
Dim sDate As Date, eDate As Date, sTime As Date, eTime As Date
sTime = Sheet2.[B3]
eTime = Sheet2.[B4]
If sTime > eTime Then
Call pullInferred_Time(Sheet2.[B1], Sheet2.[B2], Sheet2.[B3], Sheet2.[B4], "Inferred_Time")
Call pullPPR(Sheet2.[B1], Sheet2.[B2], Sheet2.[B3], Sheet2.[B4])
Call pullPod_Gaps(Sheet2.[B1], Sheet2.[B8], Sheet2.[B5], Sheet2.[B6])
Call pullOOWA(Sheet2.[B1], Sheet2.[B8], Sheet2.[B5], Sheet2.[B6])
Call pullKiva_Scout(Sheet2.[B1], Sheet2.[B8], Sheet2.[B5], Sheet2.[B6])
Else
Call pullInferred_Time(Sheet2.[B1], Sheet2.[B2], Sheet2.[B3], Sheet2.[B4], "Inferred_Time")
Call pullPPR(Sheet2.[B1], Sheet2.[B2], Sheet2.[B3], Sheet2.[B4])
Call pullPod_Gaps(Sheet2.[B1], Sheet2.[B2], Sheet2.[B5], Sheet2.[B6])
Call pullOOWA(Sheet2.[B1], Sheet2.[B2], Sheet2.[B5], Sheet2.[B6])
Call pullKiva_Scout(Sheet2.[B1], Sheet2.[B2], Sheet2.[B5], Sheet2.[B6])
Sub pullPod_Gaps(sDate, eDate, sTime, eTime)
Dim H As New WinHttp.WinHttpRequest
Dim dataobj As New MSForms.DataObject
Dim URL As String
Dim html As New HTMLDocument
Dim htmlMetricTotals As HTMLHtmlElement
Dim htmlTable As HTMLHtmlElement
Dim htmlTBody As HTMLHtmlElement
Dim htmlTR As HTMLHtmlElement
Dim i As Integer
On Error Resume Next
i = 2
'sDate = ConvertFromLocalTimezoneToUTC(sDate)
'eDate = ConvertFromLocalTimezoneToUTC(eDate)
'sDate = toUnix(sDate)
'eDate = toUnix(eDate)
URL = "https://roboscout.amazon.com/view_plot_data/?sites=(LGB3" _
& ")¤t_day=false&startDateTime=" & Format(sDate, "yyyy-mm-dd") _
& Format(sTime, "+hh%3A") _
& Format(sTime, "nn%3A00") _
& "&endDateTime=" & Format(eDate, "yyyy-mm-dd") _
& Format(eTime, "+hh%3A") _
& Format(eTime, "nn%3A00") _
& "&mom_ids=1443&osm_ids=977&oxm_ids=1131&ofm_ids=602&viz=nvd3Table&instance_id=0&object_id=20990&BrowserTZ=America%2FLos_Angeles&app_name=RoboScout&mode=CSV"
Debug.Print URL
H.SetAutoLogonPolicy 0
H.SetTimeouts 0, 0, 0, 0
H.Open "GET", URL, False
H.SetClientCertificate "CURRENT_USER\MY\" & Environ("USERNAME")
H.setRequestHeader "Cookie", VBAMidway_v1()
H.send
H.WaitForResponse
Debug.Print H.Status
Debug.Print H.responseText
dataobj.SetText H.responseText
dataobj.PutInClipboard
With Sheets("Pod_Gaps")
.Activate
.Cells.Clear
.Cells(1, 1).Select
.PasteSpecial Format:="Text", link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
.Columns("A:A").TextToColumns DataType:=xlDelimited, ConsecutiveDelimiter:=False, Comma:=True, Space:=False
End With
End Sub
Sub pullOOWA(sDate, eDate, sTime, eTime)
Dim H As New WinHttp.WinHttpRequest
Dim dataobj As New MSForms.DataObject
Dim URL As String
Dim html As New HTMLDocument
Dim htmlMetricTotals As HTMLHtmlElement
Dim htmlTable As HTMLHtmlElement
Dim htmlTBody As HTMLHtmlElement
Dim htmlTR As HTMLHtmlElement
Dim i As Integer
On Error Resume Next
i = 2
'sDate = ConvertFromLocalTimezoneToUTC(sDate)
'eDate = ConvertFromLocalTimezoneToUTC(eDate)
'sDate = toUnix(sDate)
'eDate = toUnix(eDate)
URL = "https://roboscout.amazon.com/view_plot_data/?sites=(LGB3" _
& ")&startDateTime=" & Format(sDate, "yyyy-mm-dd") _
& Format(sTime, "+hh%3A") _
& Format(sTime, "nn%3A00") _
& "&endDateTime=" & Format(eDate, "yyyy-mm-dd") _
& Format(eTime, "+hh%3A") _
& Format(eTime, "nn%3A00") _
& "&mom_ids=2170%2C2168&osm_ids=1426&oxm_ids=2593&ofm_ids=1017&instance_id=0&object_id=21628&BrowserTZ=America%2FLos_Angeles&app_name=RoboScout&mode=CSV"
Debug.Print URL
H.SetAutoLogonPolicy 0
H.SetTimeouts 0, 0, 0, 0
H.Open "GET", URL, False
H.SetClientCertificate "CURRENT_USER\MY\" & Environ("USERNAME")
H.setRequestHeader "Cookie", VBAMidway_v1()
H.send
H.WaitForResponse
Debug.Print H.Status
Debug.Print H.responseText
dataobj.SetText H.responseText
dataobj.PutInClipboard
With Sheets("OOWA")
.Activate
.Cells.Clear
.Cells(1, 1).Select
.PasteSpecial Format:="Text", link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
.Columns("A:A").TextToColumns DataType:=xlDelimited, ConsecutiveDelimiter:=False, Comma:=True, Space:=False
End With
End Sub
Sub pullKiva_Scout(sDate, eDate, sTime, eTime)
Dim H As New WinHttp.WinHttpRequest
Dim dataobj As New MSForms.DataObject
Dim URL As String
Dim html As New HTMLDocument
Dim htmlMetricTotals As HTMLHtmlElement
Dim htmlTable As HTMLHtmlElement
Dim htmlTBody As HTMLHtmlElement
Dim htmlTR As HTMLHtmlElement
Dim i As Integer
On Error Resume Next
i = 2
'sDate = ConvertFromLocalTimezoneToUTC(sDate)
'eDate = ConvertFromLocalTimezoneToUTC(eDate)
'sDate = toUnix(sDate)
'eDate = toUnix(eDate)
URL = "https://kivascout.amazon.com/view_plot_data/?sites=(LGB3" _
& ")¤t_day=false&startDateTime=" & Format(sDate, "yyyy-mm-dd") _
& Format(sTime, "+hh%3A") _
& Format(sTime, "nn%3A") _
& "00&endDateTime=" _
& Format(eDate, "yyyy-mm-dd") _
& Format(eTime, "+hh%3A") _
& Format(eTime, "nn%3A") _
& "00&mom_ids=394%2C362%2C379%2C426&osm_ids=&oxm_ids=444&ofm_ids=&viz=nvd3Table&instance_id=1927&object_id=19851&BrowserTZ=America%2FLos_Angeles&app_name=RoboScout&mode=CSV"
Debug.Print URL
H.SetAutoLogonPolicy 0
H.SetTimeouts 0, 0, 0, 0
H.Open "GET", URL, False
H.SetClientCertificate "CURRENT_USER\MY\" & Environ("USERNAME")
H.setRequestHeader "Cookie", VBAMidway_v1()
H.send
H.WaitForResponse
Debug.Print H.Status
Debug.Print H.responseText
dataobj.SetText H.responseText
dataobj.PutInClipboard
With Sheets("Kiva_Scout")
.Activate
.Cells.Clear
.Cells(1, 1).Select
.PasteSpecial Format:="Text", link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
.Columns("A:A").TextToColumns DataType:=xlDelimited, ConsecutiveDelimiter:=False, Comma:=True, Space:=False
End With
End Sub
Im kinda stuck here I need my code to be able to check to see if the value for sheet2.[B5] is greater than the value for Sheet2.[B6] then it will use the value for Sheet2.[B8] instead of the value in Sheet2.[B2] but only for the following calls(OOWA, Pod_gaps, Kiva_scout). sorry if I didn't write this well I'm new to VBA
I have an excel macro that can separate and save files per column. My problem is that I cannot make it work with large number of rows (60,000).
What should I change in my VBA code below to make it work?
Dim MyFile, NewFile As Variant
Dim sort_data As String
Dim last_row, tfiles, start_row, ktr As Integer
'Capture errors
On Error GoTo ErrorHandler
'Check for complete data
If (Separate.file_open.Value = False And Separate.Filename _
= "") Or Separate.first = "" Or Separate.last = "" Or _
Separate.sort = "" Or Separate.left_column = "" Or _
Separate.right = "" Then
MsgBox "Insufficient data.", 16, "Warning!"
Exit Sub
End If
'Turn application alerts off
Application.DisplayAlerts = False
'Open filename if necessary
If Separate.file_open.Value = False Then
Workbooks.Open Separate.Filename
End If
'Get current workbook name
MyFile = left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) _
- 4)
'Get last row of data
For last_row = Separate.last + 1 To 1048576
If Range(Separate.sort & last_row).Value = "" Then
Exit For
End If
Next last_row
'Sort data
Range(Separate.left_column & Separate.last, Separate.right & last_row).Select
Selection.sort Key1:=Range(Separate.sort & Separate.last + 1), Order1:=xlAscending, Header:=True, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
The problem is due to:
Dim last_row, tfiles, start_row, ktr As Integer
Integer mentioned in the script having a max number 32,767. You can use Long instead of Integer.
Dim last_row, tfiles, start_row, ktr As Long
May you please help me with this, I spent hours trying to figure it out but couldn't. Note: I am still learning VBA.
I have 7 headings in one spreadsheet that I want to transfer 7 text files into them.
In each text file, I want 2 columns in the text file to be selected and put into the correct heading.
I have got that bit done, but I want all text files to open at once at each heading. My problem is the files are changeable, so I don't want to specify the file name, just the path and it picks the oldest date text file to the first heading in the spreadsheet.
I tried Dir("Y:\Engineering\" & "*.txt") but Open command doesn't work, unless the path is correct and a copy of the text file is in the User Document Folder. Can I fix that to only being in the path without a need of a copy in a different folder?
Thanks in advance I appreciate it much!
This is what I have done:
Sub OpenText()
Dim FilePath As String
FilePath = "Y:\Engineering\1.txt"
Open FilePath For Input As #1
row_number = 0
Do Until EOF(1)
Line Input #1 , LineFromFile
LineItems = Split(LineFromFile, ",")
ActiveCell.Offset(row_number, 0).Value = LineItems(1)
ActiveCell.Offset(row_number, 1).Value = LineItems(4)
row_number = row_number + 1
Loop
Close #1
End Sub
Updated code.
Main() function does the actions, also you should setup this part:
sPath = "C:\Tets\"
Conditions: you should have following sheets in excel file - FileList, Import, ImportResults
You can try following code:
Option Explicit
Public oFSO As Object
Public arrFiles()
Public lngFiles As Long
Sub Main()
Dim sPath As String
Dim strXlsList As String
Dim strXlsListImport As String
Dim strXlsListImportResults As String
sPath = "C:\Tets\1\"
strXlsList = "FileList"
strXlsListImport = "Import"
strXlsListImportResults = "ImportResults"
Dim lngFilesCount As Long
lngFilesCount = 0
Erase arrFiles
Set oFSO = CreateObject("Scripting.FileSystemObject")
Call recurse(sPath)
Dim Counter As Long
For Counter = 0 To UBound(arrFiles, 2)
Sheets(strXlsList).Range("A" & Counter + 1) = arrFiles(0, Counter)
Sheets(strXlsList).Range("B" & Counter + 1) = arrFiles(1, Counter)
lngFilesCount = lngFilesCount + 1
Next Counter
' filter due date
If ActiveSheet.Name <> strXlsList _
Then
Sheets(strXlsList).Activate
End If
Range("A2:B2").Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWorkbook.Worksheets("FileList").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("FileList").Sort.SortFields.Add Key:=Range("B2:B4") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("FileList").Sort
.SetRange Range("A2:B4")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Dim lngCurrent As Long
Dim lngFilePositionColumn As Long
Dim lngOffset As Long
lngFilePositionColumn = 1
lngOffset = 1
For lngCurrent = 2 To lngFilesCount - 1
' import file
ImportTextFile Sheets(strXlsList).Range("A" & lngCurrent), strXlsListImport
' copy data from 2nd column
subCopyData strXlsListImport, strXlsListImportResults, 2, lngOffset
lngOffset = lngOffset + 1
' copy data from 5th column
subCopyData strXlsListImport, strXlsListImportResults, 5, lngOffset
lngOffset = lngOffset + 1
Next lngCurrent
End Sub
Public Sub subCopyData( _
ByVal strSheetFrom As String, _
ByVal strSheetTo As String, _
ByVal lngColumnNumberFrom As Long, _
ByVal lngOffset As Long)
Sheets(strSheetFrom).Activate
Columns(lngColumnNumberFrom).Select
Selection.Copy
Sheets(strSheetTo).Select
Columns(lngOffset).Select
ActiveSheet.Paste
End Sub
Sub recurse(sPath As String)
Dim oFolder As Object
Dim oSubFolder As Object
Dim oFile As Object
Set oFolder = oFSO.GetFolder(sPath)
'Collect file information
For Each oFile In oFolder.Files
lngFiles = lngFiles + 1
ReDim Preserve arrFiles(1, lngFiles + 1)
arrFiles(0, lngFiles) = sPath & oFile.Name
arrFiles(1, lngFiles) = oFile.DateLastModified
Debug.Print lngFiles
Next oFile
'looking for all subfolders
For Each oSubFolder In oFolder.SubFolders
'recursive call is commented, looks only in folder
'Call recurse(oSubFolder.Path)
Next oSubFolder
End Sub
Sub ImportTextFile( _
ByVal strFile As String, _
ByVal strXlsList As String _
)
If ActiveSheet.Name <> strXlsList _
Then
Sheets(strXlsList).Activate
End If
' clear existing data
Cells.Select
Selection.Delete Shift:=xlUp
' import text file
Range("A1").Select
With ActiveSheet.QueryTables.Add(Connection:="TEXT;" & strFile, _
Destination:=Range("$A$1"))
'.CommandType = 0
.Name = "next"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 866
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
I am using below code to extract data from Amazon.
Sub Macro1()
' Macro1 Macro
With ActiveSheet.QueryTables.Add(Connection:= _
"URL;http://www.amazon.com/gp/offer-listing/B00N41UTWG/ref=olp_f_new?ie=UTF8&f_new=true" _
, Destination:=Range("$A$1"))
.Name = "oldOfferPrice" _
' "its_details_value_node.html?nsc=true&listId=www_s201_b9233&tsId=BBK01.ED0439"
.FieldNames = True
.RowNumbers = True
.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 = True
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
End Sub
Above code is extracting complete page data but my requirement is to extract only prices. Page prices are in this format.
<div class="a-row a-spacing-mini olpOffer">
<div class="a-column a-span2">
<span class="a-size-large a-color-price olpOfferPrice a-text-bold"> $171.99 </span>
<span class="a-color-price">
<span class="supersaver"><i class="a-icon a-icon-prime" aria-label="Amazon Prime TM"><span class="a-icon-alt">Amazon Prime TM</span></i></span>
</span>
I want to extract two values i.e $171.99 and Amazon Prime TM. There may be multiple price and seller values in one page and I want to extract all.
Here is an example showing how you can retrieve Amazon offers for certain ASIN using XHR and Split, and output results to the sheet:
Sub TestExtractAmazonOffers()
Dim arrList() As Variant
' clear sheet
Sheets("Sheet1").Cells.Delete
' retrieve offers for certain ASIN
arrList = ExtractAmazonOffers("B07CR8D2DW")
' output data
Output Sheets("Sheet1"), 1, 1, arrList
End Sub
Function ExtractAmazonOffers(strASIN As String)
Dim strUrl As String
Dim arrTmp() As String
Dim strTmp As String
Dim arrItems() As String
Dim i As Long
Dim arrCols() As String
Dim strSellerName As String
Dim strOfferPrice As String
Dim strAmazonPrime As String
Dim strShippingPrice As String
Dim arrResults() As Variant
Dim arrCells() As Variant
' init
arrResults = Array(Array("Offer Price", "Amazon Prime TM", "Shipping Price", "Seller Name"))
strUrl = "https://www.amazon.com/gp/offer-listing/" & strASIN & "/ref=olp_f_new?ie=UTF8&f_new=true"
Do
' http get request of the search result page
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", strUrl, False
.Send
strResp = .ResponseText
End With
arrTmp = Split(strResp, "id=""olpOfferList""", 2)
If UBound(arrTmp) = 1 Then
arrItems = Split(arrTmp(1), "<div class=""a-row a-spacing-mini olpOffer""")
For i = 1 To UBound(arrItems)
' get item columns
arrCols = Split(arrItems(i), "<div class=""a-column", 6)
' retrieve seller name from column 4
strTmp = Split(arrCols(4), "olpSellerName", 2)(1)
arrTmp = Split(strTmp, "alt=""", 2)
If UBound(arrTmp) = 1 Then ' from image alt
strTmp = Split(arrTmp(1), """", 2)(0)
strSellerName = Trim(strTmp)
Else ' from link
strTmp = Split(strTmp, "<a", 2)(1)
strTmp = Split(strTmp, ">", 2)(1)
strTmp = Split(strTmp, "<", 2)(0)
strSellerName = Trim(strTmp)
End If
' retrieve offer price from column 1
strTmp = Split(arrCols(1), "olpOfferPrice", 2)(1)
strTmp = Split(strTmp, ">", 2)(1)
strTmp = Split(strTmp, "<", 2)(0)
strOfferPrice = Trim(strTmp)
' retrieve amazon prime
arrTmp = Split(arrCols(1), "olpShippingInfo", 2)
strAmazonPrime = IIf(InStr(arrTmp(0), "Amazon Prime") > 0, "Amazon Prime", "-")
' retrieve shipping info
arrTmp = Split(arrTmp(1), "olpShippingPrice", 2)
If UBound(arrTmp) = 1 Then
strTmp = Split(arrTmp(1), ">", 2)(1)
strTmp = Split(strTmp, "<", 2)(0)
strShippingPrice = Trim(strTmp)
Else
strShippingPrice = "Free"
End If
' store data
ReDim Preserve arrResults(UBound(arrResults) + 1)
arrResults(UBound(arrResults)) = Array(strOfferPrice, strAmazonPrime, strShippingPrice, strSellerName)
Next
End If
' search for next page link
arrTmp = Split(strResp, "class=""a-last""", 2)
If UBound(arrTmp) = 0 Then Exit Do
strTmp = Split(arrTmp(1), "href=""", 2)(1)
strUrl = Split(strTmp, """", 2)(0)
If Left(strUrl, 1) = "/" Then strUrl = "https://www.amazon.com" & strUrl
Loop
' convert nested array to 2-dimensional array
ReDim arrCells(UBound(arrResults), 3)
For i = 0 To UBound(arrCells, 1)
For j = 0 To UBound(arrCells, 2)
arrCells(i, j) = arrResults(i)(j)
Next
Next
ExtractAmazonOffers = arrCells
End Function
Sub Output(objSheet As Worksheet, lngTop As Long, lngLeft As Long, arrCells As Variant)
With objSheet
.Select
With .Range(.Cells(lngTop, lngLeft), .Cells( _
UBound(arrCells, 1) - LBound(arrCells, 1) + lngTop, _
UBound(arrCells, 2) - LBound(arrCells, 2) + lngLeft))
.NumberFormat = "#"
.Value = arrCells
.Columns.AutoFit
End With
End With
End Sub
The resulting sheet is as follows:
I am in the process of making a program I wrote using excel vba faster.
The program downloads stock market data from the asx.
I want to get data from 2 urls:
MY CODE
url2 = "http://ichart.finance.yahoo.com/table.txt?s=bhp.ax"
Set XMLHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
XMLHTTP.Open "GET", url2, False
XMLHTTP.send
result = XMLHTTP.responseText
ActiveCell.Value = result
Set XMLHTTP = Nothing
URL 1. http://ichart.finance.yahoo.com/table.txt?s=bhp.ax
MY PROBLEM.
This file is very large. I thought I could simply store the result of these http requests and print it to the debug window or directly to a cell. However these methods seem to be cutting off parts of the data?
if I download the txt file from url 2 in notepad++ it has almost 200 000 characters
but it excel it has between 3 -5 000. What is the best way to handle these requests so that all the data is captured and I can parse it all later?
URL 2. from the first URL I only want the JSON data which results from the YQL query.
MY PROBLEM
I am not sure how to get just the json data when you follow the link below, and or how to store it so that the problem experienced with URL 1 (missing data) does not occur.
http://developer.yahoo.com/yql/console/?q=select%20symbol%2C%20ChangeRealtime%20from%20yahoo.finance.quotes%20where%20symbol%20in%20%28%22YHOO%22%2C%22AAPL%22%2C%22GOOG%22%2C%22MSFT%22%29%20|%20sort%28field%3D%22ChangeRealtime%22%2C%20descending%3D%22true%22%29%0A%09%09&env=http%3A%2F%2Fdatatables.org%2Falltables.env#h=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20%28%22bhp.ax%22%29
Many Thanks, Josh.
Try this revised code
Sub GetYahooFinanceTable()
Dim sURL As String, sResult As String
Dim oResult As Variant, oData As Variant, R As Long, C As Long
sURL = "http://ichart.finance.yahoo.com/table.txt?s=bhp.ax"
Debug.Print "URL: " & sURL
sResult = GetHTTPResult(sURL)
oResult = Split(sResult, vbLf)
Debug.Print "Lines of result: " & UBound(oResult)
For R = 0 To UBound(oResult)
oData = Split(oResult(R), ",")
For C = 0 To UBound(oData)
ActiveSheet.Cells(R + 1, C + 1) = oData(C)
Next
Next
Set oResult = Nothing
End Sub
Function GetHTTPResult(sURL As String) As String
Dim XMLHTTP As Variant, sResult As String
Set XMLHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
XMLHTTP.Open "GET", sURL, False
XMLHTTP.Send
Debug.Print "Status: " & XMLHTTP.Status & " - " & XMLHTTP.StatusText
sResult = XMLHTTP.ResponseText
Debug.Print "Length of response: " & Len(sResult)
Set XMLHTTP = Nothing
GetHTTPResult = sResult
End Function
This will split up the data into Rows so the max text length are not reached in a cell. Also this have further split the data with commas into corresponding columns.
You may like to try following code from http://investexcel.net/importing-historical-stock-prices-from-yahoo-into-excel/
I just modify the qurl variable to your url and it work, it pouring 4087 line of data to my excel sheet, nicely formatted without any problem.
Just name your sheet1 as Data.
Sub GetData()
Dim DataSheet As Worksheet
Dim EndDate As Date
Dim StartDate As Date
Dim Symbol As String
Dim qurl As String
Dim nQuery As Name
Dim LastRow As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
Sheets("Data").Cells.Clear
Set DataSheet = ActiveSheet
' StartDate = DataSheet.Range("startDate").Value
' EndDate = DataSheet.Range("endDate").Value
' Symbol = DataSheet.Range("ticker").Value
' Sheets("Data").Range("a1").CurrentRegion.ClearContents
' qurl = "http://ichart.finance.yahoo.com/table.csv?s=" & Symbol
' qurl = qurl & "&a=" & Month(StartDate) - 1 & "&b=" & Day(StartDate) & _
' "&c=" & Year(StartDate) & "&d=" & Month(EndDate) - 1 & "&e=" & _
' Day(EndDate) & "&f=" & Year(EndDate) & "&g=" & Sheets("Data").Range("a1") & "&q=q&y=0&z=" & _
' Symbol & "&x=.csv"
qurl = "http://ichart.finance.yahoo.com/table.txt?s=bhp.ax"
Debug.Print qurl
QueryQuote:
With Sheets("Data").QueryTables.Add(Connection:="URL;" & qurl, Destination:=Sheets("Data").Range("a1"))
.BackgroundQuery = True
.TablesOnlyFromHTML = False
.Refresh BackgroundQuery:=False
.SaveData = True
End With
Sheets("Data").Range("a1").CurrentRegion.TextToColumns Destination:=Sheets("Data").Range("a1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=True, Space:=False, other:=False
Sheets("Data").Columns("A:G").ColumnWidth = 12
LastRow = Sheets("Data").UsedRange.Row - 2 + Sheets("Data").UsedRange.Rows.Count
Sheets("Data").Sort.SortFields.Add Key:=Range("A2"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With Sheets("Data").Sort
.SetRange Range("A1:G" & LastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
.SortFields.Clear
End With
End Sub
(the above is not my code, it was taken from the excel file they posted on investexcel.net link above)