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

今度は単純なテキストファイルではなく、CSV形式テキストファイルを読み込みます。
CSV形式テキストファイルって? このページをご覧になる方には説明は不要だとは思いますが、初心者の方の中で誤解されているケースを見ることがあるので、少し説明しておきます。
ここで説明する「誤解」とは「CSV形式テキストファイル」がExcel専用のファイルだと考えている人がいることと、 「CSV形式テキストファイル」のファイル形式が単一で揺るぎない「規格」だと思っている人がいるという、この2点です。



1点目については、むしろ、他のシステムで作成されたデータをExcelに取り込んだり、逆にExcelで作成したデータを他のシステムに引き渡すようなインタフェースとしての役割りを担うことが多いデータ形式なのです。



2点目は結構多くの方が誤解されていることですが、「CSV形式テキストファイル」のデータ形式の原則は、「項目間をカンマで区切る」ということだけなのです。 拡張子が「CSV」なら良いわけでもないし、文字列項目がダブルクォーテーションで囲われているかどうか、とか、日付項目が「#」で囲われているかどうかとか、 さらには、改行コードがCRLFなのか、ということも結構「あいまい」なものです。



その割にはシステム間のデータ受け渡しには頻繁に利用されているわけですが、利用する場合は、このような細かい点まで取り決めておくことが必要です。
よく問題になるのは、文字列の1項目内にカンマが文字として混在しているとか、文字列の1項目内に改行があるなどです。



今度は、CSV形式テキストデータのファイルの読み込みのサンプルです。
ここでのサンプルは、CSV形式テキストデータが5項目(5つのフィールドのデータが4つのカンマで区切られている)ことを前提としています。
I/Oの方式は前ページの上半分の「古くからあるステートメント」の方法と同じです。
動作確認をされる場合は、Ascii(シフトJIS漢字)コードによるCSV形式テキストファイルを指定して下さい。

'***************************************************************************************************
'   CSV形式テキストファイル読み込みサンプル                         Module1(Module)
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/07/25(1.00)新規作成
'03/12/04(1.01)初回修正
'20/02/26(1.10)*.xlsm化、他
'***************************************************************************************************
Option Explicit
'===================================================================================================
Private Const g_cnsTitle As String = "CSVテキストファイル読み込み"
Private Const g_cnsFilter As String = "CSV形式ファイル (*.csv),*.csv,全てのファイル(*.*),*.*"

'***************************************************************************************************
'   ■■■ ワークシート側からの呼び出し処理 ■■■
'***************************************************************************************************
'* 処理名 :READ_CsvFile1
'* 機能  :CSVテキストファイル読み込みサンプル
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年07月25日
'* 作成者 :井上 治
'* 更新日 :2020年02月26日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:サンプルなのでエラー処理は行なっていません
'***************************************************************************************************
Sub READ_CsvFile1()
    '-----------------------------------------------------------------------------------------------
    Dim intFF As Integer                                            ' FreeFile値
    Dim lngRow As Long                                              ' 収容するセルの行
    Dim lngRec As Long                                              ' レコード件数カウンタ
    Dim strFileName As String                                       ' OPENするファイル名(フルパス)
    Dim vntFileName As Variant                                      ' ファイル名受取り用
    Dim tblFld(1 To 5) As Variant                                   ' 読み込んだレコード内容
    '-----------------------------------------------------------------
    ' @「ファイルを開く」のダイアログでファイル名の指定を受ける
    Application.StatusBar = "読み込むファイル名を指定して下さい。"
    vntFileName = Application.GetOpenFilename(FileFilter:=g_cnsFilter, Title:=g_cnsTitle)
    ' キャンセルされた場合はFalseが返るので以降の処理は行なわない
    If VarType(vntFileName) = vbBoolean Then Exit Sub
    strFileName = vntFileName
    '-----------------------------------------------------------------
    ' AFreeFile値の取得(以降この値で入出力する)
    intFF = FreeFile
    ' 指定ファイルをOPEN(入力モード)
    Open strFileName For Input As #intFF
    ' 先頭行の設定(2行目から掻き出すので1とする)
    lngRow = 1
    '-----------------------------------------------------------------
    ' BファイルのEOF(End of File)まで繰り返す
    Do Until EOF(intFF)
        ' レコード件数カウンタの加算
        lngRec = lngRec + 1
        Application.StatusBar = "読み込み中です....(" & lngRec & "レコード目)"
        ' レコードを読み込む(このサンプルは5項目のCSV)
        Input #intFF, tblFld(1), tblFld(2), tblFld(3), tblFld(4), tblFld(5)
        ' 行を加算(先頭は2行目)
        lngRow = lngRow + 1
        ' A〜E列にレコード内容を配列渡し
        Range(Cells(lngRow, 1), Cells(lngRow, 5)).Value = tblFld
    Loop
    '-----------------------------------------------------------------
    ' C指定ファイルをCLOSE
    Close #intFF
    Application.StatusBar = False
    ' 終了の表示
    MsgBox "ファイル読み込みが完了しました。" & vbCr & _
        "レコード件数=" & lngRec & "件", vbInformation, g_cnsTitle
End Sub

'----------------------------------------<< End of Source >>----------------------------------------
(こちらをクリックすると、このサンプルがダウンロードできます)



ソースコードの線で囲って丸数字をコメントで書き込んだ4つのブロックについて概略を説明します。

処理工程概要
@ 開くファイル名の受け取り部分です。前頁「古くからあるステートメント」と同じです。
ここでは「ファイルを開く」ダイアログを表示させてユーザーにファイル名を指定してもらっています。
プログラム内で決まっているのであればこの工程はなくして定数でも構いません。
A [前処理]として、指定のテキストファイルを開く処理です。前頁「古くからあるステートメント」と同じです。
Openステートメント」では、「As #nn」のnnのところに「ファイルナンバー」を指定します。
新規OPENの場合は空き番号ですが、通常は他にOPEN中のファイルがなければ「1」になります。 ですが、例えば前回の処理で実行時エラー等でOPENしたままだとすると「1」は使用中ということになります。
ここで「ファイルナンバー」を「FreeFile関数」から受け取るようにすれば空き番号を割り当ててくれます。
B [主処理]として、実際にファイルをEOF(End of File)まで読み込むループです。
ループ内では「Inputステートメント」でCSV5項目分を5個の変数に格納します。
読み込んだ内容はこのサンプルでは1行の5セルに一括で転記しています。
C [後処理]として、ファイルをCLOSEして、 終了メッセージを表示しています。前頁「古くからあるステートメント」と同じです。
(4つ先のCSV形式テキストデータの書き出し」を先に実行してもらうとサンプルデータが作成されるので、動作確認ができます。)