Microsoft Excel искажает диакритические знаки в файлах .csv? - PullRequest
180 голосов
/ 01 октября 2008

Я программно экспортирую данные (используя PHP 5.2) в файл теста .csv.
Пример данных: Numéro 1 (обратите внимание на ударение на е). Данные utf-8 (без предварительной спецификации).

При открытии этого файла в MS Excel отображается как Numéro 1.

Я могу открыть это в текстовом редакторе (UltraEdit), который отображает его правильно. UE сообщает, что символ decimal 233.

Как я могу экспортировать текстовые данные в файл .csv, чтобы мог MS Excel правильно отобразить , предпочтительно без принудительного использования мастера импорта или мастера не по умолчанию настройки?

Ответы [ 22 ]

226 голосов
/ 01 октября 2008

Правильно отформатированный файл UTF8 может иметь Порядок следования байтов в качестве первых трех октетов. Это шестнадцатеричные значения 0xEF, 0xBB, 0xBF. Эти октеты служат для пометки файла как UTF8 (так как они не относятся к информации «порядка байтов»). 1 Если эта спецификация не существует, потребитель / считыватель оставляют для вывода тип кодировки текст. Считыватели, не поддерживающие UTF8, будут считывать байты как некоторые другие кодировки, такие как Windows-1252, и отображать символы  в начале файла.

Существует известная ошибка, при которой Excel при открытии файлов CSV UTF8 через сопоставление файлов предполагает, что они находятся в однобайтовой кодировке, , игнорируя наличие спецификации UTF8. Это не может быть исправлено любой системной кодовой страницей по умолчанию или настройкой языка. Спецификация не будет подсказывать в Excel - она ​​просто не будет работать. (В отчете меньшинства утверждается, что спецификация иногда запускает мастер «Импорт текста».) Эта ошибка существует в Excel 2003 и более ранних версиях. В большинстве отчетов (среди ответов здесь) говорится, что это исправлено в Excel 2007 и новее.

Обратите внимание, что вы можете всегда * правильно открывать CSV-файлы UTF8 в Excel с помощью мастера «Импорт текста», который позволяет указать кодировку открываемого файла. Конечно, это гораздо менее удобно.

Читатели этого ответа, скорее всего, находятся в ситуации, когда они не поддерживают Excel <2007, но отправляют необработанный текст в формате UTF8 в Excel, который неправильно его интерпретирует и добавляет к тексту <code>Ã и другие подобные Windows- 1252 персонажа. Добавление спецификации UTF8, вероятно, является вашим лучшим и самым быстрым решением.

Если вы застряли с пользователями старых Excels, и Excel является единственным потребителем ваших CSV, вы можете обойти это, экспортировав UTF16 вместо UTF8. Excel 2000 и 2003 дважды щелкнет, чтобы открыть их правильно. (Некоторые другие текстовые редакторы могут иметь проблемы с UTF16, поэтому вам, возможно, придется тщательно взвесить ваши варианты.)


* За исключением случаев, когда вы не можете, (по крайней мере) мастер импорта Microsoft Excel 2011 для Mac не всегда работает со всеми кодировками, независимо от того, что вы говорите. </ anecdotal-свидетельствует>:)

37 голосов
/ 24 ноября 2008

Предзаказ спецификации (\ uFEFF) работал для меня (Excel 2007), в которой Excel распознал файл как UTF-8. В противном случае сохранение и использование мастера импорта работает, но не так идеально.

30 голосов
/ 30 октября 2009

Ниже приведен код PHP, который я использую в своем проекте при отправке Microsoft Excel пользователю:

  /**
   * Export an array as downladable Excel CSV
   * @param array   $header
   * @param array   $data
   * @param string  $filename
   */
  function toCSV($header, $data, $filename) {
    $sep  = "\t";
    $eol  = "\n";
    $csv  =  count($header) ? '"'. implode('"'.$sep.'"', $header).'"'.$eol : '';
    foreach($data as $line) {
      $csv .= '"'. implode('"'.$sep.'"', $line).'"'.$eol;
    }
    $encoded_csv = mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
    header('Content-Description: File Transfer');
    header('Content-Type: application/vnd.ms-excel');
    header('Content-Disposition: attachment; filename="'.$filename.'.csv"');
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: '. strlen($encoded_csv));
    echo chr(255) . chr(254) . $encoded_csv;
    exit;
  }

ОБНОВЛЕНО: Улучшение имени файла и исправление ошибки правильного расчета длины. Благодаря TRiG и @ ivanhoe011

12 голосов
/ 22 августа 2013

Ответ для всех комбинаций версий Excel (2003 + 2007) и типов файлов

Большинство других ответов здесь касаются только их версии Excel и не обязательно помогут вам, потому что их ответ может не соответствовать действительности для вашей версии Excel.

Например, при добавлении символа спецификации возникают проблемы с автоматическим распознаванием разделителей столбцов, но не с каждой версией Excel.

Есть 3 переменные, которые определяют, работает ли он в большинстве версий Excel:

  • Кодирование
  • наличие символа спецификации
  • Сепаратор клеток

Кто-то стоик в SAP попробовал каждую комбинацию и сообщил о результате. Конечный результат? Используйте UTF16le с спецификацией и символом табуляции в качестве разделителя, чтобы он работал в большинстве версий Excel.

Ты мне не веришь? Я бы тоже не стал, но тут читаю и плачу: http://wiki.sdn.sap.com/wiki/display/ABAP/CSV+tests+of+encoding+and+column+separator

10 голосов
/ 01 октября 2008

выберите UTF-8, заканчивающийся при импорте. если вы используете Office 2007, вы выбрали именно это: сразу после открытия файла.

8 голосов
/ 30 марта 2011

Эхо UTF-8 BOM перед выводом данных CSV. Это исправляет все проблемы с символами в Windows, но не работает для Mac.

echo "\xEF\xBB\xBF";

Это работает для меня, потому что мне нужно создать файл, который будет использоваться только на ПК с Windows.

7 голосов
/ 18 февраля 2012

UTF-8 не работает для меня в Office 2007 без какого-либо пакета обновления, с или без спецификации (U + ffef или 0xEF, 0xBB, 0xBF, ни один не работает) установка sp3 заставляет UTF-8 работать, когда предваряется 0xEF, 0xBB, 0xBF BOM.

UTF-16 работает при кодировании в python с использованием "utf-16-le" с 0xff 0xef Сложная спецификация и использование табуляции в качестве разделителя. Мне пришлось вручную выписать спецификацию, а затем использовать «utf-16-le» вместо «utf-16», в противном случае каждый метод encode () добавляет префикс к спецификации для каждой записанной строки, которая появился как мусор в первом столбце второй строки и после.

не может сказать, будет ли UTF-16 работать без установленного sp, так как Я не могу вернуться сейчас. Вздох

Это на windows, не знаю про офис для MAC.

для обоих рабочих случаев импорт работает при запуске загрузки непосредственно из браузер и мастер импорта текста не вмешиваются, они работают так, как и следовало ожидать.

4 голосов
/ 27 февраля 2009

Как сказал Фрегал, \ uFEFF - это путь.

<%@LANGUAGE="JAVASCRIPT" CODEPAGE="65001"%>
<%
Response.Clear();
Response.ContentType = "text/csv";
Response.Charset = "utf-8";
Response.AddHeader("Content-Disposition", "attachment; filename=excelTest.csv");
Response.Write("\uFEFF");
// csv text here
%>
2 голосов
/ 12 июня 2009

Я также заметил, что на этот вопрос «ответили» некоторое время назад, но я не понимаю истории, в которых говорится, что вы не можете открыть CSV-файл с кодировкой utf8 в Excel без использования текстового мастера.

Мой воспроизводимый опыт: Введите Old MacDonald had a farm,ÈÌÉÍØ в Блокноте, нажмите Enter, затем Сохранить как (используя опцию UTF-8).

Использование Python, чтобы показать, что на самом деле там:

>>> open('oldmac.csv', 'rb').read()
'\xef\xbb\xbfOld MacDonald had a farm,\xc3\x88\xc3\x8c\xc3\x89\xc3\x8d\xc3\x98\r\n'
>>> ^Z

Хорошо. Блокнот поместил спецификацию спереди.

Теперь перейдите в проводник Windows, дважды щелкните имя файла или щелкните правой кнопкой мыши и используйте «Открыть с помощью ...», после чего откроется окно Excel (2003) с отображением, как и ожидалось.

2 голосов
/ 06 июня 2009

Вы можете сохранить html-файл с расширением «xls», и акценты будут работать (по крайней мере, до 2007 года).

Пример: сохраните это (используя Save As utf8 в Блокноте) как test.xls:

<html>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8" />
<table>
<tr>
  <th>id</th>
  <th>name</th>
</tr>
<tr>
 <td>4</td>
 <td>Hélène</td>
</tr>
</table>
</html>
...