はじめに
Excel VBAでテキストファイルを扱うとき、OpenステートメントやPrint #を使う方法は手軽ですが、文字コードがShift-JIS(ANSI)固定になってしまい、UTF-8で保存したいときには不向きです。特に、他システムとの連携でCSVやJSONをUTF-8(BOMなし)で出力したいケースはよくあります。
この記事では、ADODB.Streamオブジェクトを使ってUTF-8のテキストファイルを読み書きする方法、特に「BOM(バイト順マーク)を付けずに保存する方法」を解説します。既存記事「文字化け対策完全ガイド」や「Openステートメントの使い方」とは異なる、文字コードを細かく制御できるファイル操作の方法です。
この記事を読むと以下のことが分かります。
ADODB.Streamの基本的な使い方- UTF-8(BOM付き)でテキストファイルを保存する方法
- BOMなしUTF-8で保存する方法(バイナリストリームとの組み合わせ)
- UTF-8ファイルを読み込む方法
ADODB.Streamとは
ADODB.Streamは、Microsoft ActiveX Data Objects(ADO)に含まれるオブジェクトで、テキストやバイナリデータをメモリ上のストリームとして扱えます。文字コード(Charset)を細かく指定できるため、Openステートメントでは対応しづらいUTF-8などのファイル入出力に向いています。
参照設定は不要です。CreateObject("ADODB.Stream")で遅延バインディングして使用します。
UTF-8(BOM付き)でファイルを保存する
まずは基本形です。以下のコードは、文字列をUTF-8で書き出すシンプルな例です。
Sub SaveAsUtf8WithBom()
Dim ts As Object
Dim filePath As String
filePath = ThisWorkbook.Path & "\output_bom.txt"
Set ts = CreateObject("ADODB.Stream")
ts.Type = 2 ' adTypeText
ts.Charset = "utf-8"
ts.Open
ts.WriteText "こんにちは、VBAからUTF-8で保存します。"
ts.SaveToFile filePath, 2 ' adSaveCreateOverWrite
ts.Close
End Sub
コードの解説
ts.Type = 2でテキストモード(adTypeText)に設定します。数値の代わりに定数を使いたい場合は、コードの先頭にConst adTypeText = 2のように自分で定義しておくと読みやすくなります。ts.Charset = "utf-8"で文字コードをUTF-8に指定します。ts.SaveToFile filePath, 2の2はadSaveCreateOverWrite(既存ファイルがあれば上書き)を意味します。ファイルが存在しない場合のみ保存したいときは1(adSaveCreateNotExist)を指定します。
このコードで保存したファイルは、先頭に3バイトのBOM(EF BB BF)が付与されます。多くのソフトでは問題なく開けますが、Linux系のツールや一部のWeb APIではBOMがエラーの原因になることがあります。
BOMなしUTF-8で保存する
BOMを付けずに保存するには、一度テキストストリームに書き込んだ内容を、バイナリストリームに「BOM分だけ位置をずらしてコピー」する方法を使います。
Sub SaveAsUtf8WithoutBom()
Dim ts As Object
Dim bs As Object
Dim filePath As String
filePath = ThisWorkbook.Path & "\output_nobom.txt"
' テキストストリームにUTF-8で書き込む
Set ts = CreateObject("ADODB.Stream")
ts.Type = 2 ' adTypeText
ts.Charset = "utf-8"
ts.Open
ts.WriteText "こんにちは、BOMなしのUTF-8で保存します。"
' 先頭のBOM(3バイト)を読み飛ばす
ts.Position = 0
ts.Type = 1 ' adTypeBinary
ts.Position = 3
' バイナリストリームにコピーして保存
Set bs = CreateObject("ADODB.Stream")
bs.Type = 1 ' adTypeBinary
bs.Open
ts.CopyTo bs
bs.SaveToFile filePath, 2 ' adSaveCreateOverWrite
ts.Close
bs.Close
End Sub
コードの解説
- 一度
ts.Type = 2(テキストモード)で文字列を書き込んだあと、ts.Position = 0でストリームの先頭に戻し、ts.Type = 1(バイナリモード)に切り替えています。テキストモードで書き込んだ内容も、バイナリとしてそのまま読み出せる点がポイントです。 ts.Position = 3でストリームの読み取り位置を3バイト分進めることで、先頭のBOM(3バイト)を読み飛ばしています。ts.CopyTo bsで、読み飛ばした続きのバイナリデータを別のストリーム(bs)にコピーし、そちらをファイルとして保存しています。
この方法により、BOMなしのUTF-8ファイルを作成できます。他システムとの連携やWeb API送信用のファイルを作るときに活用してください。
UTF-8ファイルを読み込む
保存したファイルを読み込むときは、LoadFromFileとReadTextを使います。BOMの有無にかかわらず、以下のコードで読み込めます。
Sub ReadUtf8File()
Dim ts As Object
Dim filePath As String
Dim content As String
filePath = ThisWorkbook.Path & "\output_nobom.txt"
Set ts = CreateObject("ADODB.Stream")
ts.Type = 2 ' adTypeText
ts.Charset = "utf-8"
ts.Open
ts.LoadFromFile filePath
content = ts.ReadText
ts.Close
Debug.Print content
End Sub
Charset = "utf-8"を指定して読み込めば、BOMがあってもなくても正しく文字列として取得できます。ADOがBOMの有無を自動的に判定してくれるため、読み込み側で特別な分岐処理を書く必要はありません。
注意点
ts.Positionはバイト単位の位置を表します。UTF-8のBOMは3バイト固定なので、Position = 3で問題ありませんが、UTF-16などほかの文字コードを使う場合はBOMのバイト数が異なるため注意してください。- テキストモード(
Type = 2)とバイナリモード(Type = 1)を切り替える際は、必ずPositionを適切な位置に戻してから切り替える必要があります。切り替え忘れるとエラーになったり、データが欠落したりします。 CreateObjectで生成しているため、他のPCで実行する場合もライブラリの参照設定は不要ですが、ADO自体がインストールされている必要があります(Windows標準のExcel環境であれば通常は問題ありません)。
まとめ
この記事では、ADODB.Streamを使ったUTF-8ファイルの読み書き方法を紹介しました。
ADODB.Streamはテキスト・バイナリの両方を扱え、文字コードを細かく指定できるCharset = "utf-8"で書き込むとBOM付きのファイルになる- テキストストリームからバイナリストリームへ3バイトずらしてコピーすることで、BOMなしUTF-8ファイルを作成できる
- 読み込み時は
Charsetを指定するだけで、BOMの有無を気にせず文字列を取得できる
外部システムとのファイル連携でUTF-8(BOMなし)が求められる場面は少なくありません。ぜひこの記事のコードをベースに、自分の業務に合わせて活用してみてください。


コメント