VBAでCSVの一行を配列に格納します。
何故かVBAに無い「CSV文字列から配列への変換」
Microsoft Excel では、[データ]→[テキスト ファイル]と選んでいって、区切りをカンマにすることでCSVファイルを高速に Excel シートに読み込ませることができます。
この仕組みがVBAから利用できれば便利なのですが、そういう命令はありません。
関数を追加する
そこで、CSV文字列→配列変換をする関数を作成してみました。
VBAのエディタを開いたら、プロジェクト エクスプローラーで右クリック→[挿入]→[標準モジュール]として、以下を貼り付けてください。
[vb title=”fnvGetCSV.bas”]’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[/vb]
参考にしたサイトはありません。
使い方
VBAの中から関数として呼び出します。
パラメータには配列にしたいCSV文字列と、返却して欲しい配列名を指定します。
配列は「Dim 配列名() as String」として定義しておいてください。
[vb title=”test.bas”]’関数のテスト処理
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[/vb]
結果として配列に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
コメント