Как я могу вывести UTF-8 CSV в 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
ing эти данные, я не пишу ни одного файла. Я могу сделать это, если мне нужно, я просто не потому, что в этом нет необходимости. Любой помочь?
обновление: я попытался повторить спецификацию как echo pack("CCC", 0xef, 0xbb, 0xbf);
который я только что вытащил с сайта, который пытался обнаружить спецификацию. Но Excel просто добавляет эти три символа в самую первую ячейку при импорте и все еще путает специальные символы.
30 ответов:
цитата инженер службы поддержки 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 и электронная таблица Google Doc не имеют проблем с UTF-8 файлами с запятыми.
посмотреть таблица в этом вопросе для того, что работает и не работает для файлов CSV Unicode в Excel
в качестве примечания, я мог бы добавить, что если вы используете композитор, вы должны взглянуть на добавление
League\Csv
к вашим требованиям.League\Csv
и очень хороший API для создание CSV файлов.использовать
League\Csv
С помощью этого метода создания CSV-файлов, проверьте
У меня такая же (или похожая) проблема.
в моем случае, если я добавляю спецификацию к выходу, она работает:
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.
вот как я это сделал (то есть, чтобы предложить браузеру загрузить файл 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 preview, когда вы нажмете пробел на Mac.. но не в Excel 2008 для Mac... не знаю, почему
Я просто имел дело с той же проблемой, и придумал два решения.
использовать 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 PC, но не Google Docs, что достаточно хорошо для моего приложения.
- я нашел решение здесь, в частности ответ, но вы также должны прочитать принято отвечать как это объясняет проблему.
вот 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;
Excel не поддерживает UTF-8. Вы должны закодировать свой текст UTF-8 в UCS-2LE.
mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
У меня была та же проблема и она была решена, как показано ниже:
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();
чтобы следить за этим:
похоже, что проблема просто с Excel на Mac. Это не так, как я генерирую файлы, потому что даже генерация CSVs из Excel ломает их. Я сохраняю как CSV, и реимпорт, и все символы перепутались.
Итак ... похоже, что на это нет правильного ответа. Спасибо за все предложения.
Я бы сказал, что из всего, что я прочитал ,предложение @ Daniel Magliola о BOM вероятно, лучшим ответом на другом компьютере. Но это все еще не решает мою проблему.
CSV-файл musst содержит метку порядка байтов.
или, как было предложено и обходной путь просто эхо его с телом HTTP
Это прекрасно работает в excel как для 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; }
поскольку кодировка UTF8 не очень хорошо работает с Excel. Вы можете преобразовать данные в другой тип кодировки с помощью
iconv()
.например
iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
добавить:
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);
Как я исследовал , и я обнаружил, что 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
в моем случае следующие работы очень приятно сделать CSV-файл с UTF-8 символов отображается правильно в Excel.
$out = fopen('php://output', 'w'); fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF)); fputcsv($out, $some_csv_strings);
The
0xEF 0xBB 0xBF
заголовок спецификации позволит Excel знать правильную кодировку.
Как насчет просто вывода для самого Excel? Это отличный класс что позволяет создавать файлы XLS на стороне сервера. Я часто использую его для клиентов, которые не могут "понять" csv и до сих пор никогда не жаловались. Он также позволяет использовать дополнительное форматирование (затенение, rowheights, вычисления и т. д.), которое csv никогда не будет делать.
вы можете конвертировать 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) );
вы должны использовать кодировку "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); }
Я на Mac, в моем случае мне просто нужно было указать разделитель с
"sep=;\n"
и закодировать файл в UTF-16LE следующим образом:$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
для меня ни одно из решений выше не работало. Ниже то, что я сделал, чтобы решить проблему: измените значение с помощью этой функции в PHP-коде:
$value = utf8_encode($value);
это выходные значения правильно в листе excel.
**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; }
У меня была такая же проблема, когда у меня была процедура Excel VBA, которая импортировала данные. Поскольку CSV-это простой текстовый формат, я работал над этим, программно открывая данные в простом редакторе файлов, таком как wordpad, и повторно сохраняя его как текст unicode, или копируя его в буфер обмена оттуда и вставляя его в Excel. Если excel автоматически не анализирует CSV в ячейки, это легко исправить с помощью встроенной функции "текст в Столбцы".
проблема все еще возникает, когда вы сохраняете его как a .txt файл и их открыть, что в excel с запятой в качестве разделителя?
проблема может быть не в кодировке вообще, это может быть просто то, что файл не является идеальным CSV в соответствии со стандартами excel.
этот пост довольно старый, но после нескольких часов попыток я хочу поделиться своим решением ... может быть, это помогает кому-то иметь дело с Excel и Mac и CSV и натыкается на эту угрозу. Я генерирую csv динамически как вывод из базы данных с пользователями Excel в виду. (UTF-8 с BOM)
Я пробовал много iconvs, но не мог заставить немецких умлаутов работать в Mac Excel 2004. Одно решение: PHPExcel. Это здорово, но для моего проекта слишком много. То, что работает для меня, - это создание csv-файла и преобразуйте этот csv-файл в xls с помощью этого PHPsnippet: csv2xls. результат xls работает с немецкими умлаутами excel (ä,ö, Ü,...).
Я просто попробовал эти заголовки и получил 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
вы можете добавить 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 BOM (3 байта, hex EF BB BF) в начале файла. В противном случае Excel будет интерпретировать данные в соответствии с кодировкой по умолчанию вашей локали (например, cp1252) вместо utf-8
создание CSV-файла для Excel, как иметь новую строку внутри значения
в противном случае вы можете:
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);
преобразование уже utf-8 кодированный текст с помощью
mb_convert_encoding
не требуется. Просто добавьте три символа перед оригинальным контентом:$newContent = chr(239) . chr(187) . chr(191) . $originalContent
для меня это решило проблему специальных символов в csv-файлах.
простое решение для Mac Excel 2008: Я боролся с этим Су много раз, но вот мое легкое решение: Открывай .csv-файл в Textwrangler, который должен правильно открыть ваши символы UTF-8. Теперь в нижней строке состояния измените формат файла с " Unicode (UTF-8)" на "Western (ISO Latin 1)" и сохраните файл. Теперь перейдите на свой Mac Excel 2008 и выберите Файл > импорт > выберите csv > найти файл > в источнике файла выберите "Windows (ANSI)" и вуаля символы UTF-8 отображаются правильно. По крайней мере, это делает для меня...
Я использую это и это работает
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;