ブラウザだけで Excel 向け日本語 CSV ファイルを作る方法

※ ただし IE を除く

ブラウザで表示しているデータをCSV ファイルにしてダウンロードしたかったので調べてみると File API の Blob + createObjectURL でさくっとできるっぽい。 *1
だけど、日本語が utf8 になってしまう。

そのまま Excel で開くと文字化けてしまうので、どうしたもんかと悩んでいたら、 BOM をつければ 中身が utf8 でも開けるという情報を得たのでBOM 付きでダウンロードできるようにしてみました。というお話。

実際のHTMLは https://dl.dropbox.com/u/12062013/excel_csv/download.html で試せます。

(1) BOM の用意

数値のArray ([0xEF, 0xBB, 0xBF]) をそのまま Blob に渡すと数字文字列に変換 ("239,187,191")されて出力されるし、文字列 (String.fromCharCode(0xEF, 0xBB, 0xBF)) にしても、 勝手に utf8 に変換 (バイナリ表現で "C3 AF C2 BB C2 BF") されてしまうので NG。
Typed Array 使ったらうまくいった。

(2) CSV データの用意

本来はこのデータはModel から取得したデータ。
Excel 用なので、セル内改行なんかもできますね。="" は、先頭が 0 で始まる数字をそのまま表示したいときには必須の表現。
実際に使うときにはデータ内にカンマやダブルクォテーションなんかが含まれてないかチェックする必要があるかな。

(3) BOM 付き CSV ファイルの元となる Blob を作成

BOM と CSV データを渡すだけ。
BlobPropertyBag (第2引数) に type を渡すとFirefox では mime として利用するようで、これを指定しておかないとブラウザにCSVデータが表示されちゃう。もちろん実際の挙動はFirefox の設定によって異なるけど、あらかじめ設定しておけば ダウンロード後 Excel に渡してくれる。
"application/x-csv" とか、 "text/comma-separated-values" でもいいかも。

(4) createObjectURL を使って Blob URL を構築

Firefox の場合は window.URL、Chrome の場合は window.webkitURL の createObjectURL を使って Blob URL を作る。
これは、URL とはいっても永続的なものではなく、現在のスクリプトを実行している時のみ利用可能なもの。

(5) Blob URL をダウンロードさせるリンクを作る

a タグに download 属性を付けると、 Chrome ではそれをファイル名として扱ってくれる。
Firefox には効果ないけど。

文字コードについて

HTML の文字コードが何であっても、 utf8 になるっぽい。この辺は javascript の実装が絡んでくるのかよく分からないけどそうなる。

それから、 4byte utf8 は 数値文字参照に変換されてしまったので注意。

動作確認

動作を確認したのは Firefox 19 と Chrome 24。
Typed Array がないので IE9 だと動かないし、IE10 確認するの面倒だったの。

あと、 Mac Excel だとダメらしい。


*1:参考リンクの項を参照