简体   繁体   English

为 Excel 导出 CSV

[英]Export CSV for Excel

I'm writing a CSV file in PHP using fputcsv($file, $data) .我正在使用fputcsv($file, $data)在 PHP 中编写一个 CSV 文件。 It all works, however I can't just open it in Excel but have to import it and specify the encoding and which delimiter to use (in a wizard).一切正常,但是我不能只在 Excel 中打开它,而是必须导入它并指定编码和要使用的分隔符(在向导中)。 I've seen exports from other websites that open correctly just by clicking on them and now would like to know what I should do to my file to achieve that.我已经看到其他网站的导出,只需单击它们即可正确打开,现在想知道我应该对我的文件做什么才能实现这一目标。

I tried using this library: http://code.google.com/p/parsecsv-for-php/ But I couldn't even get it to run and am not really confident if it would really help me...我尝试使用这个库: http : //code.google.com/p/parsecsv-for-php/但我什至无法让它运行,我也不确定它是否真的能帮助我......

This is how I make Excel readable CSV files from PHP :这就是我从 PHP 制作 Excel 可读 CSV 文件的方法:

  • Add BOM to fix UTF-8 in Excel添加 BOM 以修复 Excel 中的 UTF-8
  • Set semi-colon (;) as delimeter将分号 (;) 设置为分隔符
  • Set correct header ("Content-Type: text/csv; charset=utf-8")设置正确的标题 ("Content-Type: text/csv; charset=utf-8")

For exemple :举个例子 :

$headers = array('Lastname :', 'Firstname :');
$rows = array(
    array('Doe', 'John'),
    array('Schlüter', 'Rudy'),
    array('Alvarez', 'Niño')
);

// Create file and make it writable

$file = fopen('file.csv', 'w');

// Add BOM to fix UTF-8 in Excel

fputs($file, $bom = (chr(0xEF) . chr(0xBB) . chr(0xBF)));

// Headers
// Set ";" as delimiter

fputcsv($file, $headers, ";");

// Rows
// Set ";" as delimiter

foreach ($rows as $row) {

    fputcsv($file, $row, ";");
}

// Close file

fclose($file);

// Send file to browser for download

$dest_file = 'file.csv';
$file_size = filesize($dest_file);

header("Content-Type: text/csv; charset=utf-8");
header("Content-disposition: attachment; filename=\"file.csv\"");
header("Content-Length: " . $file_size);
readfile($dest_file);

Works with Excel 2013.适用于 Excel 2013。

this is really a mess.这真是一团糟。 You surely can use the sep=;你当然可以使用 sep=; or sep=, or sep=\\t or whatever to make Excel aware of a separator used in your CSV.或 sep= 或 sep=\\t 或任何使 Excel 知道您的 CSV 中使用的分隔符的东西。 Just put this string at the beginning of your CSV contents.只需将此字符串放在 CSV 内容的开头即可。 Eg:例如:

fwrite($handle, "sep=,\n");

fputcsv($handle,$yourcsvcontent);

This works smoothly.这工作顺利。 BUT, it doesn't work in combination with a BOM which is required to make Excel aware of UTF-8 in case you need to support special characters or MB respectively.但是,如果您需要分别支持特殊字符或 MB,它不能与使 Excel 知道 UTF-8 所需的 BOM 结合使用。

In the end to make it bullet-proof you need to read out users locale and set the Separator accordingly, as mentioned above.最后,要使其防弹,您需要读出用户区域设置并相应地设置分隔符,如上所述。 Put a BOM ("\\xEF\\xBB\\xBF") at the begining of your CSV content, then write the CSV like eg: fputcsv($handle, $fields, $user_locale_seperator);在 CSV 内容的("\\xEF\\xBB\\xBF")放置一个 BOM ("\\xEF\\xBB\\xBF") ,然后像这样编写 CSV: fputcsv($handle, $fields, $user_locale_seperator); where $user_locale_seperator is the separtator you retrieved by checking the user's locale.其中$user_locale_seperator是您通过检查用户的语言环境检索到的分隔符。 Not comfortable but it works...不舒服,但它有效......

Despite the "C=comma" in CVS, Excel uses your locale native separator.尽管 CVS 中有“C=逗号”,但 Excel 使用您的语言环境本机分隔符。 So supposing fputcsv always uses a comma, it won't work, if your locale separator is for example a semicolon.因此,假设fputcsv始终使用逗号,如果您的区域设置分隔符是分号,则它将不起作用。

What Google AdSense does, when you click "Export to Excel CSV" , is that it uses Tab as a separator.当您点击“导出到 Excel CSV”时,Google AdSense 的作用是使用Tab作为分隔符。 And that works.这有效。

To replicate that, set the third parameter ( delimiter ) of fputcsv to override the default comma.要复制它,请设置fputcsv的第三个参数 ( delimiter ) 以覆盖默认逗号。 Eg for Tab use: fputcsv($handle, $fields, "\\t");例如对于Tab使用: fputcsv($handle, $fields, "\\t");

Compare the format of the CSV that works for you against the one generated by fputcsv .将适用于您的 CSV 格式与fputcsv生成的格式进行比较。

Consider including example of both in your question.考虑在您的问题中包含两者的示例。 You might get better answers.你可能会得到更好的答案。

I notice that you need to consider: Content-Type header BOM (Byte Order Mark) Actual character encoding in the file我注意到你需要考虑: Content-Type header BOM (Byte Order Mark) 文件中的实际字符编码

With BOM (works):使用 BOM(作品):

$bom = pack("CCC", 0xEF, 0xBB, 0xBF);
header('Content-Type: text/csv');
header('Content-Length: '.(strlen($csv)+strlen($bom)));
header('Content-Disposition: attachment;filename=my.csv');
echo $bom;
echo $csv;

Without BOM (works but you need to replace “smart quotes” then run utf8_decode on each value or cell, and it converts some characters, for example FRĒ is converted to FRE')没有 BOM(有效,但您需要替换“智能引号”,然后在每个值或单元格上运行utf8_decode ,它会转换一些字符,例如 FRĒ 被转换为 FRE')

header('Content-Type: application/csv;charset=utf-8');
header('Content-Length: '.strlen($csv));
header('Content-Disposition: attachment;filename=my.csv');
echo $csv;

If the wrong combination of charset and BOM are used, it just comes out wrong when opening in MS Excel.如果使用了错误的字符集和 BOM 组合,在 MS Excel 中打开时就会出错。

Bonus fact: mb_strlen tells you the number of characters, strlen tells you the number of bytes.额外的事实: mb_strlen告诉您字符数, strlen告诉您字节数。 You do NOT want to use mb_strlen for calculating the Content-Length header.希望使用mb_strlen计算Content-Length头。

Bonus 2: replace microsoft "smart" characters (em dash, curly quotes, etc):奖励 2:替换微软的“智能”字符(破折号、卷曲引号等):

$map = array(chr(145) => "'"
            ,chr(146) => "'"
            ,chr(147) => '"'
            ,chr(148) => '"'
            ,chr(149) => '-'
            ,chr(150) => '-'
            ,chr(151) => '-'
            ,chr(152) => '-'
            ,chr(152) => '-'
            ,chr(171) => '-'
            ,chr(187) => '-'
);
// faster that strtr
return str_replace( array_keys($map), $map, $str );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM