Excel
golang
CSV
bom
クソ

エクセルで読み込むためのCSVファイル

クソアプリケーションことエク○ルでCSVを読み込む時にいろんな問題が発生する。
しかしCSVファイルにちょっとした工夫をすることで、問題なくエ○セルで読み込め、正常に文字が表示されることが発覚した。
ここに報告する。

先に結論

  • 文字コードはUTF-8
  • BOM付きCSVで出力
  • 数字で構成されている文を文字列として認識させたい場合は、=(イコール)を書いて"(ダブルクォート)で囲むと、正常な表示がなされる。(例 ="012345"と書くと、012345と表示される)
    • これはCSVの定義に則っていないはずなので、他の表計算ソフトでも正常に読めるかは謎。

文字コードの問題

クソアプリケーションであるエ○セルは、周知の通り使い古されたShift-JISを使っているため、UTF-8でCSVファイルを作成して普通に開くと文字化けする。
この2017年にいまだにShift-JISを使っているとか、全くもってクソの極みだ。
そんなものは便所に流してスッキリさせたいところだが、不幸なことにJapanese標準CSV用アプリケーションといったらエクセルしかない。
全くこの国はどうかしている。

しょうがないので、UTF-8で書き出したCSVをnkfかなんかでShift-JISに変換しようと思ったお前。
お前が今しようとしている作業はとんでもなく愚行だ。
なぜなら昨今のスマートフォンの普及により絵文字がUTF-8で規定されているが、Shift-JISでの規定がない。
いや、正確にはガラケー時代に各キャリアがShift-JISを独自拡張したキメラのようなクソ規格があると聞く。
お前はまたあのガラケー時代の使い古されたクソのような絵文字を扱いたいのか?

話を戻そう。
絵文字をnkfで変換してみるとどうなるか。
...消えるんだよ。いいか、もう一度言うぞ。
消えるんだ。跡形もなくな。

...何?じゃあ変換せずにエクセルを開いてCSVをインポートすれば良いだと?
お前は正気か?
もしお前が受託開発で、客先でその方法を提示してみろ。
マッドマックスよろしくコンボイのボンネットにくくりつけられて砂漠でヒャッハーだ。

じゃあどうすれば良いのか。
今は2017年。かの一大ブームを作ったWind○ws95から22年が経ち、流石のMicr○s○ftも学んだとみえ、実はやつはUTF-8を標準で直接開いて読むことができる。
しかし、ただでは読めない。
実はCSVにある「クソ」をつけると、UTF-8でも正常に読めるという仕様になっているわけだ。
そのクソの名前は「BOM」。
詳しくはこいつを参考にしてくれ。
https://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%88%E3%82%AA%E3%83%BC%E3%83%80%E3%83%BC%E3%83%9E%E3%83%BC%E3%82%AF

こいつをつけないとエク○ルはUTF-8のCSVを正しく読めないときた。
全くクソをクソで煮しめたような話だな。

参考までにGoでのクソ(BOM)付きCSVを吐き出すコードを提示しよう。
みんなの助けになれば幸いだ。

BOM付きCSVファイル生成コード
import {
    "encoding/csv"
    "bytes"
    "bufio"
}

// 中略

csvBytes := &bytes.Buffer{}         // 書き込むCSVデータ
bw := bufio.NewWriter(csvBytes)
bw.Write([]byte{0xEF, 0xBB, 0xBF})  // BOMをつける
writer := csv.NewWriter(bw)
writer.Write("hoge, fuga, piyo")    // データの書き込み
writer.Flush()                      // 終了処理

なお、このコードはこちらを参考にした。
https://pinzolo.github.io/2017/03/29/utf8-csv-with-bom-on-golang.html
全く先人の知恵には頭が下がる。

エク○ルで取り込んだ時の数字/文字の扱い

たとえばCSVで電話番号や郵便番号を吐き出したとしよう。
それをエクセルで表示したらどうなるか?
答えはこうなる。

スクリーンショット 2017-10-31 18.33.05.png
(表示されている住所/電話番号は一例)

...そうだ、こいつは数字だけで構成されている文字列は問答無用で数値として変換し、勝手に0を消してしまうんだ。

オッケーわかった。
確かにそびえ立つクソのようなエク○ルという表計算ソフトからすれば、気を利かせてやったぜ、ってことなんだろう。
全くあのイルカの時代から何も変わってねぇ。
ではCSVでは文字列の扱いの規定があるので、その規定にしたがって文字列とみなして欲しい場合は"(ダブルクォーテーション)で囲むことにしよう。
http://itdoc.hitachi.co.jp/manuals/3020/30203698A0/swrj0068.htm#ID00385

そういうわけで俺は次のようなCSVファイルを用意した。
もちろんBOM付きだ。

csvファイル
電話番号,郵便番号,住所
"09012345678","0791143",北海道赤平氏赤平

さて、これをエクセルで開くとどうなるか。

スクリーンショット 2017-10-31 18.54.21.png
WTF!?!?!?!?!?!
どういうことだ、文字列として扱えって言ってるのにやつは全くもってブレない。
このあと全角空白を前後に入れたりもしてみたが、やつはピクリとも動かない。
こんなにこびりついて取れないクソは初めてだぜ。

さて、そこで俺はふと思いついた。
古の技術で、セルに入力するあたいの先頭に'(シングルクォーテーション)を入れると、エク○ルは文字列扱いにするというものだ。
なるほど、もはや俺が扱っているのはエク○ルではない。
あくまでCSVっぽいクソファイルをを開くためのクソアプリケーションであるという認識さえもてば、その考えは自然だ。
というわけで電話番号と郵便番号の先頭に'(シングルクォーテーション)をつけた。
それを開いた結果がこれだ。

スクリーンショット 2017-10-31 19.02.46.png
ガッデム!!!!!!!
どうしてCSVから取り込んだ場合にはシングルクォーテーションが表示されるんだ!!!!!!!!
ちなみに該当のセルをダブルクリックで編集モードにして、何も入力せずエンターキーで決定するとちゃんとシングルクォーテーションが消えるという具合だ。
まったく、クソ街道をクソを撒き散らしながらバキュームカーに乗って驀進中という具合だな。

そうやってクソアプリケーションと闘っていた俺がようやくたどり着いた結論がこれだ。

クソ
電話番号,郵便番号,住所
="09012345678",="0791143",北海道赤平氏赤平

スクリーンショット 2017-10-31 19.22.09.png

完璧だ。完璧に表示された。
ウォシュレットで洗い流してついでに毛まで剃ってツルツルにした気分だ。
=(イコール)を書いて"(ダブルクォーテーション)で囲めばやつは式として認識する。
俺が扱っていたのは断じてCSVなんかではない。エク○ルというクソアプリケーションを読み込む専用クソファイルを扱っていたんだ。

おわりに

カッとなって書いた。後悔はない。
間違い等あれば指摘してほしい。