VBAでCSVの一行を配列に格納する

VBA
この記事は約9分で読めます。

VBAでCSVの一行を配列に格納します。

何故かVBAに無い「CSV文字列から配列への変換」

Microsoft Excel では、[データ]→[テキスト ファイル]と選んでいって、区切りをカンマにすることでCSVファイルを高速に Excel シートに読み込ませることができます。

この仕組みがVBAから利用できれば便利なのですが、そういう命令はありません。

関数を追加する

そこで、CSV文字列→配列変換をする関数を作成してみました。

VBAのエディタを開いたら、プロジェクト エクスプローラーで右クリック→[挿入]→[標準モジュール]として、以下を貼り付けてください。

'fncGetCSV ver1.2
Function fncGetCSV(Record As String, Table() As String) As Long
    Dim lngCol          As Long
    Dim lngCol2         As Long
    Dim lngLocate       As Long
    Dim lngLen          As Long
    Dim lngLenAll       As Long
    Dim strRec          As String
    Dim strTest         As String
    Dim strTest2        As String
    Dim strValue        As String
    Dim blnQuote        As Boolean
    Dim blnComma        As Boolean
    Dim blnSeparate     As Boolean
    Dim lngInStr        As Long
    Dim lngInStr2       As Long
    
    lngCol = 0
    lngCol2 = 1
    ReDim Table(1 To lngCol2)
    
    lngLocate = 1
    strRec = Record
    lngLen = Len(strRec)
    lngLenAll = lngLen
    
    blnQuote = False
    
    While (lngLen <> 0)
        strTest = Mid$(strRec, lngLocate, 1)
        If (strTest = """") Then
            If (blnQuote) Then
                strTest2 = Mid$(strRec, lngLocate, 2)
                If (strTest2 = """""") Then
                    strValue = strValue & """"
                    lngLocate = lngLocate + 2
                    lngLen = lngLen - 2
                Else
                    blnQuote = False
                    lngLocate = lngLocate + 1
                    lngLen = lngLen - 1
                End If
            Else
                blnQuote = True
                lngLocate = lngLocate + 1
                lngLen = lngLen - 1
            End If
        Else
            If (blnQuote) Then
                lngInStr = InStr(lngLocate, strRec, """")
                If (lngInStr = 0) Then
                    strValue = strValue & Mid$(strRec, lngLocate)
                    lngLen = 0
                    blnSeparate = True
                Else
                    strValue = strValue & Mid$(strRec, lngLocate, lngInStr - lngLocate)
                    lngLocate = lngInStr
                    lngLen = lngLen + lngInStr - lngLocate
                End If
            Else
                lngInStr = InStr(lngLocate, strRec, ",")
                lngInStr2 = InStr(lngLocate, strRec, """")
                If (lngInStr2 > 0) And (lngInStr2 < lngInStr) Then
                    strValue = strValue & Mid$(strRec, lngLocate, lngInStr2 - lngLocate)
                    lngLen = lngLenAll - lngInStr2 + 1
                    lngLocate = lngInStr2
                Else
                    If (lngInStr = 0) Then
                        strValue = strValue & Mid$(strRec, lngLocate)
                        lngLen = 0
                    Else
                        strValue = strValue & Mid$(strRec, lngLocate, lngInStr - lngLocate)
                        lngLen = lngLenAll - lngInStr
                        lngLocate = lngInStr + 1
                        lngCol2 = lngCol2 + 1
                        blnComma = True
                    End If
                    blnSeparate = True
                End If
            End If
            If (blnSeparate) Then
                lngCol = lngCol + 1
                ReDim Preserve Table(1 To lngCol)
                Table(lngCol) = strValue
                strValue = ""
                blnQuote = False
                blnSeparate = False
            End If
        End If
    Wend
    If (lngCol <> lngCol2) Then
        ReDim Preserve Table(1 To lngCol2)
    End If
    fncGetCSV = lngCol2
End Function

参考にしたサイトはありません。

使い方

VBAの中から関数として呼び出します。

パラメータには配列にしたいCSV文字列と、返却して欲しい配列名を指定します。

配列は「Dim 配列名() as String」として定義しておいてください。

'関数のテスト処理
Sub Main()
    Dim i               As Long
    Dim strInputData    As String
    Dim arrCSV()        As String
    Dim lngCol          As Long
    
    strInputData = "test,""te""""st,""test,te""st,"
    
    lngCol = fncGetCSV(strInputData, arrCSV)
    
    Debug.Print "元データ=" & strInputData
    If (lngCol > 0) Then
        For i = LBound(arrCSV) To UBound(arrCSV)
            Debug.Print i & "=" & arrCSV(i)
        Next i
    End If
End Sub

結果として配列にCSVを分解した文字列が入ってきます。

通常は LINE INPUT や adReadLine で読み込んできた行を入力にする感じだと思います。

ルール

” (ダブルクォート)が来たあとは、特殊な文字列の開始となります。

この間は、カンマが来ても文字として扱い、項目の区切りにはなりません。

“” (ダブルクォート2文字)が文字の「”」(ダブルクォート)と判定されます。

” (ダブルクォート)が1つだけ来た場合、特殊な文字列の終了となります。

入力 結果
配列(0) 配列(1) 配列(2) 配列(3)
“te,st,”,test te,st, test
“te””st””,test te”st test
te”st,test,”test test,testtest

では、この辺で。(^-^)o

コメント

タイトルとURLをコピーしました