CSV形式テキストデータの読み込み

今度は単純なテキストファイルではなく、CSV形式テキストファイルを読み込みます。
CSV形式テキストファイルって? このページをご覧になる方には説明は不要だとは思いますが、初心者の方の中で誤解されているケースを見ることがあるので、少し説明しておきます。
ここで説明する「誤解」とは「CSV形式テキストファイル」がExcel専用のファイルだと考えている人がいることと、 「CSV形式テキストファイル」のファイル形式が単一で揺るぎない規格だと思っている人がいるという、この2点です。
1点目については、むしろ、他のシステムで作成されたデータをExcelに取り込んだり、逆にExcelで作成したデータを他のシステムに引き渡すようなインタフェースとしての役割りを担うことが多いデータ形式なのです。
2点目は結構多くの方が誤解されていることですが、「CSV形式テキストファイル」のデータ形式の原則は、「項目間をカンマで区切る」ということだけなのです。 拡張子が「CSV」なら良いわけでもないし、文字列項目がダブルクォーテーションで囲われているかどうか、とか、日付項目が「#」で囲われているかどうかとか、 さらには、改行コードがCRLFなのか、ということも結構「あいまい」なものです。
システム間の受け渡しに利用する場合は、このような細かい点まで取り決めておくことが必要です。
今度は、CSV形式テキストデータのファイルの読み込みのサンプルです。
ここでのサンプルは、CSV形式テキストデータが5項目(5つのフィールドのデータが4つのカンマで区切られている)ことを前提としています。

Option Explicit

' CSV形式テキストファイル(5カラム)読み込みサンプル
Sub READ_TextFile()
    Const cnsTITLE = "テキストファイル読み込み処理"
    Const cnsFILTER = "CSV形式ファイル (*.csv),*.csv,全てのファイル(*.*),*.*"
    Dim xlAPP As Application        ' Applicationオブジェクト
    Dim intFF As Integer            ' FreeFile値
    Dim strFileName As String       ' OPENするファイル名(フルパス)
    Dim vntFileName As Variant      ' ファイル名受取り用
    Dim X(1 To 5) As Variant        ' 読み込んだレコード内容        ' @
    Dim GYO As Long                 ' 収容するセルの行
    Dim lngREC As Long              ' レコード件数カウンタ

    ' Applicationオブジェクト取得
    Set xlAPP = Application
    ' 「ファイルを開く」のフォームでファイル名の指定を受ける
    xlAPP.StatusBar = "読み込むファイル名を指定して下さい。"
    vntFileName = xlAPP.GetOpenFilename(FileFilter:=cnsFILTER, _
                                        Title:=cnsTITLE)
    ' キャンセルされた場合はFalseが返るので以降の処理は行なわない
    If VarType(vntFileName) = vbBoolean Then Exit Sub
    strFileName = vntFileName

    ' FreeFile値の取得(以降この値で入出力する)
    intFF = FreeFile
    ' 指定ファイルをOPEN(入力モード)
    Open strFileName For Input As #intFF
    GYO = 1
    ' ファイルのEOF(End of File)まで繰り返す
    Do Until EOF(intFF)
        ' レコード件数カウンタの加算
        lngREC = lngREC + 1
        xlAPP.StatusBar = "読み込み中です....(" & lngREC & "レコード目)"
        ' レコードを読み込む(このサンプルは5項目のCSV)
        Input #intFF, X(1), X(2), X(3), X(4), X(5)                  ' A
        ' 行を加算しA〜E列にレコード内容を表示(先頭は2行目)
        GYO = GYO + 1
        Range(Cells(GYO, 1), Cells(GYO, 5)).Value = X   ' 配列渡し  ' B
    Loop
    ' 指定ファイルをCLOSE
    Close #intFF
    xlAPP.StatusBar = False
    ' 終了の表示
    MsgBox "ファイル読み込みが完了しました。" & vbCr & _
        "レコード件数=" & lngREC & "件", vbInformation, cnsTITLE
End Sub
(こちらをクリックすると、このサンプルがダウンロードできます)
CSV形式テキストデータに特化したところ以外は、前項の「テキストデータの読み込み」と同じです。(2つ先のCSV形式テキストデータの書き出し」を先に実行してもらうと、簡単なデータが作成されるので、このサンプルで読み込んでみることができます。)

@
変数はCSVの項目数分作成する必要があります。ここではテーブルとしています。Variant型にしているのは、読み込んで収容する値に応じたデータ型になる利点を利用するためです。
A
レコードの読み込みはInputステートメントで行ないます。ファイル番号の次からがレコードデータを格納する変数で項目数がレコード上の項目数と合っていないとレコードずれを起こします。
なお、レコード右端改行位置にはカンマは必要ありません。
※項目の属性が一定していない(数値になったり文字になったりする)場合は、Inputメソッドの前に配列の初期化(Erase X)の行を追加して下さい。XはVariantとしているので、セットする値によって属性のふるまいが変わります。
B
A〜Eの5列のセルに5項目のテーブルを転記するのは、このように配列全体を1行で渡すこともできます。通常は、カラムを変数にして1から5までをループさせて1セルずつ渡します。

※CSV形式テキストファイルとはどのようなファイルでしょうか。
CSV(Comma Separated Value)ということで、項目間をカンマで区切ったテキストファイルのことを指します。
但し、「CSV形式テキストファイル」なら全て同じというわけではありません。
下記のような事象があります。
@
文字列項目は両端がダブルクォーテーションで囲われている。
A
文字列項目は両端がシングルクォーテーションで囲われている。
B
文字列項目でも両端がダブルクォーテーションやシングルクォーテーションで囲われていない。
C
文字列項目は両端がダブルクォーテーションで囲われているが、その文字列中にカンマが存在する。
D
行ごとにカンマの数(つまり項目数)が一定していない。
E
途中にブランク行が許されている。また、行によりカンマの数(つまり項目数)が一定でない。
F
改行コードがCR+LFでない。(UNIX系システムではLFのみの場合がある)
G
一番ひどい例では、文字列項目の途中に改行(CRLF)が含まれている。

ここでサンプルとして挙げている方法は、MS-DOS時代からの方法であり、現在のような「野放図」になってしまったCSV形式ファイルには対応できません。
読み込み処理を作成する場合は、単に「CSV形式ファイル」で鵜呑みにせず内容をよく確認する必要があります。
ここに挙げているサンプルで読み込める「CSV形式ファイル」は以下のような仕様(約束事)になります。

@
項目数が5項目としているので、カンマはその間の4つ。どの行も同様。(ブランク行不可)
項目数(カンマ数)が合っていないと、シートに展開した結果が行を追うごとにズレていきます。
A
文字列両端のダブルクォーテーションは無くても良いが、文字列途中にカンマやダブルクォーテーション、シングルクォーテーション、改行(CRLF)が含まれないこと。
不正セパレータがデータに含まれていると、その行から後ろ全てがズレていきます。
B
改行コードがCR+LF。最終行にも改行コードがあること。
ファイルに使用されている改行コードがCR+LFでない場合は、1行目しか表示されなかったり、メモリオーバーとなったりします。
※このサンプルのようなコードで使用するCSV形式テキストデータは各行の項目数が全て5項目(つまりカンマが4つ)で統制が取れているものに限ります。
※カンマ数が不定(一定していない)の場合は、次ページの方法(行単位に読み込んでからカンマ位置で分解する方法)も参照して下さい。