やりたいこと
phpでcsvファイルを作成するにあたり、
全てのフィールドをダブルコーテーションで囲うプログラムを作りたい
fputcsv()を使ってcsvを作る
ダブルコーテーションで「くくられる」or「くくられない」
$header = [
'MakeCsv',
'SampleReport',
'Php',
'Date',
'Csv'
];
$data = [
"hoge",
"ho ge",//半角スペース1つ
"ho ge",//半角スペース2つ
"ho ge",//全角スペース1つ(全角スペースは$enclosureでくくられない)
"hoge"
];
$delimiter = ',';//引数として設定しなくてもデフォでカンマ区切り
$enclosure = '"';//引数として設定しなくても必要があればダブルコーテーションでくくってくれる?
$escape ; //今回未使用だが、エスケープしたい文字があれば指定する
$csvFile = fopen('test.txt', 'w');
fputcsv($csvFile,$header, $delimiter, $enclosure);
fputcsv($csvFile, $data, $delimiter, $enclosure);
fclose($csvFile);
出力結果
MakeCsv,SampleReport,Php,Date,Csv
hoge,"ho ge","ho ge",ho ge,hoge
このように、fputcsvというphpの関数を使用してみたが何かと不都合が多かったです。
http://php.net/manual/ja/function.fputcsv.php
delimiter
delimiterの設定は上手くいきました。
そもそも引数として取らなくても、デフォルトで「,」(カンマ)区切りとなっています。
enclosure
enclosureの設定が上手くいきませんでした。
一文字で区切るためのオプションですが、
フィールドに半角スペースが入っていると、デブルコーテーションでくくられますが、
全角スペースが入っていても、くくられない問題があります。
書き方の問題かと思い、エスケープ「/"」などを試してみましたが、どうやらそうゆう問題ではなさそうで、
enclosureの「"」は、エスケープ済みであるらしく、バックスラッシュで区切る必要はないみたいです。
しかし、だからといってダブルコーテーションでくくられるわけではありませんでした。
php5.4以降に出来たオプション escape_char
と組み合わせても、うまくいかなかったです。
http://d.hatena.ne.jp/miau/20141214/1418574582
fputcsvを使って「""」(ダブルコーテーション)を必ず囲うという組み合わせは、諦める方向で判断しました(´Д` )
結論!! 文字列として、自前でcsvにする
配列を文字列にし、必要な文字を追加していきました。
「"」「対象の値」「"」「,」「/n」の順で、文字列として追加
※cakePHP3を使用しているので、new Folderなどは適時置き換えて下さい。
private function _createCSV($data, $header, $fileName)
{
$folderPath = TMP . 'csv-sheets/';
$dir = new Folder();
$dir->create($folderPath);
$stream = fopen($folderPath . $fileName, 'w');
fwrite($stream, $header);
foreach ($data as $row) {
$out = '';
$row_tmp = '"';
$row_tmp .= implode('","', $row);
$row_tmp .= '"' . "\n";
$out .= $row_tmp;
fwrite($stream, $out);
}
fclose($stream);
}
これで、すべての値がダブルコーテーションでくくられることが出来ました。
※関数fwriteは、配列を引数としてとれないので、ヘッダーに関してはフィールドの値が決まっているため、直で文字列で格納しています。
$header = '"MakeCsv","SampleReport",Php,"Date","Csv"' . "\n";
ダブルコーテーションにこだわる必要はあったのか
今回はcsvファイルを作成する上で、ダブルコーテーションを必ず付与するという仕様のためダブルコーテーションにこだわりました。
しかしそもそも、csvファイルとしては、すべてにダブルコーテーションをつける必要はなかったのではないかと疑問を抱きました。
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11145768576
スペースが間に入っていたりすると、その区切りとして、ダブルコーテーションが必要で、
fputcsvは、間にスペースがある値にダブルコーテーションを囲っていて、それ以外は囲ってないのは、それで問題がないから囲ってないのかもしれない。
懸念点を一つあげるとしたら、windowsのエクセルがshift-jisなため、shift-jisに変更しておかないとダメな可能性があります
RFC 規約を見てみる
RFCによると、ダブルコーテションをつけるつけないは、どっちでも良いみたいです。
ただし、フィールドにダブルコーテーションがある場合は、そのフィールドをダブルコーテーションでくくらないといけないなどの例外はある模様でした。
http://www.kasai.fm/wiki/rfc4180jp
ダブルコーテーションでくくらないといけない理由が少しでもあると救われます^_^;