t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

VBA 2段階Splitの応用ワザ ~CSVファイルをレコード・フィールドに切り分ける。

以前、文字列を異なるデリミタで切り分けるテクニックを紹介した。
thom.hateblo.jp

直近でこのテクニックを利用したCSVファイルの処理を作成したのでメモしておく。

※今回はデータ中にカンマが無いシンプルなファイル処理とする。

一般的にはCSVをテキストファイルとして読み込む場合、一行ずつ読みながらカンマでSplitする。

コードにすると以下のようになる。
※FileSystemObjectとTextStreamを使用するには、あらかじめMicrosoft Scripting Runtimeを参照設定しておく必要がある。

Sub 一行ずつ読み込み()
    Dim FSO As New FileSystemObject
    Dim TS As TextStream
    Set TS = FSO.OpenTextFile("C:\work\sample.csv", ForReading, False)
    
    Dim Record As String
    Do Until TS.AtEndOfLine
        Record = TS.ReadLine
        Debug.Print Split(Record, ",")(0), Split(Record, ",")(2)
    Loop
    '処理の最後でファイルをクローズする。
    TS.Close
    Set TS = Nothing
    Set FSO = Nothing
End Sub

このコードで肝になるのは次の部分だ。

    Do Until TS.AtEndOfLine
        Record = TS.ReadLine
        Debug.Print Split(Record, ",")(0), Split(Record, ",")(2)
    Loop

和訳するとこんな感じ。

ファイルの最終行まで、
  Record = ファイルからの行読込
  表示 カンマで区切った0番目, カンマで区切った2番目
繰り返し

しかしこれだと、ファイルを一行ずつ読み込みながら処理をするので、処理が終わるまでファイルを開きっぱなしになる。
たとえ読み取り専用であっても、ファイルアクセス時間は短いほうが良い。

そこで冒頭で述べた、2段階Splitの出番だ。
以下のコードでは、TS.ReadAllでCSVを一気に読み取り、その場でSplitを使って動的配列に格納し、すぐにファイルをクローズしている。

Sub 一括読み込み()
    Dim FSO As New FileSystemObject
    Dim TS As TextStream
    Set TS = FSO.OpenTextFile("C:\work\sample.csv", ForReading, False)
    
    Dim Records() As String
    Records = Split(TS.ReadAll, vbLf)
    TS.Close    '一括読込後、すぐにファイルクローズできる。
    Set TS = Nothing
    Set FSO = Nothing
    
    For i = LBound(Records) To UBound(Records)
        If Records(i) <> "" Then
            Debug.Print Split(Records(i), ",")(0), Split(Records(i), ",")(2)
        End If
    Next
End Sub

そして動的配列RecordsをForループで回しながら、ひとつめのマクロと同じように出力している。

500レコードのCSVを用いて計測してみたとこ、一行ずつ読み取るマクロではファイルオープンの時間は約1.6秒、一括読み込みの場合は0.017秒だった。
デバッグプリントが時間を食うので総合的には同じくらいであるが、後者の方法だとファイルをつかんでいる時間が圧倒的に短くなるので、拘る方は活用してみてほしい。

※今回のCSVはたまたま改行コードがLFだったのでvbLfでSplitしているが、CSVを作成した環境で変わるので注意。
改行コードについては以下の記事を参照
thom.hateblo.jp

また、時間の計測については以下の記事を参照
thom.hateblo.jp

以上。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。