Escape символ с запятой при записи в файл csv

Я хочу написать что-то вроде

=HYPERLINK("http://example.com"; "Example")

в CSV файл, разделенный запятыми, но Excel анализирует точку с запятой и помещает часть "Example" ) в другую ячейку. Я попытался сбежать с точкой с запятой с обратной косой чертой и без всякой удачи обернуть все в двойные кавычки.

Любая помощь?

Ответы

Ответ 1

Обертка с двойными кавычками уже была правильной идеей, но вы должны убедиться, что делаете это правильно. Вы можете поместить столбец в двойные кавычки, тогда все внутри рассматривается как одно значение. Котировки сами должны быть экранированы, написав два из них ("").

См. например:

Column A;Column B;Column C
Column A;"Column B; with semicolon";Column C
Column A;"Column B"";"" with semicolon and quotes";Column C
Column A;"=HYPERLINK(""http://example.com""; ""Example"")";Column C

Ответ 2

У меня также было очень дикое время, чтобы понять всю картину, то есть то, как у меня все мои csv готовы открыть в excel в php (включая также кодировку utf8):

$sep='";"';//note the separator is double quoted
while($t=mysql_fetch_assoc(mysql_query('select ..')){
  #replaces the caracters who are breaking csv display
  $t=array_map(function($x){return str_replace(array("\n","\r",'"'),array('\\n',"\\r",'""'),$x);},$t);
  $csv.="\n\"".implode($sep,$t)."\"";
}
$charset='utf-8';
header('Content-Type: application/csv;charset='.$charset);
header('Content-Disposition: attachment; filename="filename.csv"');
$bom=chr(239).chr(187).chr(191);#this tells excel document is utf8 encoded
die($bom.$csv);

Ответ 3

Я использую эту функцию для каждого значения CSV, чтобы передать ее правильно. Он цитирует значение только в том случае, если оно содержит новые строковые символы, двойные кавычки или разделители. Фактически единственным значением для выхода является символ с двойными кавычками. Все остальные содержимое ячейки попадают в нее и отображаются правильно в Excel.

Проверено с различными версиями парсеров Excel и ODBC CSV в кириллице в Windows.

/**
 * This function escapes single CSV value if it contains new line symbols, quotes or separator symbol and encodes it into specified $encoding.
 * 
 * @param string $source - origin string
 * @param string $sep - CSV separator
 * @param string $source_encoding - origin string encoding
 * @param string $encoding - destination encoding
 *
 * @return string - escaped string, ready to be added to CSV
 *
 * @example echo escapeStringCSV("Hello\r\n\"World\"!");
 *  will output
 *      "Hello
 *      ""World""!"
 */
function escapeStringCSV($source, $sep=';', $source_encoding='utf-8', $encoding="windows-1251//TRANSLIT"){

    $str = ($source_encoding!=$encoding ? iconv($source_encoding, $encoding, $source) :  $source);

    if(preg_match('/[\r\n"'.preg_quote($sep, '/').']/', $str)){
        return '"'.str_replace('"', '""', $str).'"';
    } else 
        return $str;
}

Таким образом, использование может быть таким:

 while($row = mysql_fetch_assoc($res)){
    foreach($row as $val){
        $csv .= escapeStringCSV($val).';';
    }
    $csv .= "\r\n";
}