0

I use this code to download the CSV format from Yahoo Finance for a particular ticker. For some reason the CSV file is downloading in the same line as supposed to beginning a new line for everyday in the share price history. Due to this, I am unable to use the open file for input as # method. Any ideas? Thank you kindly in advance for any help or suggestions.

Public Sub DownloadAllHistorical(ticker As Variant, stdate As Date, endate As Date, freq As String, loc As Variant)
Dim a, b, c, d, e, f As String
a = "&a=" & Month(stdate) - 1
b = "&b=" & Day(stdate)
c = "&c=" & Year(stdate)
d = "&d=" & Month(endate) - 1
e = "&e=" & Day(endate)
f = "&f=" & Year(endate)
g = "&g=" & freq

Dim URL As String
URL = "http://ichart.finance.yahoo.com/table.csv?s=" & _
      ticker & _
      a & b & c & _
      d & e & f & _
      g & "&ignore=.csv"

Dim http As MSXML2.XMLHTTP
Set http = New MSXML2.XMLHTTP
http.Open "GET", URL, False
http.send
URL = http.responseBody
If http.Status = 200 Then
    Set ostream = CreateObject("ADODB.Stream")
    ostream.Open
    ostream.Type = 1
    ostream.Write http.responseBody
    ostream.SaveToFile loc & ticker & ".csv", 2 ' 1 = no overwrite, 2 = overwrite
    ostream.Close
End If

Set ostream = Nothing
Set http = Nothing
End Sub
Community
  • 1
  • 1
bp123
  • 15
  • 1
  • 5

1 Answers1

2

This is not a good question. A good question would probably have been answered in minutes.

You can assume that any one who visits the Excel-VBA page of Stack Overflow with the intention of answering questions is familiar with Excel VBA. You should not assume that they are familiar with anything else. You assume a potential answerer is familiar with the word “ticker” and knows the parameters for a Yahoo finance download.

Your title is “CSV text downloading all in one line instead of new lines”. You say: “For some reason the CSV file is downloading in the same line as supposed to beginning a new line for everyday in the share price history.” In fact, the title and the statement are untrue.

Having run your code and looked at the saved file, the problem is obvious. Perhaps if I have given some thought to your wish to use the Input# statement, I would have guessed the cause immediately.

Some features of Windows go back to the days of MS-DOS. In particular, NotePad and Input# only work with MS-DOS style text files. In those days, output devices worked like typewriters: CR meant return to beginning of current line and LF meant advance one line. All text files used CRLF (Carriage return followed by Line feed) as the line delimiter because this meant they could be output directly to printers, consoles, etc.

Most parts of Windows still use CRLF as the default line delimiter but will accept LF which is the standard everywhere else. NotePad and Input# do not.

If you have opened the downloaded file with a text editor that accepts LF as a delimiter, you would have seen that the details for each day are on their own line. You might not have known why but you would not have asked such a misleading question.

What should you do?

Choice 1

Add something like this to your routine:

Dim InxLine As Long
Dim Line() As String

Line = Split(http.responseText, vbLf)
For InxLine = 0 To UBound(Line)
  Debug.Print Line(InxLine)
Next

This code simply output each line to the Immediate Window. You will have to replace Debug.Print Line(InxLine) with appropriate code to process the lines.

Choice 2

If you want to save the CSV file, you can keep your existing routine unchanged and add something like this:

Sub TestOpen()

  Dim WbkThis As Workbook

  Set WbkThis = ThisWorkbook

  Workbooks.Open ("C:\Users\Tony\Desktop\goog.csv")

  ' goog.csv is now the active workbook which have a single worksheet named "goog"
  Sheets("goog").Move After:=WbkThis.Sheets(WbkThis.Worksheets.Count)
  ' because the only sheet within workbook goog.csv has been removed, the workbook is
  ' automatically closed.

End Sub

I have downloaded a CSV file for Google to my desktop. This macro opens that CSV file as a workbook and moves the worksheet containing the data to the workbook containing the macro. The worksheet “goog” is ready to process as required.

Choice 3

If it is really important that the routine create a file that uses CRLF as a line terminator:

Add the following to your existing routine after the download and before the write to disc:

Dim FileText As String
FileText = Replace(http.responseText, vbLf, vbCr & vbLf)

Replace:

ostream.Type = 1
ostream.Write http.responseBody

by:

ostream.Type = 2
ostream.Writetext FileText

This will give a file that NotePad and other ancient programs can split into lines.

Tony Dallimore
  • 12,335
  • 7
  • 32
  • 61
  • 1
    Tony, I totally agree with what you mentioned. In hindsight, I should have been more explicit. I sincerely appreciate your help so thank you and I will keep this in mind next time. Re, your code option 1: the debug.print statement does work and as you say I need to put in an appropriate line to process the lines. The only way I am aware of is using the open file for append method; is there a way of doing it without actually opening/closing a file that has obviously not been saved yet. I guess basically these lines need to be appended to the file 'on the go'. Once again, Thanks in advance. – bp123 Jan 11 '15 at 18:16
  • @bp123 I do not understand. You can create a new text file or overwrite an existing one if you do not wish to append. My problem is: what file? Perhaps if you told me your objective, I could suggest an approach. – Tony Dallimore Jan 11 '15 at 19:13
  • My objective is to download a new csv file and the code I have written above does that except for the crlf. I am trying to find a way to do this as each file is being saved by the code (There are multiple files being done at once). The end result I am seeking is essentially a csv file downloaded that can be used by another software with the formatting that displays each line on a new line - if that makes sense. As supposed to, right now when the file is saved and opened in a text editor, everything is a single line.Regards. – bp123 Jan 11 '15 at 21:00
  • 1
    I agree NotePad requires CRLF but most text editors will be fine with LF. I use NotePad++ but there are many to choose from. Most modern software will accept LF as a line delimiter. Have you tried one of these CSV files with the target software? I can show you how to replace LF by CRLF but I doubt it will be necessary. – Tony Dallimore Jan 11 '15 at 21:11
  • please let me try and rephrase. So if I wanted to append data to the second row such as an updated stock price OR read the last share price in that csv file that has been downloaded already, how would I do that? I cannot use the open file for output/input method because the data in csv is a single file. Would you be able to please tell me how I could do that? Thank you kindly. – bp123 Jan 12 '15 at 06:28
  • @bp123 I still do not understand your problem. In choice 1, I use function `Split` to split the download into lines. `Line(InxLine)` is a single line. You could use `Split(Line(InxLine),",")` to split each line into seven fields. In choice 2, I have saved the download as a worksheet with seven columns. To me it seems either choice gives you a convenient start point for further processing. I have added choice 3 which creates a file that NotePad can split into lines but I do not understand why you would need it. – Tony Dallimore Jan 12 '15 at 09:47
  • With all that confusion, but with your help, I have managed to solve my own problem. In hindsight, I am surprised your answered by question at all, I don't think I would have answered my own question even if I knew the answer! Cheers, – bp123 Jan 12 '15 at 18:17