【ExcelVBA】CSVファイルを読み込む方法

仕事効率化
スポンサーリンク

  • 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」が画像のデータを保持している時、「サンプル」シートに次のように値が転記されます。
01-VBACSVファイル読み込み結果イメージ 次に詳しい解説をしていきます。

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」を返します。
02-VBACSVファイル読み込みEOFイメージ
次にファイル番号「trgtNum」のファイルを1行ずつ「Line Input」を使って「buf」に読み込んでいます。
  • Line Input #ファイル番号, 変数
  • テキストファイルから読み込まれたデータは「変数」に格納される
'格納した値を「","」で区切って配列に格納
splitAry = Split(buf, ",")
続いて「Line Input」によって「値,値2,値3,…」の形で1行分のデータが格納されている「buf」を「Split」関数で配列に変換し、変数「splitAry」に定義します。
03-VBACSVファイル読み込みSplitイメージ
'結果を格納する配列の要素数を再定義
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」に再定義
これで、要素を格納する度に、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」
「splitAry」の要素数(4回)の「For Next」処理を実行した後、「tmpAry」の要素は画像のようになります。
04-VBACSVファイル読み込み結果配列イメージ
繰り返し処理「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」
同様に、最終列「pasteLastCol」を求めます。
  • 最終列は「開始列 + 要素数 – 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」関数について紹介します。
  1. 基本構文
EOF(対象ファイル番号)
  • Findメソッドが返すのは「Rangeオブジェクト」
  • ※「End Of File」の略
05-VBACSVファイル読み込みEOFイメージ

VBAでCSVを読み込む処理の応用

読み込み対象ファイルをファイルダイアログから選ぶ

読み込み対象ファイルをファイルダイアログから選択してシートに出力したい場合は「GetOpenFileName」を使いましょう。
06-VBACSVファイル読み込みファイルダイアログ選択イメージ
  • 読込ファイルをファイルダイアログから選択したい場合は「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」でデータを区切る
できるだけ汎用性が高く、高速に処理できるように作っているので、まずはコピペして使ってみてください。