VBAでCSV解析を実践するための記法とレールロード図

VBAでCSV解析を実践するための記法とレールロード図

Copyright © 2026 LWP 山中 一弘

本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。

記事要約

CSV解析を実装するには、コードを書く前にCSVの記法を理解する必要があります。

CSVはテキストファイルですが、実際にはバイト列として保存されています。改行、カンマ、ダブルクオート、EOF、セル内改行をどう見るかを整理しないまま実装すると、すぐに壊れます。

この記事では、VBAによるCSV解析実践のために、記法、CR/LF、DQ、論理行、ABNF、レールロード図を整理します。

本記事の対象とゴール

  • VBAでCSV解析を学びたい人

  • CSVを Split で処理して失敗したことがある人

  • テキスト解析の基礎としてCSVを題材にしたい人

先に結論

CSV解析の入口で学ぶべきことは、次の5つです。

  1. CSVファイルはバイトストリームである

  2. CR、LF、CRLFを文字として意識する

  3. ダブルクオートはフィールドを引用する記号である

  4. フィールド内改行を扱うには、物理行と論理行を分ける必要がある

  5. RFC4180のABNFを、VBAで扱いやすいレールロード図や状態遷移へ変換する

<!-- LWP_REWRITE_EXPANSION_記事110 -->

1. 記法は実装の前に必要である

CSV解析のように分岐が多い処理では、いきなりコードを書くと全体像を失います。先に、どの文字で状態が変わるのか、どの状態でどの文字を許すのかを記法として整理します。

レールロード図や状態遷移表は、そのための道具です。実装者だけでなく、後から読む人が仕様を確認できる形になります。

2. レールロード図で入口と出口を見る

レールロード図は、構文の通り道を図として表します。CSVなら、レコード、フィールド、引用符付きフィールド、通常フィールドを分けて見ることができます。

図にすると、許される入力と許されない入力が見えます。たとえば、引用符を閉じた後に文字が続く場合を許すのか、エラーにするのかを明確にできます。

3. VBA実装へ落とす

図や表で整理したら、VBAでは状態、現在文字、出力バッファ、フィールド一覧、レコード一覧へ分けます。1文字ずつ読み、状態に応じて処理します。

ここで大切なのは、パーサーの中に業務処理を混ぜないことです。CSVを解析する処理はCSVだけを扱い、社員番号や金額などの業務判断は解析後に行います。

CSVはバイトストリームである

CSVを説明するとき、画面上では行ごとに折り返して書きます。

しかし、実際のCSVファイルは、文字が順番に並んだバイトストリームです。

abc,def,ghe CRLF
aaa,bbb,ccc CRLF

このように見せると分かりやすいですが、実際には CRLF もファイル内に現れる文字列、または文字コード上の制御文字です。

CSV解析では、「目で見た行」と「データとしての改行」を分けて考える必要があります。

EOFと番兵

ファイル終端は、実際に EOF という文字が入っているわけではありません。

ファイルを読み込んだときに、もう読むものがないことを示す印として扱います。

このような印を番兵と呼びます。

CSV解析のコードでは、実際のデータと重ならない値を終端として使うと、ループが書きやすくなります。

今回の素材では、文字列バッファ全体を読み込んだ後の終端として EOT を置く話が出ていました。ただし、ASCII上の EOT は 0x04、ETX は 0x03 なので、コード上の名前は注意が必要です。

引用されるフィールドと引用されないフィールド

CSVのフィールドは、引用されていても、引用されていなくても構いません。

abc
"abc"

解析結果としては、どちらも abc です。

ただし、フィールド内にカンマ、改行、ダブルクオートが含まれる場合は、ダブルクオートで囲む必要があります。

"a,b"
"a
b"
"a""b"

VBAでは文字列リテラルにもダブルクオートを使うため、CSV上のダブルクオートとVBAコード上のダブルクオートが混ざって見えます。

ここは、CSVの記号としての DQUOTE と、VBA文字列としての " を分けて考える必要があります。

セル内改行と論理行

Excelでは、セル内改行を含むセルがあります。

このセルをCSVとして出力すると、フィールド内に改行が含まれます。

"hoe
hoe",123

このとき、物理的には複数行に見えます。しかしCSVとしては1つのレコードです。

ここで重要になるのが、物理行と論理行の区別です。

  • 物理行: ファイル上で改行文字によって区切られて見える行

  • 論理行: CSVレコードとしての1行

フィールド内改行があると、物理的な複数行が、CSVから見れば1つの論理行になります。

DQの数で継続を判断する

CSVでセル内改行を扱う代表的な方法の一つは、ダブルクオートの数を見ることです。

ダブルクオートの数が奇数なら、まだ引用フィールドが閉じていない可能性があります。次の物理行を読み足して、論理行を完成させます。

1行目: "abc
2行目: def",123

1行目だけでは、ダブルクオートが閉じていません。2行目まで読むと閉じます。

ただし、2つ並んだダブルクオート "" は、フィールド内の1つのダブルクオートを表します。この扱いも必要です。

RFC4180のABNFを見る

RFC4180では、CSVの構造がABNFで示されています。

file = [header CRLF] record *(CRLF record) [CRLF]
header = name *(COMMA name)
record = field *(COMMA field)
name = field
field = (escaped / non-escaped)
escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE
non-escaped = *TEXTDATA
COMMA = %x2C
CR = %x0D
DQUOTE = %x22
LF = %x0A
CRLF = CR LF
TEXTDATA = %x20-21 / %x23-2B / %x2D-7E

この定義から、次のことが分かります。

  • ヘッダは任意

  • 最後のCRLFは任意

  • レコードはフィールドの並び

  • フィールドは引用あり、引用なしのどちらか

  • 引用フィールドの中では、カンマやCR/LFをデータとして扱える

レールロード図へ落とす

ABNFは正確ですが、実装を考えるには読みづらいことがあります。

そこで、レールロード図や状態遷移図へ落とします。

素材画像では、ABNFを読み解きながら、右側にトップレベルのレールロード図を書いていました。特に、最後の CRLF が任意であることが重要です。

最後のレコードは、次のどちらでもよいということです。

abc CRLF EOF
abc EOF

この違いを考慮しないと、最後の1レコードを取りこぼす実装になります。

2つの実装方針

素材では、セル内改行対策として大きく2つの方法が示されていました。

1つ目は、ダブルクオートの数を数え、奇数であれば物理行が継続しているとみなし、ダブルクオートが閉じるまで読み足してから1つの論理行にまとめる方法です。

2つ目は、物理行を先にまとめず、読み進めながらダブルクオートの数や状態で継続を判断する方法です。

前者は理解しやすく、後者は解析器として自然です。

どちらを選ぶにしても、「見た目の行」と「CSVとしてのレコード」を分けて考えることが重要です。

まとめ

CSV解析は、カンマで分割する処理ではありません。

CSVを正しく扱うには、CR、LF、CRLF、ダブルクオート、フィールド内改行、最後のCRLF省略、EOFを理解する必要があります。

RFC4180のABNFは正確な出発点です。ただし、VBAで実装するには、ABNFをそのまま読むだけでなく、レールロード図や状態遷移へ変換すると分かりやすくなります。

CSV解析は、CSVだけの話ではありません。

テキストを読み、記号を認識し、状態を持ちながら解釈するという、すべてのテキスト解析の基礎になります。

出典メモ- 元Posfie URL: https://posfie.com/@hoehoe1234/p/0fVQeIy

  • 元Posfieタイトル: 2022-03-27 個別指導 VBAによるCSVの解析実践編

  • 投稿者: hoehoe1234

  • 投稿数: 24

  • 画像確認: 画像9点を取得し、記事化時に内容を確認

  • 取得・確認日: 2026-06-11

画像・他者投稿として確認した主な投稿:

  • @hoehoe1234 2022-03-28 13:41:34: https://x.com/hoehoe1234/status/1508303259731382272

  • @hoehoe1234 2022-03-28 13:57:02: https://x.com/hoehoe1234/status/1508307153115058178

  • @hoehoe1234 2022-03-28 14:08:25: https://x.com/hoehoe1234/status/1508310015752679427

  • @hoehoe1234 2022-03-28 14:20:45: https://x.com/hoehoe1234/status/1508313118786859011

  • @hoehoe1234 2022-03-28 14:27:06: https://x.com/hoehoe1234/status/1508314716892205062

  • @hoehoe1234 2022-03-28 14:34:33: https://x.com/hoehoe1234/status/1508316593126002691

  • @hoehoe1234 2022-03-28 14:47:46: https://x.com/hoehoe1234/status/1508319917464244229

  • @hoehoe1234 2022-03-28 14:50:12: https://x.com/hoehoe1234/status/1508320530679869442

  • @hoehoe1234 2022-03-28 14:55:29: https://x.com/hoehoe1234/status/1508321862128128001

  • 参考: RFC 4180 Common Format and MIME Type for CSV Files, https://www.rfc-editor.org/rfc/rfc4180