【Power Query】CSVの文字化けをEncoding指定で防ぐ方法

Power QueryのCsv.DocumentでCSVの文字化けをEncoding引数で防ぐ方法のアイキャッチ画像 Power Query

古いシステムから出力されたCSVファイルをPower Queryで取り込もうとすると、日本語部分が文字化けすることがあります。古いシステムからCSV連携をしようとすると、文字コードの違いによる文字化けによく遭遇します。

Excelでファイルを直接開く場合は、文字コードをある程度自動で判別・補正してくれます。しかし、Power Queryのようにコードで処理する場合はこの自動補正がかからないため、文字コードを明示的に指定・判定する必要があります。ここをすんなり処理できるかどうかで、その後の加工がスムーズに進むかが決まります。

結論:Csv.DocumentのEncoding引数で文字コードを指定する

Power QueryでCSVを読み込むCsv.Document関数には、文字コードを指定するEncoding引数があります。この引数を省略した場合の既定値は65001(UTF-8)です。

古いシステムが出力するShift_JISのCSVをそのまま読み込むと、既定のUTF-8として解釈されるため文字化けします。次のようにEncoding引数へコードページ番号を明示的に指定すると、正しく読み込めます。

let
    Source = Csv.Document(
        File.Contents("C:\Users\xxxx\Downloads\sample.csv"),
        [Delimiter=",", Columns=2, Encoding=932, QuoteStyle=QuoteStyle.None]
    ),
    Promoted = Table.PromoteHeaders(Source, [PromoteAllScalars=true])
in
    Promoted
Power Queryの詳細エディターでCsv.DocumentにEncoding=932を指定したM言語のコード
Encoding=932を指定して読み込んだCSVが文字化けせずに表示された結果テーブル

今回はShift_JISとUTF-8の2つを扱いますが、それぞれのコードページ番号は次のとおりです。

文字コードコードページ番号
Shift_JIS932
UTF-865001

なぜ文字化けするのか(Csv.Documentの既定はUTF-8)

Excelで.csvファイルをダブルクリックして開く場合、Excel側でファイルの文字コードをある程度自動判別し、Shift_JISでもUTF-8でも大きな問題なく表示してくれます。

Csv.Document関数はEncoding引数を省略すると、既定値のUTF-8(コードページ65001)としてファイルを読み込みます。実際のファイルがShift_JIS(コードページ932)で保存されていると、バイト列をUTF-8のルールで解釈してしまうため、日本語部分が文字化けします。Excelで開いたときの「自動で直してくれる」感覚のままPower Queryを使うと、ここでつまずきやすいポイントです。

Shift_JISとUTF-8が混在する場合はBOMの有無で判定する

取り込むCSVの文字コードが毎回同じであれば、Encoding引数に固定値を指定するだけで済みます。しかし、複数の連携元からCSVを受け取っていて、ファイルごとにShift_JISだったりUTF-8だったりする場合は、コード側でどちらの文字コードかを判定してから読み込む必要があります。

判定の手がかりになるのが、UTF-8ファイルの先頭に付与されることがあるBOM(Byte Order Mark)です。UTF-8のBOMは16進数でEF BB BFの3バイトです。ファイルの先頭にこの3バイトがあればUTF-8、なければShift_JIS、という前提で振り分けます。

let
    FilePath = "C:\Users\xxxx\Downloads\sample.csv",
    BinarySource = File.Contents(FilePath),
    Bom = Binary.Range(BinarySource, 0, 3),
    IsUtf8Bom = Bom = #binary({0xEF, 0xBB, 0xBF}),
    EncodingCode = if IsUtf8Bom then 65001 else 932,
    Source = Csv.Document(BinarySource, [Delimiter=",", Columns=2, Encoding=EncodingCode, QuoteStyle=QuoteStyle.None]),
    Promoted = Table.PromoteHeaders(Source, [PromoteAllScalars=true])
in
    Promoted
Power Queryの詳細エディターでBOMの有無によりEncodingを自動判定するM言語のコード
BOM判定パターンで読み込んだCSVがExcelシートに正しく表示された結果

このパターンには前提条件があります。「BOMがないCSVはShift_JISで送られてくる」という前提が成り立つ場合に限り有効です。実機で検証したところ、BOM付きのUTF-8ファイルとShift_JISファイルは正しく判定できましたが、BOMなしのUTF-8ファイルを試すとShift_JISと誤判定され、文字化けすることを確認しています。

実務では、同じシステムから毎回決まったフォーマットで出力されるCSVを扱うことがほとんどで、CSVのレイアウトごとにクエリを分けて作るのが一般的です。その場合は、連携元のCSVの傾向(BOM付きUTF-8で来るのか、Shift_JISで来るのか)に合わせてこの判定ロジックをそのまま使って問題ありません。複数の連携元のCSVを1つのクエリでまとめて処理していて、その中にBOMなしのUTF-8ファイルが混ざる可能性がある場合だけ、注意してください。

Shift_JIS(コードページ932)のCSVを取り込んだ後、VBAで氏名のバイト数を上限チェックする場面もあります。その方法は、全角氏名のバイト数チェックはLenBとStrConvで行うで扱っています。

BOMなしのUTF-8を置換文字で判定する方法と、判定できないケース(半角カナのShift_JISなど)は、【Power Query】CSVの文字コードを置換文字で判定するで検証しています。

書き出す側(BOM付きUTF-8のCSVを作る方法)は、【VBA】BOM付きUTF-8のCSV書き出しと、URLパスの検知で扱っています。

まとめ

Power QueryでCSVを読み込むときの文字化けは、多くの場合「Csv.Documentの既定値(UTF-8)と実際のファイルの文字コードが食い違っている」ことが原因です。Excelでファイルを直接開いたときのような自動補正は働かないため、Encoding引数に932(Shift_JIS)や65001(UTF-8)を明示的に指定します。

連携元によって文字コードが変わる場合は、BOMの有無で判定する方法も使えます。CSVのレイアウト(=連携元)ごとにクエリを分けて作るのが実務では一般的なので、「このクエリで扱うCSVはBOMなしならShift_JIS」という決め打ちで基本的に問題ありません。より詳しい仕様はMicrosoft LearnのCsv.Documentリファレンスも参考にしてください。

コメント

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