CSVファイルを二次元配列に変換する
CSVファイルの内容を二次元配列に変換する関数を紹介します。
二次元配列の他にも連想配列のDictinaryクラスやジャグ配列(配列に配列を入れる仕組み)を使う方法もあります。二次元配列と連想配列とジャグ配列のどれが良いかは用途によって異なります。ここで紹介する二次元配列はコードが単純で分かりやすい利点があり、連想配列は高速に動作する利点があり、ジャグ配列は配列の領域拡張とデータの登録が同時にできる利点があります。
連想配列(Dictionaryクラス)の使い方については「VBAのDictionaryの使い方(全メソッドとプロパティ網羅)」をご参照ください。
ジャグ配列での方法については「VBAでCSVファイルを二次元配列に格納する」をご参照ください。
参照設定
ファイル操作はFileSystemObjectにて行います。FileSystemObjectはツールメニュー→参照設定 で「Microsoft Scripting Runtime」にチェックを付けることでクラスオブジェクトとして利用できます。
前提条件
CSVファイルの列数が行ごとに異なる場合は、全ての行の中で最大の列数を二次元配列の列数とします。以下の3行のCSVファイルの場合は2行目の5列を最大列数とします。
CSVファイルの仕様として、ファイルの終端(最終行の右端)は改行コードがあってもなくてもどちらでもよい、というルールがあります。
ただ、このページのコードはファイルの終端には改行コード(CRLF)がある前提にしています。というのも、ファイル終端が改行コードかどうかをチェックするのはデータサイズが大きい場合に負荷がかかることと、先頭から読みだしていく必要があり処理が遅くなることから、ファイル終端には改行コードがある前提にしています。
そのため、以下の例であれば、3行目の右端には空行を入れて、ファイルの終端を改行コードにしてください。
1 2 3 |
1,2,3 1,2,3,4,5 1,2,3,4 |
サクラエディタの場合であればこのようになります。
CSVファイルを二次元配列に変換する関数
以下の関数は1つ目の引数のCSVファイルの内容を2つ目の引数の二次元配列に格納します。CSVファイルは参照のみ行い、更新はしません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
Sub CsvToArray(a_sFilePath, a_sArLine()) Dim oFS As New FileSystemObject '// FileSystemObjectインスタンス Dim oTS As TextStream '// TextStream変数 Dim sLine '// CSVファイルの行文字列 Dim iLineCount '// CSVファイル行数 Dim iCommaCount '// カンマ数 Dim v '// カンマ分割後の配列 Dim i '// ループカウンタ Dim iColumn '// 引数のファイルが存在しない場合は処理を終了する If (oFS.FileExists(a_sFilePath) = False) Then Exit Sub End If '// 最終行を取得するために追加モードで開く Set oTS = oFS.OpenTextFile(a_sFilePath, ForAppending) '// CSVファイルの行数を取得 iLineCount = oTS.Line - 1 Call oTS.Close '// TextStreamオブジェクト作成 Set oTS = oFS.OpenTextFile(a_sFilePath) i = 0 iCommaCount = 0 '// ファイルループ Do While oTS.AtEndOfStream <> True '// 1行読み込み sLine = oTS.ReadLine '// カンマで文字列を分割し配列化 v = Split(sLine, ",") '// 現在行をカンマで分割した数が今までより多い場合 If (iCommaCount < UBound(v)) Then '// 最大カンマ数を更新 iCommaCount = UBound(v) End If i = i + 1 Loop Call oTS.Close Erase a_sArLine ReDim a_sArLine(iLineCount - 1, iCommaCount) '// TextStreamオブジェクト作成 Set oTS = oFS.OpenTextFile(a_sFilePath) i = 0 '// ファイルループ Do While oTS.AtEndOfStream <> True '// 1行読み込み sLine = oTS.ReadLine '// カンマで文字列を分割し配列化 v = Split(sLine, ",") '// カンマ区切り配列をループ For iColumn = 0 To UBound(v) '// カンマ区切りの内容を二次元配列に格納 a_sArLine(i, iColumn) = v(iColumn) Next i = i + 1 Loop Call oTS.Close End Sub |
コード説明
この関数は4つの処理で構成されています。
- CSVファイル行数の取得する。
- CSVファイルから最大カンマ数を取得する。
- 二次元配列を1と2で取得した行数と最大カンマ数で領域確保する。
- CSVファイルを1行ずつカンマで分割して二次元配列に格納する。
1、2、3は二次元配列の領域確保のための処理です。4がCSVファイルを二次元配列に変換する実質的な本体処理です。
なぜこのようなことを行っているかと言うと、CSVファイルのループ中に二次元配列の領域をRedim Preserveで拡張すると、それまで格納したデータが消えてしまうというVBAの特性があるため、ループ中にRedim Preserveをする方法はせずに事前に必要な領域を確保しておくためです。
なお、CSVファイルの各行でカンマの数が異なる場合は、全ての列(二次元目)の要素数は2で取得した最大カンマ数になります。そのため、カンマの数が少ない行の二次元配列の値は何も設定されないため、配列の値はEmptyのままになります。説明だけでは分かりにくいので後述する関数の使い方の実行結果を参照してください。
1行目 | 1番目の引数にはCSVファイルのフルパスを指定します。2番目の引数には変換後の二次元配列を指定します。呼び出し元でDim xxx()の形で宣言していればOKです。 |
2~3行目 | ファイル操作用にFileSystemObjectクラスとTextStreamクラスを利用しています。前述していますが参照設定が必要です。 |
4~9行目 | 内部処理で使う変数です。7行目の変数vはSplit関数で配列になります。 |
12~14行目 | CSVファイルの存在チェックを行っています。存在しない場合は以降の処理をせずに終了します。 |
17~20行目 | 二次元配列の一次元目の要素数を特定するために、CSVファイルの行数を取得しています。追加モードでOpenTextFileメソッドを使うと書き込み位置がファイル終端に移動する特性を利用しています。ファイル行数の取得については他にも方法がありますので詳細は「VBAでファイルの行数を取得する」を参照ください。 |
23~44行目 | 二次元配列の二次元目の要素数を特定するために、CSVファイルの全行でカンマの数が一番多い行のカンマの数を取得しています。 |
46~47行目 | 引数の配列を消去し、そのあとで事前に取得したCSVファイルの行数と最大カンマ数から二次元配列の領域を確保しています。 |
50~70行目 | CSVファイルを先頭から終端までループし、1行ずつSplit関数でカンマ区切りの配列に変換し、その配列vの内容を1つずつ二次元配列に登録しています。 |
使い方
以下の3行(3行目の右端に改行コードを入れる)のCSVファイル(a.csv)を二次元配列に変換するサンプルです。呼び出し元では二次元配列の初期化は不要です。
1 2 3 |
1,2,3 1,2,3,4,5 1,2,3,4 |
利用サンプルソース
1 2 3 4 5 |
Sub CsvToArrayTest() Dim ar() Call CsvToArray("C:\web\test\a.csv", ar) End Sub |
実行結果