Как я могу выводить CSV UTF-8 в PHP, который Excel будет читать правильно?
У меня есть очень простая вещь, которая просто выводит некоторые вещи в формате CSV, но это должен быть UTF-8. Я открываю этот файл в TextEdit или TextMate или Dreamweaver, и он правильно отображает символы UTF-8, но если я открою его в Excel, он сделает это глупое дело. Вот что я получил во главе моего документа:
header("content-type:application/csv;charset=UTF-8");
header("Content-Disposition:attachment;filename=\"CHS.csv\"");
Все это похоже на желаемый эффект, за исключением того, что Excel (Mac, 2008) не хочет импортировать его должным образом. В Excel нет никаких опций для "открытия как UTF-8" или чего-то еще, поэтому... Я немного раздражаюсь.
Кажется, я не могу найти каких-либо ясных решений в этом месте, несмотря на то, что у многих людей такая же проблема. То, что я вижу больше всего, это включить спецификацию, но я не могу точно понять, как это сделать. Как вы можете видеть выше, я просто echo
используя эти данные, я не пишу никаких файлов. Я могу это сделать, если мне это нужно, я просто не потому, что на данный момент это не похоже на необходимость. Любая помощь?
Обновление: я попытался повторить спецификацию как echo pack("CCC", 0xef, 0xbb, 0xbf);
, которую я просто вытащил с сайта, который пытался обнаружить спецификацию. Но Excel просто добавляет эти три символа в первую ячейку, когда он импортирует, и все еще испортил специальные символы.
Ответы
Ответ 1
Чтобы процитировать инженера по поддержке Microsoft,
Excel для Mac в настоящее время не поддерживает UTF-8
Обновление, 2017: это относится ко всем версиям Microsoft Excel для Mac до Office 2016. Более новые версии (из Office 365) теперь поддерживают UTF-8.
Чтобы вывести содержимое UTF-8, которое Excel как в Windows, так и в OS X сможет успешно прочитать, вам нужно будет сделать две вещи:
-
Убедитесь, что вы конвертируете текст UTF-8 в UTF-16LE
mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
-
Убедитесь, что вы добавили символ порядка байтов UTF-16LE
chr(255) . chr(254)
Следующая проблема, которая появляется только с Excel в OS X (но не в Windows), будет при просмотре CSV файла с запятыми, значения Excel будут отображать строки только с одной строкой и всем текстом вместе с запятыми в первой строке.
Способ избежать этого - использовать вкладки в качестве разделенного значения.
Я использовал эту функцию из комментариев PHP (используя вкладки "\ t" вместо запятых), и она отлично работала на OS X и Windows Excel.
Обратите внимание, что для исправления проблемы с пустым столбцом в конце строки мне пришлось изменить строку кода, которая гласит:
$field_cnt = count($fields);
в
$field_cnt = count($fields)-1;
Как показывают некоторые другие комментарии на этой странице, другие приложения для электронных таблиц, такие как OpenOffice Calc, Apple, Numbers и Google Doc Spreadsheet не имеют проблем с UTF-8 файлами с запятыми.
См. Таблицу в этом вопросе, для чего работает и не работает для файлов CSV Unicode в Excel
В качестве примечания я мог бы добавить, что если вы используете Composer, вам следует взглянуть на добавление League\Csv
к вашим требованиям. League\Csv
есть действительно хороший API для создания файлов CSV.
Чтобы использовать League\Csv
с помощью этого метода создания файлов CSV, ознакомьтесь с этим примером.
Ответ 2
У меня такая же (или аналогичная) проблема.
В моем случае, если я добавляю спецификацию к выходу, она работает:
header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=Customers_Export.csv');
echo "\xEF\xBB\xBF"; // UTF-8 BOM
Я считаю, что это довольно уродливый взлом, но он работал у меня, по крайней мере, для Excel 2007 Windows. Не уверен, что он будет работать на Mac.
Ответ 3
Вот как я это сделал (чтобы заставить браузер загружать файл csv):
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=file.csv');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo "\xEF\xBB\xBF"; // UTF-8 BOM
echo $csv_file_content;
exit();
Единственное, что зафиксировало проблему кодирования UTF8 в превью CSV, когда вы нажимаете пробел на Mac.. но не в Excel Mac 2008... не знаете, почему
Ответ 4
Я только что затронул ту же проблему и придумал два решения.
-
Используйте класс PHPExcel, как предлагается bpeterson76.
- С помощью этого класса создается наиболее широко совместимый файл, я смог создать файл из кодированных UTF-8 данных, которые отлично открылись в Excel 2008 Mac, Excel 2007 Windows и Google Docs.
- Самая большая проблема с использованием PHPExcel заключается в том, что он медленный и использует много памяти, что не является проблемой для файлов с разумным размером, но если ваш файл Excel/CSV содержит сотни или тысячи строк, эта библиотека становится непригодной.
-
Вот PHP-метод, который будет принимать некоторые данные TSV и выводить файл Excel в браузер, обратите внимание, что он использует Excel5 Writer, что означает, что файл должен быть совместим со старыми версиями Excel, но у меня больше нет доступа к каким-либо, поэтому я не могу их протестировать.
function excel_export($tsv_data, $filename) {
$export_data = preg_split("/\n/", $tsv_data);
foreach($export_data as &$row) {
$row = preg_split("/\t/", $row);
}
include("includes/PHPExcel.php");
include('includes/PHPExcel/Writer/Excel5.php');
$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
$sheet = $objPHPExcel->getActiveSheet();
$row = '1';
$col = "A";
foreach($export_data as $row_cells) {
if(!is_array($row_cells)) { continue; }
foreach($row_cells as $cell) {
$sheet->setCellValue($col.$row, $cell);
$col++;
}
$row += 1;
$col = "A";
}
$objWriter = new PHPExcel_Writer_Excel5($objPHPExcel);
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="'.$filename.'.xls"');
header('Cache-Control: max-age=0');
$objWriter->save('php://output');
exit;
}
-
Из-за проблем с производительностью с PHPExcel мне также пришлось выяснить, как создать файл CSV или TSV, совместимый с UTF-8 и Excel.
- Лучшее, что я мог придумать, - это файл, который был совместим с Excel 2008 Mac и компьютером Excel 2007, но не с документами Google, что достаточно для моего приложения.
- Я нашел решение здесь, в частности, этот ответ, но вы также должны прочитать принятый ответ, поскольку он объясняет проблему.
-
Вот код PHP, который я использовал, обратите внимание, что я использую данные tsv (вкладки как разделители вместо запятых):
header ( 'HTTP/1.1 200 OK' );
header ( 'Date: ' . date ( 'D M j G:i:s T Y' ) );
header ( 'Last-Modified: ' . date ( 'D M j G:i:s T Y' ) );
header ( 'Content-Type: application/vnd.ms-excel') ;
header ( 'Content-Disposition: attachment;filename=export.csv' );
print chr(255) . chr(254) . mb_convert_encoding($tsv_data, 'UTF-16LE', 'UTF-8');
exit;
Ответ 5
Excel не поддерживает UTF-8. Вы должны кодировать текст UTF-8 в UCS-2LE.
mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
Ответ 6
У меня была такая же проблема, и она была решена, как показано ниже:
header('Content-Encoding: UTF-8');
header('Content-Type: text/csv; charset=utf-8' );
header(sprintf( 'Content-Disposition: attachment; filename=my-csv-%s.csv', date( 'dmY-His' ) ) );
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
$df = fopen( 'php://output', 'w' );
//This line is important:
fputs( $df, "\xEF\xBB\xBF" ); // UTF-8 BOM !!!!!
foreach ( $rows as $row ) {
fputcsv( $df, $row );
}
fclose($df);
exit();
Ответ 7
Чтобы следить за этим:
Похоже, что проблема просто в Excel на Mac. Это не то, как я генерирую файлы, потому что даже генерация CSV из Excel нарушает их. Я сохраняю CSV и reimport, и все символы перепутаны.
Итак... похоже, нет правильного ответа на этот вопрос. Спасибо за все предложения.
Я бы сказал, что из всего, что я прочитал, предложение Даниэля Маглиолы о спецификации, вероятно, будет лучшим ответом для другого компьютера. Но он все еще не решает мою проблему.
Ответ 8
Файл CSV содержит знак байтового заказа.
Или, как предложено и обходным путем, просто эхо его с телом HTTP
Ответ 9
Так как кодировка UTF8 не очень хорошо работает с Excel. Вы можете преобразовать данные в другой тип кодирования с помощью iconv()
.
например.
iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
Ответ 10
Добавить
fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
Или:
fprintf($file, "\xEF\xBB\xBF");
Перед записью любого содержимого в файл CSV.
Пример:
<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "বাংলা"]);
fclose($file);
Ответ 11
Это отлично работает как для Windows, так и для Mac OS.
Исправлены проблемы в excel, которые не отображают символы, содержащие диакритические знаки, кириллические буквы, букву греческого алфавита и символы валюты.
function writeCSV($filename, $headings, $data) {
//Use tab as field separator
$newTab = "\t";
$newLine = "\n";
$fputcsv = count($headings) ? '"'. implode('"'.$newTab.'"', $headings).'"'.$newLine : '';
// Loop over the * to export
if (! empty($data)) {
foreach($data as $item) {
$fputcsv .= '"'. implode('"'.$newTab.'"', $item).'"'.$newLine;
}
}
//Convert CSV to UTF-16
$encoded_csv = mb_convert_encoding($fputcsv, 'UTF-16LE', 'UTF-8');
// Output CSV-specific headers
header('Set-Cookie: fileDownload=true; path=/'); //This cookie is needed in order to trigger the success window.
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename.csv\";" );
header("Content-Transfer-Encoding: binary");
header('Content-Length: '. strlen($encoded_csv));
echo chr(255) . chr(254) . $encoded_csv; //php array convert to csv/excel
exit;
}
Ответ 12
Как я выяснил, и я обнаружил, что UTF-8 плохо работает на MAC и Windows, поэтому я попытался с Windows-1252, он хорошо поддерживает оба из них, но вы должны выбрать тип кодирования на ubuntu.
Вот мой код $valueToWrite = mb_convert_encoding($value, 'Windows-1252');
$response->headers->set('Content-Type', $mime . '; charset=Windows-1252');
$response->headers->set('Pragma', 'public');
$response->headers->set('Content-Endcoding','Windows-1252');
$response->headers->set('Cache-Control', 'maxage=1');
$response->headers->set('Content-Disposition', $dispositionHeader);
echo "\xEF\xBB\xBF"; // UTF-8 BOM
Ответ 13
В моем случае следующие работы очень приятно сделать CSV файл с символами UTF-8 корректно отображаемым в Excel.
$out = fopen('php://output', 'w');
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($out, $some_csv_strings);
Заголовок 0xEF 0xBB 0xBF
BOM позволит Excel узнать правильную кодировку.
Ответ 14
Как только вывести сам Excel? Это отличный класс, который позволяет создавать файлы XLS на стороне сервера. Я часто использую его для клиентов, которые не могут "выяснить" csv и до сих пор никогда не получали жалобы. Он также позволяет некоторое дополнительное форматирование (затенение, строки, расчеты и т.д.), Которые csv никогда не будет делать.
Ответ 15
вы можете конвертировать CSV-строку с iconv.
например:
$csvString = "Möckmühl;in Möckmühl ist die Hölle los\n";
file_put_contents('path/newTest.csv',iconv("UTF-8", "ISO-8859-1//TRANSLIT",$csvString) );
Ответ 16
Вы должны использовать кодировку "Windows-1252".
header('Content-Encoding: Windows-1252');
header('Content-type: text/csv; charset=Windows-1252');
header("Content-Disposition: attachment; filename={$filename}");
Возможно, вам нужно преобразовать строки:
private function convertToWindowsCharset($string) {
$encoding = mb_detect_encoding($string);
return iconv($encoding, "Windows-1252", $string);
}
Ответ 17
Для меня ни одно из вышеприведенных решений не работало. Ниже приводится то, что я сделал для решения проблемы:
измените значение с помощью этой функции в коде PHP:
$value = utf8_encode($value);
Этот вывод правильно выводится на листе excel.
Ответ 18
У меня была такая же проблема, когда у меня была процедура Excel VBA, которая импортировала данные. Поскольку CSV - это простой текстовый формат, я работал над этим, программно открывая данные в простом редакторе файлов, например wordpad, и повторно сохраняя его как текст в формате Unicode или копируя его в буфер обмена оттуда и вставляя его в Excel. Если excel автоматически не анализирует CSV в ячейках, это легко исправить, используя встроенную функцию "Текст в столбцы".
Ответ 19
Проблема возникает, когда вы сохраняете ее как .txt файл, и они открываются в excel с запятой в качестве разделителя?
Проблема может быть не в кодировке вообще, возможно, просто, что файл не является идеальным CSV в соответствии с стандартами excel.
Ответ 20
Эта почта довольно старая, но после нескольких часов попыток я хочу поделиться своим решением... возможно, это помогает кому-то, кто имеет дело с Excel, Mac и CSV, и спотыкается об этой угрозе. Я генерирую csv динамически как вывод из базы данных с пользователями Excel. (UTF-8 с спецификацией)
Я пробовал много iconv'ов, но не мог получить немецкие умлауты, работающие в Mac Excel 2004. Одно из решений: PHPExcel. Это здорово, но для моего проекта слишком много. Что для меня работает - это создать файл csv и преобразовать этот CSV файл в xls с помощью этого PHPsnippet: csv2xls. результат xls работает с excel german umlauts (ä, ö, Ü,...).
Ответ 21
Я просто попробовал эти заголовки и получил Excel 2013 на ПК под управлением Windows 7, чтобы правильно импортировать CSV файл со специальными символами. Знак байтового заказа (BOM) был последним ключом, который заставлял его работать.
header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
header("Content-disposition: attachment; filename=filename.csv");
header("Pragma: public");
header("Expires: 0");
echo "\xEF\xBB\xBF"; // UTF-8 BOM
Ответ 22
Вы можете добавить 3 байта в файл перед экспортом, он работает для меня. Перед тем как сделать эту систему работать только в Windows и HP -UX, но не удалось в Linux.
FileOutputStream fStream = new FileOutputStream( f );
final byte[] bom = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
OutputStreamWriter writer = new OutputStreamWriter( fStream, "UTF8" );
fStream.write( bom );
У вас есть спецификация UTF-8 (3 байта, hex EF BB BF) в начале файла. В противном случае Excel будет интерпретировать данные в соответствии с вашим стандартом кодировки по умолчанию (например, cp1252) вместо utf-8
Создание CSV файла для Excel, как иметь новую строку внутри значения
Ответ 23
В противном случае вы можете:
header("Content-type: application/x-download");
header("Content-Transfer-Encoding: binary");
header("Content-disposition: attachment; filename=".$fileName."");
header("Cache-control: private");
echo utf8_decode($output);
Ответ 24
Преобразование уже закодированного utf-8 текста с помощью mb_convert_encoding
не требуется. Просто добавьте три символа перед исходным контентом:
$newContent = chr(239) . chr(187) . chr(191) . $originalContent
Для меня это решило проблему специальных символов в файлах csv.
Ответ 25
Решение EASY для Mac Excel 2008:
Я много раз боролся с этим су, но здесь было мое легкое решение:
Откройте CSV файл в Textwrangler, который должен правильно открыть символы UTF-8. Теперь в нижней строке состояния измените формат файла с "Unicode (UTF-8)" на "Western (ISO Latin 1)" и сохраните файл.
Теперь перейдите в свой Mac Excel 2008 и выберите "Файл" > "Импорт" > "Выбрать csv" > "Найти свой файл" > "Происхождение файла" выберите "Windows (ANSI)" и отобразите символы UTF-8 правильно. По крайней мере, это для меня...
Ответ 26
Я использую это, и он работает
header('Content-Description: File Transfer');
header('Content-Type: text/csv; charset=UTF-16LE');
header('Content-Disposition: attachment; filename=file.csv');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
// output headers so that the file is downloaded rather than displayed
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
fputs( $output, "\xEF\xBB\xBF" );
// output the column headings
fputcsv($output, array('Thông tin khách hàng đăng ký'));
// fetch the data
$setutf8 = "SET NAMES utf8";
$q = $conn->query($setutf8);
$setutf8c = "SET character_set_results = 'utf8', character_set_client =
'utf8', character_set_connection = 'utf8', character_set_database = 'utf8',
character_set_server = 'utf8'";
$qc = $conn->query($setutf8c);
$setutf9 = "SET CHARACTER SET utf8";
$q1 = $conn->query($setutf9);
$setutf7 = "SET COLLATION_CONNECTION = 'utf8_general_ci'";
$q2 = $conn->query($setutf7);
$sql = "SELECT id, name, email FROM myguests";
$rows = $conn->query($sql);
$arr1= array();
if ($rows->num_rows > 0) {
// output data of each row
while($row = $rows->fetch_assoc()) {
$rcontent = " Name: " . $row["name"]. " - Email: " . $row["email"];
$arr1[]["title"] = $rcontent;
}
} else {
echo "0 results";
}
$conn->close();
// loop over the rows, outputting them
foreach($arr1 as $result1):
fputcsv($output, $result1);
endforeach;
Ответ 27
Я нахожусь на Mac, в моем случае мне просто нужно было указать разделитель с "sep=;\n"
и закодировать файл в UTF-16LE следующим образом:
$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
Ответ 28
# вывести UTF-8 CSV в PHP, который Excel будет читать правильно.
//Use tab as field separator
$sep = "\t";
$eol = "\n";
$fputcsv = count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';
Ответ 29
**This is 100% works fine in excel for both Windows7,8,10 and also All Mac OS.**
//Fix issues in excel that are not displaying characters containing diacritics, cyrillic letters, Greek letter and currency symbols.
function generateCSVFile($filename, $headings, $data) {
//Use tab as field separator
$newTab = "\t";
$newLine = "\n";
$fputcsv = count($headings) ? '"'. implode('"'.$newTab.'"', $headings).'"'.$newLine : '';
// Loop over the * to export
if (! empty($data)) {
foreach($data as $item) {
$fputcsv .= '"'. implode('"'.$newTab.'"', $item).'"'.$newLine;
}
}
//Convert CSV to UTF-16
$encoded_csv = mb_convert_encoding($fputcsv, 'UTF-16LE', 'UTF-8');
// Output CSV-specific headers
header('Set-Cookie: fileDownload=true; path=/'); //This cookie is needed in order to trigger the success window.
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename.csv\";" );
header("Content-Transfer-Encoding: binary");
header('Content-Length: '. strlen($encoded_csv));
echo chr(255) . chr(254) . $encoded_csv; //php array convert to csv/excel
exit;
}
Ответ 30
//convert UTF-8 file without BOM to UTF-16LE for excel on mac
$fileUtf8String = file_get_contents("file.ext");
file_put_contents("file.ext", "\xFF\xFE" . mb_convert_encoding($fileUtf8String, "UTF-16LE", "UTF-8"));