【安全なCSVエスケープ処理】ダブルクォーテーションやカンマを含む文字列の完全エスケープ関数
現場でVBScriptを使った業務自動化ツールを組んでいて、最も頻発するトラブルの一つが「CSV出力の崩壊」だ。
「ユーザーが備考欄にカンマ(`,`)や改行を入力したせいで、後続の集計システムが盛大にパースエラーを起こした」
「名前にダブルクォーテーション(`”`)が含まれていて、列のズレが連鎖した」
……このようなトラブルの連絡を、情報システム部のチャットで受け取るたびに頭を抱えてはいないだろうか?
安易に `Replace` 関数でカンマを置換したり、とりあえずダブルクォーテーションで囲むだけのいい加減な実装は、業務データを確実に破壊する。
今回は、RFC 4180(CSVの標準仕様)に完全に準拠し、エスケープ漏れやパフォーマンス低下を極限まで排除した「実務でそのまま使える完全版CSVエスケープ関数」を、プロのアーキテクトの知見を込めて伝授する。
—
なぜ「単純な置換」ではCSVが崩壊するのか?
多くの初学者がやりがちな実装を見てみよう。
‘ 【アンチパターン】絶対にやってはいけない例
Function BadEscape(str)
‘ カンマやダブルクォーテーションがあったらとりあえずダブルクォーテーションで囲む
Dim result
result = str
result = Replace(result, “”””, “”””””) ‘ ダブルクォーテーションのエスケープ忘れ
BadEscape = “””” & result & “”””
End Function
これの何が問題か?
1. ダブルクォーテーションのエスケープルール違反:RFC 4180では、フィールド内にダブルクォーテーションが存在する場合、それを2連続のダブルクォーテーション(`””`)に置換した上で、全体をさらにダブルクォーテーションで囲む必要がある。単にエスケープを忘れると、そこで文字列のクォートが閉じたと判定され、データが破損する。
2. 無駄な囲み処理:カンマも改行もダブルクォーテーションも含まない通常の文字列まで全てダブルクォーテーションで囲むと、出力ファイルの容量が無駄に肥大化し、Excel等で開いた際のデータ型判定にも悪影響を及ぼす。
3. 改行コードの混入:セル内改行(CRLFやLF)が含まれている場合、適切にダブルクォーテーションで括られていないと、行数が勝手に増殖してCSVの構造そのものが破壊される。
—
堅牢なCSVエスケープ関数の設計思想
プロダクション環境に投入するコードとして、以下の要件を満たす必要がある。
1. 条件付きクォーテーション:文字列内に「カンマ(`,`)」「ダブルクォーテーション(`”`)」「改行コード(`vbCr` または `vbLf`)」が含まれている場合のみ、全体をダブルクォーテーションで囲む。
2. 正確な文字置換:フィールド内のダブルクォーテーションは、必ず `””` にエスケープする。
3. VBScriptのメモリ効率を意識した実装:巨大なテキスト処理において、文字列結合演算子(`&`)の乱用はガベージコレクタに負荷をかける。必要最小限の処理ステップで構築する。
—
【コピペ即採用】RFC 4180完全準拠・エスケープ関数実装
以下のコードは、実務の現場でそのままモジュールとして組み込めるプロダクションコードだ。
Option Explicit
‘ ==============================================================================
‘ 処理概要: 指定された文字列をRFC 4180に準拠したCSV形式のフィールド値に変換する
‘ 引数 : ByVal strValue As String (変換前の文字列)
‘ 戻り値 : String (エスケープ済みのCSVフィールド文字列)
‘ ==============================================================================
Function EscapeCsvField(ByVal strValue)
‘ NullまたはEmptyの場合は空文字を返す
If IsNull(strValue) Then
EscapeCsvField = “”
Exit Function
End If
Dim targetStr
targetStr = CStr(strValue)
‘ フィールド内にエスケープ対象文字(カンマ、ダブルクォーテーション、改行)が含まれているか判定
If InStr(targetStr, “,”) > 0 Or _
InStr(targetStr, “”””) > 0 Or _
InStr(targetStr, vbCr) > 0 Or _
InStr(targetStr, vbLf) > 0 Then
‘ 1. ダブルクォーテーションは「2連続のダブルクォーテーション」に置換する
targetStr = Replace(targetStr, “”””, “”””””)
‘ 2. 全体をダブルクォーテーションで囲む
EscapeCsvField = “””” & targetStr & “”””
Else
‘ エスケープ対象が含まれない場合はそのまま返す(パフォーマンス最適化)
EscapeCsvField = targetStr
End If
End Function
—
実践:ファイル出力スクリプトへの組み込み方
作成したエスケープ関数を、実際のファイル書き込み処理(`ADODB.Stream` または `Scripting.FileSystemObject`)と組み合わせる実践的なサンプルを示す。文字コードは現代の標準である UTF-8 (BOM付き) を想定している。
Sub ExportDataToCsv()
Dim fso, stream
Dim filePath
filePath = “C:\Work\Output_Result.csv”
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ADODB.Streamを使用してUTF-8でファイルを出力する(文字化け防止の鉄則)
Set stream = CreateObject(“ADODB.Stream”)
stream.Type = 2 ‘ text
stream.Charset = “UTF-8”
stream.Open
‘ — ヘッダー行の書き込み —
stream.WriteText “ID,氏名,備考,登録日時” & vbCrLf
‘ — データ行の書き込み(ダミーデータ) —
Dim id, name, remarks, regDate
id = 101
name = “山田 太郎”
remarks = “通常データです。”
regDate = “2026-03-30 10:00:00”
‘ 各フィールドを関数に通してからカンマで結合
Dim line1
line1 = id & “,” & _
EscapeCsvField(name) & “,” & _
EscapeCsvField(remarks) & “,” & _
EscapeCsvField(regDate)
stream.WriteText line1 & vbCrLf
‘ 特殊文字(カンマ、ダブルクォーテーション、改行)を含む異常系データ例
id = 102
name = “鈴木, 次郎” ‘ カンマ含有
remarks = “「重要」案件につき、” & vbCrLf & “要確認のこと(“”A”ランク)” ‘ 改行・ダブルクォーテーション含有
regDate = “2026-03-30 11:30:00”
Dim line2
line2 = id & “,” & _
EscapeCsvField(name) & “,” & _
EscapeCsvField(remarks) & “,” & _
EscapeCsvField(regDate)
stream.WriteText line2 & vbCrLf
‘ ファイル保存とクリーンアップ
stream.SaveToFile filePath, 2 ‘ 2 = adSaveCreateOverWrite
stream.Close
Set stream = Nothing
Set fso = Nothing
WScript.Echo “CSV出力が正常に完了しました。”
End Sub
‘ スクリプトの実行
ExportDataToCsv()
—
開発現場のプロからのアドバイス:DB連携時の注意点
データベース(SQL ServerやOracleなど)から抽出したレコードセット(`ADODB.Recordset`)を直接CSVに吐き出すバッチを組む際も、この `EscapeCsvField` 関数を必ずフィールド値に対して通す習慣をつけてほしい。
特に注意すべきは以下の点だ:
- DB上のNULL値:VBScript上でDBの `Null` をそのまま文字列結合するとエラーになるか予期せぬ空文字(あるいは文字としての “Null”)になる。関数内で `IsNull` のガードを入れているため、データが欠損していても安全に空のフィールド(`,,`)として出力される。
- 改行コードの統一:Windows環境であれば `vbCrLf` で問題ないが、Linux等の別システムへ連携する場合は適宜 `vbLf` に置き換えるなどの配慮が必要になる。
「動けばいいや」で書かれた脆弱なコードは、データ量が膨れ上がった時や、ユーザーが意図しない特殊文字を入力した瞬間にシステムを沈黙させる。
このエスケープ関数をあなたのツールボックスの標準装備とし、堅牢でメンテナンスフリーな自動化基盤を築き上げてほしい。
