禁用adblock

Adblock正在阻止网站上的一些内容

ADBlock errore

如何在Excel正确阅读的PHP中输出UTF-8 CSV?

StackOverflow https://stackoverflow.com/questions/4348802
 检查

问题

我有这个非常简单的东西,它只是以CSV格式输出一些东西,但必须是UTF-8。我在TextEdit,TexteDeg或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”或其他任何东西,所以……我有点生气了。

尽管很多人遇到了同样的问题,但我似乎在任何地方都找不到任何明确的解决方案。我最看到的是包括BOM,但我无法完全弄清楚如何做到这一点。如您所见,我只是 echo在此数据中,我没有编写任何文件。如果需要的话,我可以做到这一点,我只是不是因为此时似乎不需要。有帮助吗?

更新:我尝试将BOM回调为 echo pack("CCC", 0xef, 0xbb, 0xbf); 我只是从试图检测BOM的站点中拉出的。但是Excel导入时只将这三个字符附加到第一个单元格上,并且仍然弄乱了特殊字符。

解决方案

去引用 微软支持工程师,

Mac的Excel当前不支持UTF-8

更新,2017年: :在所有版本的Microsoft Excel之前,Mac都是如此 办公室2016. 。较新版本(来自Office 365)现在支持UTF-8。

为了输出Windows和OS X上出色的UTF-8内容,您将需要做两件事:

  1. 确保将UTF-8文本转换为UTF-16LE

    mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
    
  2. 确保添加UTF-16LE字节订单标记

    chr(255) . chr(254)
    

仅在OS X上出现Excel的下一个问题(但是 不是 Windows)将是在查看具有逗号分离值的CSV文件时,Excel只能用一行和所有文本以及第一行的逗号渲染行。

避免这种情况的方法是将选项卡作为您的分离值。

我用了 此功能来自PHP评论 (使用Tabs“ t”代替逗号),并且在OS X和Windows Excel上完美工作。

请注意,要用空列作为行末尾解决问题,我确实必须更改说:

    $field_cnt = count($fields);

    $field_cnt = count($fields)-1;

正如本页上的其他一些评论所说,其他电子表格应用程序,例如OpenOffice Calc,Apple自己的号码和Google Doc的电子表格,对带有逗号的UTF-8文件没有任何问题。

这个问题的桌子 对于excel中的Unicode CSV文件不起作用的方法


附带说明,我可能会补充说,如果您正在使用 作曲家, ,您应该看看添加 League\Csv 满足您的要求。 League\Csv 拥有 一个非常好的用于构建CSV文件的API.

使用 League\Csv 使用这种创建CSV文件的方法,请查看 这个示例

其他提示

我有相同的(或类似)的问题。

就我而言,如果我向输出添加BOM,则可以正常工作:

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();

当您在Mac上击中太空栏时,它唯一修复了CSV预览中的UTF8编码问题。但是在Excel Mac 2008中不知道...不知道为什么

我只是处理了同样的问题,并提出了两个解决方案。

  1. 使用 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;   
      }
      
  2. 由于Phpexcel的效率问题,我还必须弄清楚如何生成UTF-8和Excel兼容CSV或TSV文件。

    • 我能想到的最好的是一个与Excel 2008 Mac和Excel 2007 PC兼容的文件,但Google Docs却不适合我的应用程序。
    • 我找到了解决方案 这里, , 具体来说, 这个答案, ,但您还应该阅读 接受的答案 正如它解释了问题所在。
    • 这是我使用的PHP代码,请注意,我正在使用TSV数据(TABS作为定界符而不是逗号):

      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;
      

我遇到了同样的问题,它的解决方案如下:

    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不支持UTF-8。您必须将UTF-8文本编码到UCS-2LE中。

mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');

跟进这一点:

看来问题仅在Mac上使用Excel。这不是我生成文件的方式,因为即使生成CSV 来自Excel 正在打破它们。我将其保存为CSV和Reimport,所有字符都混乱了。

因此,……似乎没有正确的答案。感谢所有的建议。

我想说的是,从我阅读的所有内容来看,@Daniel Magliola关于BOM的建议可能是其他计算机的最佳答案。但这仍然无法解决我的问题。

在我的情况下,随后的工作非常好,可以在Excel中正确显示使用UTF-8字符的CSV文件。

$out = fopen('php://output', 'w');
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($out, $some_csv_strings);

0xEF 0xBB 0xBF BOM标头将使Excel知道正确的编码。

这在Windows和Mac OS中都可以在Excel中运行良好。

修复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;
}

CSV文件musst包括一个字节订单标记。

或者如建议和解决方法一样,只需与HTTP身体回荡

由于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编码文本的文本 mb_convert_encoding 不需要。只需在原始内容的前面添加三个字符:

$newContent = chr(239) . chr(187) . chr(191) . $originalContent

对我来说,这解决了CSV文件中特殊字符的问题。

当我研究时,我发现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

**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本身? 这是一个很好的课程 这使您可以生成XLS文件服务器端。我经常将其用于无法“弄清楚” CSV的客户,到目前为止从未投诉。它还允许CSV永远不会做的一些额外的格式(阴影,rowheights,计算等)。

您可以使用 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);
}

您可以在导出之前将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解释数据

为Excel生成CSV文件,如何在值中具有newline

我在Mac上,就我而言,我只需要用 "sep=;\n" 并在UTF-16LE中编码文件:

$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');

对我来说,上面的解决方案都没有用。以下是我为解决该问题所做的:使用此函数在PHP代码中修改值:

$value = utf8_encode($value);

此输出在Excel表中正确值。

当我拥有导入数据的Excel VBA例程时,我也遇到了同样的问题。由于CSV是一种纯文本格式,因此我通过在像WordPad这样的简单文件编辑器中打开数据并将其重新保存为Unicode文本,或将其从那里复制到剪贴板并将其粘贴到Excel中,从而围绕此操作。如果Excel不会自动将CSV解析到单元格中,则可以使用内置的“文本到列”功能轻松地对其进行补救。

当您将其保存为.txt文件并将其保存在comma中作为定界符时,问题仍然会发生吗?

问题可能根本不是编码,可能只是根据Excel标准而不是完美的CSV。

这篇文章很古老,但是经过数小时的尝试,我想分享我的解决方案……也许它可以帮助与Excel,Mac和CSV打交道的人,并偶然发现了这种威胁。我正在从数据库中动态生成CSV,并考虑到Excel用户。 (带有BOM的UTF-8)

我尝试了很多ICONV,但无法在Mac Excel 2004中获得德国的Umlauts。一个解决方案:Phpexcel。这很棒,但对我的项目来说太多了。对我有用的是创建CSV文件,并使用此phpsnippet将此CSV文件转换为XLS: CSV2XLS. 。结果XLS与Excel German Umlauts(ä,Ö,ü,...)一起使用。

我刚刚尝试了这些标题,并在Windows 7 PC上获得了Excel 2013,以正确地将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

否则您可以:

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);

Mac Excel 2008的简单解决方案:我多次为此而苦苦挣扎,但这是我的简单修复程序:在Textwrangler中打开.csv文件,该文件应该正确打开您的UTF-8字符。现在,在底部状态栏中,将文件格式从“ Unicode(UTF-8)”更改为“ wester(ISO Latin 1)”,然后保存文件。现在,转到您的Mac Excel 2008,然后选择文件>导入>选择CSV>在文件Origin中找到您的文件>“ Windows(ANSI)”,然后voila utf-8 chars正确显示。至少对我有...

我用这个,它有效

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;

#output在PHP中的UTF-8 CSV,Excel将正确读取。

//Use tab as field separator   
$sep  = "\t";  
$eol  = "\n";    
$fputcsv  =  count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';

//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"));

许可以下: CC-BY-SA归因
不隶属于 StackOverflow