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
コメント