2023年2月5日
開発環境
OS:Windows 10
SDK:VS Code + flutter 3.3.10
概要
flutterでCSVデータを出力するときはBOMを付けた方がいい。
エクセルはShift-JISに対応している
flutterでCSVを出力します。
テキストエディタで表示すると問題なし。
いざ、エクセルで開いてみた結果。。。

文字化けしています。
なぜなのか調べてみたところ、エクセルは文字コードをShift-JISで取り扱うようです。
それに対し、flutterはutf-8で出力します。
故に文字コードが異なるため、文字化けが発生したということですね。
BOMを付ける
対策はどうするのか。
flutterでutf-8をshift-jisに変換して出力すればいいんじゃないのか。
最初にそう思ったわけですが、「文字コード変換」と「変換後のデータ出力」。
2つの対応が必要になります。
もっとうまい方法がないのかとネットで検索してみると見つけました。
エクセルはBOM付きutf-8なら表示できる。
つまり、
utf-8のデータの先頭にBOMと呼ばれる識別コードを付与するだけです。
これなら簡単。
改修したコードがこちら。
//CSV生成
final csv = await makeFileCsv();
// utf-8バイト変換
final excelCsvBytes = [0xEF, 0xBB, 0xBF, ...utf8.encode(csv)];
// base64エンコード変換
final base64ExcelCsvBytes = base64Encode(excelCsvBytes);
AnchorElement(
href: 'data:text/plain;charset=utf-8;base64,$base64ExcelCsvBytes')
..setAttribute('download', 'test.csv')
..click();
2行目でCSVデータをバイト配列に変換して先頭に「0xEF 0xBB 0xBF」を付与。
3行目でそのバイト配列をbase64に再変換。
あとはそのデータを「utf-8;base64」として出力する。
という流れです。
改修コードで確認した結果、テキストエディタでも問題なく開き、エクセルの文字化けもなくなりました。