3

I have written a visual basic macro to load a csv file into Excel that I use quite frequently.

Unfortunately, if the csv file contains quoted newlines, the result is different from what you would get if you opened the csv file directly with excel. Unlike the usual import facility, QueryTables.add() assumes any newline it runs into, whether quoted or not, is the end of the row.

Is there a way around this? I'd prefer a solution that did not involve pre-modifying the incoming csv files to remove the newlines, but I'm open to suggestions on that front as well. I do want to have newlines in the resulting excel file cells, though.

The relevant part of my macro:

Sub LoadMyFile()
    ' Query the table of interest
    With ActiveSheet.QueryTables.Add(Connection:="TEXT;" _
      & ThisWorkbook.Path & "\" & Range("A1").Value & ".csv", _
      Destination:=Range("$A$2"))
        .Name = ActiveSheet.Name
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlOverwriteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 437
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = False
        .TextFileCommaDelimiter = True
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
End Sub

Here's an example csv file with quoted newlines

"firstCol","secondCol"
"name1","data
one"
"name 
2","data two"

The macro reads the file name (minus the .csv extension) from cell A1 and assumes the csv file is in the same directory as the excel file containing the macro.

I'm using 32 bit Office Professional 2010 on a windows 7 machine.

farnsy
  • 2,282
  • 19
  • 22

2 Answers2

3

the import of such CSV files (newlines in data-points) works only with Workbooks.Open and only with CSVs in the locale format (delimiter, text-delimiter), the Excel is used.

Set wb = Workbooks.Open(Filename:="C:\Users\axel\Desktop\test.csv", Local:=True)

aData = wb.Worksheets(1).UsedRange.Value
lRows = UBound(aData, 1)
lCols = UBound(aData, 2)

With ActiveSheet
 .Range(.Cells(1, 1), .Cells(lRows, lCols)).Value = aData
End With

wb.Close

Greetings

Axel

Axel Richter
  • 56,077
  • 6
  • 60
  • 87
  • Thanks for this suggestion. It looks promising. I'll give it a try when I get back to the office on Monday. – farnsy Aug 09 '14 at 23:32
  • As written this solution opens the file in a new workbook (and also fills in a bunch of cells with NA). I may be able to work with it, though. Thanks – farnsy Aug 11 '14 at 21:38
  • Lovely. Local:=True was what I were looking for. Without this, the columns were corrupted. – Unicco Jun 17 '17 at 11:20
1

Edit: the code previously provided was actually designed with the specific example you provided in mind, with 2 columns and a relatively small number of data in the source CSV. I have reviewed the code below to fit other possible scenarios - also including a number of optimizations for runtime efficiency as well.

Note I am not used to using the seeking facilities relating to the Open method that I am relying on here, and I still have a couple misgivings re the way they actually work in some contexts tbh, but after running a couple tests the code looks to work just fine.

Sub csvImportbis()

    Dim s As String
    Dim i As Long
    Dim j As Long
    Dim a() As String

    myfile = FreeFile
    i = 1
    j = 1

    'ENTER YOUR PATH/FILE NAME HERE
    Open "YOUR_PATH/FILENAME" For Input As #myfile

        Do Until EOF(myfile)

            Do
                Input #myfile, s
                cur = Seek(myfile)
                Seek myfile, cur - 1
                i = i + 1
            Loop While input(1, #myfile) <> vbLf

            ReDim a(1 To i - 1, 1 To 10000)

            i = 1

            Seek #myfile, 1

            Do Until EOF(myfile)

                Input #myfile, a(i, j)
                i = i + 1

                If i > UBound(a, 1) Then
                    i = 1
                    j = j + 1
                End If

                If j > UBound(a, 2) Then
                    ReDim Preserve a(1 To UBound(a, 1), 1 To UBound(a, 2) + 10000)
                End If

            Loop

        Loop

    Close #myfile

    sup = j

    ReDim Preserve a(1 To UBound(a, 1), 1 To sup)

    'QUALIFY THE RANGE WITH YOUR WORKBOOK & WORKSHEET REFERENCES
    Range("A1").Resize(sup, UBound(a, 1)) = WorksheetFunction.Transpose(a)

End Sub
IAmDranged
  • 2,890
  • 1
  • 12
  • 6
  • Thanks for the suggestion. At present I'm actually removing these newlines with a different tool before import as a workaround. Unfortunately, they are part of the data and should be retained after import. I've thought about replacing them with a code that I change back into a newline after import, though... – farnsy Aug 09 '14 at 23:31
  • Ok - well you can retain the newlines within your strings with the code above by just getting rid of the replace function and assigning the s1 and s2 string variables directly to the ranges values instead. I was just assuming these newlines shouldn't be retained – IAmDranged Aug 10 '14 at 08:36
  • Ahh, very good. Thanks. Also, does one need to know in advance how many columns there are in the csv file using this method? There is quite a variety in the files I load. Thanks for your help, btw! – farnsy Aug 10 '14 at 15:48
  • No worries. Check out my response - I have provided some new code and information. Hopefully this helps – IAmDranged Aug 10 '14 at 21:50
  • I'm having an issue with this one. My original input file has these annoying fields that look like this: `"=""1994"""` as a workaround to make sure excel reads numbers as text and it's getting mangled. I think it might be easier to work from `Workbooks.Open()` as suggested in the other answer. – farnsy Aug 11 '14 at 21:53
  • Haven't tested out the other answer, but agreed it looks more fitting – IAmDranged Aug 12 '14 at 12:46