Parse CSV, ignoring commas inside string literals in VBA?

后端 未结 11 1909
青春惊慌失措
青春惊慌失措 2020-12-30 03:27

I have a VBA application that runs every day. It checks a folder where CSVs are downloaded automatically, and adds their contents to a database. When parsing them, I reali

11条回答
  •  忘掉有多难
    2020-12-30 04:11

    @Gimp said...

    The current answers do not contain enough detail.

    I'm running into the same problem. Looking for more detail in this answer.

    To elaborate on @MRAB's answer:

    Function ParseCSV(FileName)
        Dim Regex       'As VBScript_RegExp_55.RegExp
        Dim MatchColl   'As VBScript_RegExp_55.MatchCollection
        Dim Match       'As VBScript_RegExp_55.Match
        Dim FS          'As Scripting.FileSystemObject
        Dim Txt         'As Scripting.TextStream
        Dim CSVLine
        ReDim ToInsert(0)
    
        Set FS = CreateObject("Scripting.FileSystemObject")
        Set Txt = FS.OpenTextFile(FileName, 1, False, -2)
        Set Regex = CreateObject("VBScript.RegExp")
    
        Regex.Pattern = """[^""]*""|[^,]*"    '<- MRAB's answer
        Regex.Global = True
    
        Do While Not Txt.AtEndOfStream
            ReDim ToInsert(0)
            CSVLine = Txt.ReadLine
            For Each Match In Regex.Execute(CSVLine)
                If Match.Length > 0 Then
                    ReDim Preserve ToInsert(UBound(ToInsert) + 1)
                    ToInsert(UBound(ToInsert) - 1) = Match.Value
                End If
            Next
            InsertArrayIntoDatabase ToInsert
        Loop
        Txt.Close
    End Function
    

    You need to customize the InsertArrayIntoDatabase Sub for your own table. Mine has several text fields named f00, f01, etc...

    Sub InsertArrayIntoDatabase(a())
        Dim rs As DAO.Recordset
        Dim i, n
        Set rs = CurrentDb().TableDefs("tbl").OpenRecordset()
        rs.AddNew
        For i = LBound(a) To UBound(a)
            n = "f" & Format(i, "00") 'fields in table are f00, f01, f02, etc..
            rs.Fields(n) = a(i)
        Next
        rs.Update
    End Sub
    

    Note that instead of using CurrentDb() in InsertArrayIntoDatabase(), you should really use a global variable that gets set to the value of CurrentDb() before ParseCSV() runs, because running CurrentDb() in a loop is very slow, especially on a very large file.

提交回复
热议问题