PHP7.2:Excelで編集できるCSVを作る
PHP7.2:Excelで編集できるCSVを作る
Excel 2016以降はUTF-8で扱えるようですので、2013以前の場合のお話です。
このやり方でダウンロードしたCSVファイルをExcelで編集してそのままアップロードできます。
ただ、Excelによる値の変換(ex.全角数字のみの項目は半角数字に変換される、数字の頭に有る0が消える)は起きるので注意してください。
環境
現象
CSVファイルをExcelで開くときに、文字コードがSJIS以外の場合はBOMをつけないとSJISで読み込もうとして文字化けしてしまう。
また、開いたCSVファイルを保存したときにExcelが自動変換してしまう。
Excelで開いたとき、保存したときの動作は下表の通り。
区切り文字 | 文字コード | BOM | Excelで開いたときの動作 | Excelで保存したときの動作 |
---|---|---|---|---|
カンマ | UTF-8 | 無し | 項目がセルごとに別れる。文字化け | カンマ区切り・SJISで保存 |
カンマ | UTF-8 | 有り | 項目がセルごとに別れる。文字化けしない | タブ区切り・SJISで保存 |
カンマ | UTF-16 LE | 有り | セルごとに別れない。文字化けしない | 1行が1項目扱い・UTF-16 LEで保存 |
タブ | UTF-8 | 無し | セルごとに別れない。文字化け | 1行が1項目扱い・SJISで保存 |
タブ | UTF-8 | 有り | セルごとに別れない。文字化けしない | 1行が1項目扱い・SJISで保存 |
タブ | UTF-16 LE | 有り | 項目がセルごとに別れる。文字化けしない | タブ区切り・UTF-16 LEで保存 |
対応
対応策としては2通り。今回は下のパターンで対応します。
参考リンクを参考にstream_filterでUTF-16 LEに変換し、タブ区切りで出力する。
// ストリームを開く $fp = fopen('php://output','w'); // 文字コードを変換するフィルター stream_filter_prepend($fp, "convert.iconv.utf-8/utf-16le//TRANSLIT"); // BOMをつける fwrite($fp, "\xEF\xBB\xBF"); //UTF-8 // CSVのヘッダ行出力 $csvHeader = ["1列目", "2列目", "3列目"]; fputcsv($fp, $csvHeader, "\t"); // レコード出力 foreach ($rows as $row) { fputcsv($fp, $row, "\t"); } // ストリームを閉じる fclose($fp);
参考
[PHP] Mac版Excelと互換性のあるCSVファイルを出来るだけ効率よく作成する
https://qiita.com/mpyw/items/2795bef3ed561f4cf4e9
PHPのストリームフィルタでCSV読み込み
https://qiita.com/rana_kualu/items/dc99be34b9e2f721b70f
感想
お願いですからUTF-8で処理できるようにしといてください。
というか2016以降を使えという話かもしれないが。
一点分からないのが、なぜ付与するBOMが「\xFF\xFE」(UTF-16 LE)でなく「\xEF\xBB\xBF」(UTF-8)なのか。
BOMもstream_filterで変換されるのだろうか?
もう少し調べる必要がある。