【ExcelVBA・マクロ】文字化け対策完全ガイド|CSV読み込み時のUTF-8・Shift-JIS判定と変換方法【コピペOK】

ExcelVBA

「VBAでCSVファイルを読み込んだら日本語が文字化けした」という経験がある方は多いのではないでしょうか。原因の多くは、ファイルの文字コード(UTF-8・Shift-JISなど)とVBA側の読み込み方法が合っていないことにあります。

この記事では、Open ステートメントで文字化けが起きる理由から、ADODB.Streamオブジェクトを使ってUTF-8のファイルを正しく読み書きする方法まで、実際に使えるコードで解説します。

スポンサーリンク
スポンサーリンク

なぜ文字化けが起きるのか

VBAのOpenステートメントを使った読み込みは、内部的にOSの標準文字コード(日本語Windowsでは基本的にShift-JIS)を前提としています。そのため、メモ帳などで「UTF-8」形式で保存されたCSVファイルをOpenで読み込むと、日本語部分が正しく解釈されず文字化けが発生します。

Sub 文字化けする例()
    Dim buf As String
    Open ThisWorkbook.Path & "\data_utf8.csv" For Input As #1
    Do Until EOF(1)
        Line Input #1, buf
        Debug.Print buf  ' UTF-8ファイルだと日本語が文字化けする
    Loop
    Close #1
End Sub

近年はWebサービスからダウンロードするCSVがUTF-8であることが多く、この問題に遭遇しやすくなっています。解決にはADODB.Streamオブジェクトを使うのが確実です。

ADODB.StreamでUTF-8ファイルを読み込む

ADODB.Streamは文字コードを明示的に指定して読み書きできるオブジェクトです。参照設定は不要で、CreateObjectから呼び出せます。

Sub UTF8ファイルを読み込む()
    Dim stream As Object
    Dim allText As String

    Set stream = CreateObject("ADODB.Stream")
    stream.Type = 2  ' テキストモード
    stream.Charset = "UTF-8"
    stream.Open
    stream.LoadFromFile ThisWorkbook.Path & "\data_utf8.csv"
    allText = stream.ReadText
    stream.Close
    Set stream = Nothing

    Debug.Print allText  ' 文字化けせずに表示される
End Sub

Charsetプロパティに"UTF-8"を指定して開くのがポイントです。読み込んだallTextSplit関数で改行ごとに分割すれば、1行ずつ処理することもできます。

Sub UTF8ファイルを1行ずつ処理する()
    Dim stream As Object
    Dim allText As String
    Dim lines() As String
    Dim i As Long

    Set stream = CreateObject("ADODB.Stream")
    stream.Type = 2
    stream.Charset = "UTF-8"
    stream.Open
    stream.LoadFromFile ThisWorkbook.Path & "\data_utf8.csv"
    allText = stream.ReadText
    stream.Close
    Set stream = Nothing

    lines = Split(allText, vbLf)
    For i = LBound(lines) To UBound(lines)
        If Trim(lines(i)) <> "" Then
            Debug.Print i & "行目: " & lines(i)
        End If
    Next i
End Sub

改行コードがファイルによってvbCrLfだったりvbLfだったりするため、Replace関数でvbCrLfvbLfに統一してからSplitすると、行がずれるトラブルを防げます。

BOMあり・BOMなしUTF-8の違いに注意する

UTF-8には、ファイル先頭に「BOM(Byte Order Mark)」と呼ばれる目印が付いているものと付いていないものがあります。ADODB.StreamCharset = "UTF-8"はBOMありのファイルを想定しているため、BOMなしのUTF-8ファイルを読み込むと、先頭に余分な文字が混入することがあります。

先頭1文字にChr(65279)(BOM)が含まれていないか確認し、あれば取り除くコードを入れておくと安全です。

Function BOM除去(ByVal text As String) As String
    If Len(text) > 0 Then
        If AscW(Left(text, 1)) = 65279 Then
            text = Mid(text, 2)
        End If
    End If
    BOM除去 = text
End Function

allTextSplitする前にallText = BOM除去(allText)のように呼び出しておけば、先頭行のデータが余計な文字で汚れるのを防げます。

UTF-8形式でファイルを書き出す

逆に、VBAからUTF-8形式でファイルを書き出したい場合もADODB.Streamが使えます。他システムに渡すCSVなど、文字コード指定が必要な場面で役立ちます。

Sub UTF8ファイルを書き出す()
    Dim stream As Object
    Dim outputText As String

    outputText = "名前,部署" & vbCrLf & "山田太郎,営業部" & vbCrLf & "鈴木花子,経理部"

    Set stream = CreateObject("ADODB.Stream")
    stream.Type = 2
    stream.Charset = "UTF-8"
    stream.Open
    stream.WriteText outputText
    stream.SaveToFile ThisWorkbook.Path & "\output_utf8.csv", 2  ' 2 = 上書き保存
    stream.Close
    Set stream = Nothing

    MsgBox "UTF-8形式で保存しました。"
End Sub

SaveToFileの第2引数に2adSaveCreateOverWrite)を指定すると、同名ファイルがあっても上書き保存されます。なお、この方法で保存するとBOM付きUTF-8になります。BOMなしで保存したい場合は、一度Shift-JISで書き出してからバイナリ操作でBOM部分を取り除くなど、別途工夫が必要です。

まとめ

VBAで文字化けが起きたときは、まずファイルの文字コードを確認し、OpenステートメントではなくADODB.Streamを使う方法に切り替えるのが有効です。

  • OpenステートメントはOS標準(Shift-JIS)を前提としており、UTF-8ファイルは文字化けしやすい
  • ADODB.StreamCharsetプロパティで文字コードを明示的に指定できる
  • BOMあり・BOMなしの違いに注意し、必要ならBOM除去処理を入れる
  • 書き出し時も同様にCharsetを指定すれば、UTF-8形式で保存できる

CSVを扱うマクロを作る際は、まず対象ファイルの文字コードを確認する習慣をつけておくと、文字化けトラブルを未然に防げます。

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

コメント

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