- VBAでCSVファイルの値を取得するにはどうすればいいの?
- 読み込んだ値をシートに出力したい
- できるだけ処理を高速にしたい
そこで今回は、VBAでCSVファイルを読み込んでシートに転記する方法について紹介します。
配列も使ってできるだけ高速な処理になるように、また最低限の修正で済むように作ってあるので、コピペして使ってみてください。
VBAでCSVを読み込むサンプルコード
'対象ファイルフルパスを取得
Dim trgtFile As String
trgtFile = "C:\Sample\Sample.csv"
'読み込むCSVファイルの列数を指定
Dim maxNum As Long
maxNum = 4
'空番号を取得
Dim trgtNum As Long
trgtNum = FreeFile
Dim buf As String
Dim splitAry As Variant
Dim n As Long
Dim tmpAry As Variant
Dim trgtIndex As Long
'CSVファイルを読み込むために開く
Open trgtFile For Input As #trgtNum
'CSVファイルの終端までループ処理
Do Until EOF(trgtNum)
'CSVファイルの対象行を変数に格納
Line Input #trgtNum, buf
'格納した値を「","」で区切って配列に格納
splitAry = Split(buf, ",")
'結果を格納する配列の要素数を再定義
If IsArray(tmpAry) = False Then
ReDim tmpAry(1 To maxNum, 1 To 1) As Variant
Else
ReDim Preserve tmpAry(1 To maxNum, 1 To UBound(tmpAry, 2) + 1) As Variant
End If
trgtIndex = UBound(tmpAry, 2)
'CSVファイルから格納した1行分のデータの数だけループ処理
For n = LBound(splitAry) To UBound(splitAry)
tmpAry(n + 1, trgtIndex) = splitAry(n)
Next
Loop
'開いたCSVファイルを閉じる
Close #trgtNum
'貼り付け対象シートを定義
Dim trgtSh As Worksheet
Set trgtSh = ThisWorkbook.Worksheets("サンプル")
'貼り付け最終行を取得する
Dim pasteLastRow As Long
pasteLastRow = 1 + UBound(tmpAry, 2) - 1
Dim pasteLastCol As Long
pasteLastCol = 1 + maxNum - 1
'配列行列入れ替え(貼り付けの方向と合わせる)
tmpAry = WorksheetFunction.Transpose(tmpAry)
'貼り付け対象セル範囲に取得した値を転記
Dim trgtRng As Range
Set trgtRng = trgtSh.Range(trgtSh.Cells(1, 1), trgtSh.Cells(pasteLastRow, pasteLastCol))
trgtRng.Value = tmpAry
上記サンプルコードを実行すると「Sample.csv」が画像のデータを保持している時、「サンプル」シートに次のように値が転記されます。次に詳しい解説をしていきます。
VBAでCSVを読み込むコードの解説
'対象ファイルフルパスを取得
Dim trgtFile As String
trgtFile = "C:\Sample\Sample.csv"
'読み込むCSVファイルの列数を指定
Dim maxNum As Long
maxNum = 4
まず初めに、対象となるCSVファイルのフルパス「trgtFile」とCSVファイルデータの最大列数「maxNum」を定義しています。'空番号を取得
Dim trgtNum As Long
trgtNum = FreeFile
このあとの「Open」メソッド処理では、開く対象にファイル番号を指定する必要があります。このファイル番号は重複すると実行時エラーとなります。そこで重複しない番号を取得できる「FreeFile」関数を変数「trgtNum」に定義して、ファイル番号として使用します。
Dim buf As String
Dim splitAry As Variant
Dim n As Long
Dim tmpAry As Variant
Dim trgtIndex As Long
'CSVファイルを読み込むために開く
Open trgtFile For Input As #trgtNum
この後の処理で使用する各種変数「buf」「splitAry」「n」「indexCnt」「tmpAry」「trgtIndex」を宣言します。次に「Open」メソッドで「trgtFile」を読み込むため(「For Input」)に開きます。
- Open ファイルフルパス For 何のために開く As #ファイル番号
'CSVファイルの終端までループ処理
Do Until EOF(trgtNum)
'CSVファイルの対象行を変数に格納
Line Input #trgtNum, buf
ファイルを開いたら「Do Loop」を使って繰り返し処理を実行します。ここで繰り返し条件に使われている「EOF()」は「End Of File」の略で、引数に指定したファイル番号のテキストファイルが終端に到達した際に「True」を返します。次にファイル番号「trgtNum」のファイルを1行ずつ「Line Input」を使って「buf」に読み込んでいます。
- Line Input #ファイル番号, 変数
- テキストファイルから読み込まれたデータは「変数」に格納される
'格納した値を「","」で区切って配列に格納
splitAry = Split(buf, ",")
続いて「Line Input」によって「値,値2,値3,…」の形で1行分のデータが格納されている「buf」を「Split」関数で配列に変換し、変数「splitAry」に定義します。'結果を格納する配列の要素数を再定義
If IsArray(tmpAry) = False Then
ReDim tmpAry(1 To maxNum, 1 To 1) As Variant
Else
ReDim Preserve tmpAry(1 To maxNum, 1 To UBound(tmpAry, 2) + 1) As Variant
End If
「splitAry」を定義したら、次に読み込み結果全体を格納する配列「tmpAry」を再定義します。この時、1つ目の要素を格納する際には「tmpAry」が配列ではないので、「If」文を使って次のように処理しています。- 「tmpAry」が配列でない場合(1つ目の要素を格納する場合)
- 2次元方向の要素を「1 To 1」に再定義
- 「tmpAry」が配列の場合(2つ目以降の要素を格納する場合)
- 2次元方向の要素を「1 To UBound(tmpAry,2) + 1」に再定義
また、ここでは「tmpAry」が配列かどうかを判定するため「IsArray」関数を使用しています。
- IsArray(対象配列)
- 対象配列が配列なら「True」
- 対象配列が配列でなければ「False」
trgtIndex = UBound(tmpAry, 2)
値を格納する2次元方向のインデックスを「trgtIndex」に定義します。拡張した最後のインデックスを対象としたいので、最大インデックスを取得する「UBound」関数を使っています。 'CSVファイルから格納した1行分のデータの数だけループ処理
For n = LBound(splitAry) To UBound(splitAry)
tmpAry(n + 1, trgtIndex) = splitAry(n)
Next
Loop
'開いたCSVファイルを閉じる
Close #trgtNum
次に「For Next」を使ってCSVファイル1行分のデータを定義した配列「splitAry」の要素数分だけ繰り返し処理を実行します。この時「tmpAry」の1次元の対象インデックスは「n + 1」となります。
- 結果を格納する「tmpAry」の最小インデックスは「1」
- 「Split」関数を使って取得した「splitAry」の最小インデックスは「0 」 ⇒「tmpAry」の1次元の対象インデックスは「n + 1」
繰り返し処理「For Next」「Do Loop」が終わったら「Close #trgtNum」で対象のファイルを閉じます。
- Close #ファイル番号
'貼り付け対象シートを定義
Dim trgtSh As Worksheet
Set trgtSh = ThisWorkbook.Worksheets("サンプル")
'貼り付け最終行・列を取得する
Dim pasteLastRow As Long
pasteLastRow = 1 + UBound(tmpAry, 2) - 1
Dim pasteLastCol As Long
pasteLastCol = 1 + maxNum - 1
ここではまず、読込結果を書き込むシートを「trgtSh」に定義します。次に、貼り付ける最終行「pasteLatRow」を求めます。
- 最終行は「開始行 + 要素数 – 1」
- 要素数は列方向の最大インデックス「UBound(tmpAry, 2)」
- ※「tmpAry」とシートの行・列方向が反転しているため
⇒「pasteLastRow」は「1 + UBound(tmpAry, 2) – 1」
- 最終列は「開始列 + 要素数 – 1」
- 列方向の要素数は「maxNum」
- ※「maxNum」は読込ファイルの列方向要素数
⇒「pasteLastCol」は「1 + maxNum – 1」
'配列行列入れ替え(貼り付けの方向と合わせる)
tmpAry = WorksheetFunction.Transpose(tmpAry)
'貼り付け対象セル範囲に取得した値を転記
Dim trgtRng As Range
Set trgtRng = trgtSh.Range(trgtSh.Cells(1, 1), trgtSh.Cells(pasteLastRow, pasteLastCol))
trgtRng.Value = tmpAry
転記する前に配列とシートの行・列方向と合わせるため「Transpose」関数を使って「tmpAry」の行・列方向を反転します。最後に、事前に求めた最終行「pasteLastRow」と最終列「pasteLastCol」を使って、貼り付け対象セル範囲「trgtRng」を定義し、CSV読込結果を格納した配列「tmpAry」を転記します。
以上で、CSVファイルを読込、シートに転記することができました。
EOF関数について
サンプルコードで使用した「EOF」関数について紹介します。- 基本構文
EOF(対象ファイル番号)
- Findメソッドが返すのは「Rangeオブジェクト」
- ※「End Of File」の略
VBAでCSVを読み込む処理の応用
読み込み対象ファイルをファイルダイアログから選ぶ
読み込み対象ファイルをファイルダイアログから選択してシートに出力したい場合は「GetOpenFileName」を使いましょう。- 読込ファイルをファイルダイアログから選択したい場合は「GetOpenFileName」を使う
次のサンプルコードでは、選択したファイルのフルパスを返す「GetOpenFileName」で読み込み対象となるファイルパス「trgtFile」を取得しています。また、ファイルダイアログ上で「ファイル」が選択されなかった場合は、中断処理を行います。
- ファイルダイアログ上で「キャンセル」を押す
- ファイルダイアログ上で「×」を押す ⇒「GetOpenFileName」は「False」を返す
'対象ファイルフルパスを取得
Dim trgtFile As String
trgtFile = Application.GetOpenFileName("CSVファイル(*.csv), *.csv")
If trgtFile = False Then
End
End If
'以下冒頭サンプルコードと同様
'読み込むCSVファイルの列数を指定
Dim maxNum As Long
maxNum = 4
'空番号を取得
Dim trgtNum As Long
trgtNum = FreeFile
Dim buf As String
Dim splitAry As Variant
Dim n As Long
Dim tmpAry As Variant
Dim trgtIndex As Long
'CSVファイルを読み込むために開く
Open trgtFile For Input As #trgtNum
'CSVファイルの終端までループ処理
Do Until EOF(trgtNum)
'CSVファイルの対象行を変数に格納
Line Input #trgtNum, buf
'格納した値を「","」で区切って配列に格納
splitAry = Split(buf, ",")
'結果を格納する配列の要素数を再定義
If IsArray(tmpAry) = False Then
ReDim tmpAry(1 To maxNum, 1 To 1) As Variant
Else
ReDim Preserve tmpAry(1 To maxNum, 1 To UBound(tmpAry, 2) + 1) As Variant
End If
trgtIndex = UBound(tmpAry, 2)
'CSVファイルから格納した1行分のデータの数だけループ処理
For n = LBound(splitAry) To UBound(splitAry)
tmpAry(n + 1, trgtIndex) = splitAry(n)
Next
Loop
'開いたCSVファイルを閉じる
Close #trgtNum
'貼り付け対象シートを定義
Dim trgtSh As Worksheet
Set trgtSh = ThisWorkbook.Worksheets("サンプル")
'貼り付け最終行・列を取得する
Dim pasteLastRow As Long
pasteLastRow = 1 + UBound(tmpAry, 2) - 1
Dim pasteLastCol As Long
pasteLastCol = 1 + maxNum - 1
'配列行列入れ替え(貼り付けの方向と合わせる)
tmpAry = WorksheetFunction.Transpose(tmpAry)
'貼り付け対象セル範囲に取得した値を転記
Dim trgtRng As Range
Set trgtRng = trgtSh.Range(trgtSh.Cells(1, 1), trgtSh.Cells(pasteLastRow, pasteLastCol))
trgtRng.Value = tmpAry
「txt」ファイルを読み込む
紹介したCSVファイルを読み込むサンプルコードは「カンマ区切り(.csvファイル)」を前提とした方法です。「.txtファイル」を読み込む場合には、データが「カンマ区切り」なのかどうか確認する必要があります。
- 「.txtファイル」を読み込みたい場合は、データ形式をチェックする
'格納した値を「","」で区切って配列に格納
splitAry = Split(buf, ",")
- 「カンマ区切り」の場合
- splitAry = Split(buf, “,”)
- 「タブ区切り」の場合
- splitAry = Split(buf, vbTab)
VBAでCSVを読み込むまとめ
今回はVBAでCSVファイルを読み込んでシートに転記する方法と下記の応用について紹介しました。VBAでのテキストファイル読込の応用
できるだけ汎用性が高く、高速に処理できるように作っているので、まずはコピペして使ってみてください。- 読込ファイルをファイルダイアログから選択したい場合は「GetOpenFileName」を使う
- 対象ファイルが「タブ区切り」なら「”,”」ではなく「vbTab」でデータを区切る