Excel VBAでCSVファイルを扱う基本と実践
音声
目次
CSVファイルを開く方法(Workbooks.Open、QueryTables)
目的に応じて使い分けます。単にブックとして開くなら Workbooks.Open/OpenText を使い、取り込み時に区切り文字・列型・文字コードを細かく指定したいなら QueryTables が有利です。例(OpenText の最小例)です。
Workbooks.OpenText Filename:="C:\Temp\sample.csv", Origin:=65001, _
DataType:=xlDelimited, Comma:=True
実行は標準モジュールに貼り付け、VBE で F5 します。表示が期待通りか A1 などで確認します。
CSVファイルの書き出し(SaveAs xlCSV)
Workbook.SaveAs で CSV を出力できます。アクティブブックを上書きしたくない場合は、シートをコピーして新規ブックとして保存するのが安全です。Excel のバージョンによっては UTF-8 出力向けに xlCSVUTF8 を利用できます。最小例は次のとおりです。
ActiveSheet.Copy
ActiveWorkbook.SaveAs Filename:="C:\Temp\out.csv", FileFormat:=xlCSV
ActiveWorkbook.Close SaveChanges:=False
数値や先頭ゼロなどは、セルをテキスト形式にしてから保存すると期待どおりになりやすいです。
文字コードの問題と対処法
日本語の文字化けは、Origin(読み込み)や BOM(書き出し)の設定で解決することが多いです。
Origin=932 が Shift_JIS、65001 が UTF-8 です。
SaveAs で UTF-8 が使えない場合は、ADODB.Stream や FileSystemObject を使い、バイナリ的に BOM を付けて書き出す方法があります。
実務では、(1) 取り込み側で Origin を指定して正しく開けるかを確認し、(2) 必要に応じて ADODB.Stream で UTF-8(BOM/無BOM)を制御する、という流れが基本です。
テキストファイルの読み書き(Open、Print #、Input #)
VBAの古典的手法はOpen/Close/Print #/Line Input #です。行単位の読み書きやヘッダー操作に向きますが、文字コードの制御は弱めです。簡単な書き込み例はこちらです。
Open "C:\Temp\sample_txt.csv" For Output As #1
Print #1, "列1,列2"
Close #1
読み込みはLine Input #で1行ずつ読み、Debug.Printなどで処理します。UTF-8が必要ならADODB.Streamと組み合わせるか、SaveAsを使う方法を選びます。パスやファイルロックは要チェックです。
大量データの分割処理
大量行は一度に処理せず分割すると安定します。行数のしきい値で新ファイルを作る方式は簡単で高速です。ストリーム読み(Open For Input/Line Input)で出力ファイルを切り替えるパターンが実用的です。
概略は次のとおりです。
- Openで元ファイルをFor Inputとして開きます。
- 行カウントnを増やしつつ、現行の出力先へPrintで書き込みます。
- n >= maxRowsになったら出力をCloseし、新規にOpenしてn=0へ戻します。
処理前にApplication.ScreenUpdating=False、Calculation=xlCalculationManualにすると速度が向上します。書き込み回数を減らすためにバッファ(配列や文字列結合)を使うと、さらに高速になります。
注意(ここだけ)
-
最小マクロ:マクロ実行前にブックを
*.xlsmで保存し、Excel のセキュリティ設定でマクロが実行可能な状態にしてください。また、ファイルアクセス権やパス、他プロセスでのロックもエラー原因になります。
要約
Workbooks.Open は手軽に使えますが、OpenText/QueryTables は区切り文字や列型、文字コード指定に有効です。
CSV の書き出しは SaveAs の FileFormat を使い、UTF-8 が必要なら xlCSVUTF8 や ADODB.Stream を検討するのがポイントです。
文字化けは Origin や BOM の有無で多く解決しますので、取り込みと出力の両方で確認を行うのが要チェックです。
Open/Print #/Line Input # は行単位処理に向きますが、文字コード制御は限定的です。
大量データは分割して処理し、ScreenUpdating や Calculation の一時変更、バッファ利用で効率化するのがポイントです。