【ExcelVBA・マクロ】ADODB.Streamの使い方|BOMなしUTF-8でテキストファイルを読み書きする方法【コピペOK】

ExcelVBA

はじめに

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, 22adSaveCreateOverWrite(既存ファイルがあれば上書き)を意味します。ファイルが存在しない場合のみ保存したいときは1adSaveCreateNotExist)を指定します。

このコードで保存したファイルは、先頭に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ファイルを読み込む

保存したファイルを読み込むときは、LoadFromFileReadTextを使います。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なし)が求められる場面は少なくありません。ぜひこの記事のコードをベースに、自分の業務に合わせて活用してみてください。

スポンサーリンク
スポンサーリンク
ExcelVBA
シェアする
いがぴをフォローする

コメント

タイトルとURLをコピーしました