我以编程方式将数据(使用PHP 5.2)导出到.csv测试文件中。
示例数据:Numéro 1
(注意重音e)。数据是utf-8
(没有前置BOM)。
当我在MS Excel中打开此文件时显示为Numéro 1
。
我可以在文本编辑器(UltraEdit)中打开它,正确显示它。 UE报告该字符是decimal 233
。
如何在.csv文件中导出文本数据以便MS Excel正确呈现它,最好不强制使用导入向导或非默认向导设置?
正确格式化的UTF8文件可以将Byte Order Mark作为其前三个八位字节。这些是十六进制值0xEF,0xBB,0xBF。这些八位字节用于将文件标记为UTF8(因为它们与“字节顺序”信息无关).1如果此BOM不存在,则消费者/读者可以推断文本的编码类型。不支持UTF8的读取器将读取字节作为一些其他编码,如Windows-1252,并在文件的开头显示字符
。
有一个已知的错误,在通过文件关联打开UTF8 CSV文件时,Excel假定它们采用单字节编码,而忽略了UTF8 BOM的存在。任何系统默认代码页或语言设置都无法解决此问题。 BOM不会在Excel中发现 - 它只是不起作用。 (少数报告声称BOM有时会触发“导入文本”向导。)此错误似乎存在于Excel 2003及更早版本中。大多数报告(在此处的答案中)表示这已在Excel 2007及更新版本中得到修复。
请注意,您始终可以使用“导入文本”向导在Excel中正确打开UTF8 CSV文件,该向导允许您指定要打开的文件的编码。当然这不太方便。
这个答案的读者最有可能是他们不特别支持Excel <2007,但是将原始的UTF8文本发送到Excel,这会误解它并用Ã
和其他类似的Windows-1252字符散布文本。添加UTF8 BOM可能是您最好,最快的修复方法。
如果您遇到旧版Excel上的用户,并且Excel是CSV的唯一使用者,则可以通过导出UTF16而不是UTF8来解决此问题。 Excel 2000和2003将双击 - 正确打开它们。 (其他一些文本编辑可能会遇到UTF16问题,因此您可能需要仔细权衡您的选项。)
*除非您不能,(至少)Excel 2011 for Mac的导入向导实际上并不总是适用于所有编码,无论您告诉它什么。 </轶事 - 证据> :)
您可以使用扩展名“xls”保存html文件,并且重音符号将起作用(至少2007年之前)。
示例:将此(在记事本中使用另存为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>
这只是字符编码的问题。看起来您将数据导出为UTF-8:UTF-8中的é是双字节序列0xC3 0xA9,在Windows-1252中解释时是é。将数据导入Excel时,请务必告诉它您使用的字符编码是UTF-8。
CSV格式在Excel中实现为ASCII,而不是unicode,从而破坏了变音符号。我们遇到了同样的问题,就是我如何跟踪官方CSV标准被定义为基于ASCII的Excel。
Excel 2007使用BOM(EF BB BF)编码的csv正确读取UTF-8。
Excel 2003(可能更早)使用BOM(FF FE)读取UTF-16LE,但使用TAB而不是逗号或分号。
我只能在Excel 2007中正确解析CSV作为制表符分隔的小端UTF-16,从正确的字节顺序标记开始。
将BOM写入输出CSV文件实际上在Django中对我有用:
def handlePersoonListExport(request):
# Retrieve a query_set
...
template = loader.get_template("export.csv")
context = Context({
'data': query_set,
})
response = HttpResponse()
response['Content-Disposition'] = 'attachment; filename=export.csv'
response['Content-Type'] = 'text/csv; charset=utf-8'
response.write("\xEF\xBB\xBF")
response.write(template.render(context))
return response
了解更多信息http://crashcoursing.blogspot.com/2011/05/exporting-csv-with-special-characters.html谢谢你们!
我发现的另一个解决方案是将结果编码为Windows代码页1252(Windows-1252或CP1252)。这样做,例如通过将Content-Type
适当地设置为类似text/csv; charset=Windows-1252
并类似地设置响应流的字符编码。
请注意,包括UTF-8 BOM不一定是个好主意 - Mac版本的Excel会忽略它,并且实际上会将BOM显示为ASCII ...电子表格中第一个字段开头的三个令人讨厌的字符......
检查生成文件的编码,要使Excel正确显示文件,必须使用系统默认代码页。
你用哪种语言?如果它是.Net,你只需要在生成文件时使用Encoding.Default。
如果您在vb.net中有遗留代码,就像我一样,以下代码对我有用:
Response.Clear()
Response.ClearHeaders()
Response.ContentType = "text/csv"
Response.Expires = 0
Response.AddHeader("Content-Disposition", "attachment; filename=export.csv;")
Using sw As StreamWriter = New StreamWriter(Context.Response.OutputStream, System.Text.Encoding.Unicode)
sw.Write(csv)
sw.Close()
End Using
Response.End()
预先设置BOM(\ uFEFF)对我有用(Excel 2007),因为Excel将文件识别为UTF-8。否则,保存它并使用导入向导可以工作,但不太理想。
我找到了解决问题的方法。这是一个讨厌的黑客,但它的工作原理:用Open Office打开文档,然后将其保存为任何excel格式;由此产生的.xls
或.xlsx
将显示突出的字符。
使用Ruby 1.8.7,我将每个字段编码为UTF-16并丢弃BOM(可能)。
以下代码从active_scaffold_export中提取:
<%
require 'fastercsv'
fcsv_options = {
:row_sep => "\n",
:col_sep => params[:delimiter],
:force_quotes => @export_config.force_quotes,
:headers => @export_columns.collect { |column| format_export_column_header_name(column) }
}
data = FasterCSV.generate(fcsv_options) do |csv|
csv << fcsv_options[:headers] unless params[:skip_header] == 'true'
@records.each do |record|
csv << @export_columns.collect { |column|
# Convert to UTF-16 discarding the BOM, required for Excel (> 2003 ?)
Iconv.conv('UTF-16', 'UTF-8', get_export_column_value(record, column))[2..-1]
}
end
end
-%><%= data -%>
重要的是:
Iconv.conv('UTF-16', 'UTF-8', get_export_column_value(record, column))[2..-1]
在Encode上打开带有notepad ++ clic的文件csv,选择转换为UTF-8(不转换为UTF-8(无BOM))用exc的双clic保存打开希望帮助Christophe GRISON
下面是我在向用户发送Microsoft Excel时在项目中使用的PHP代码:
/**
* 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;
}
更新:文件名改进和BUG修复正确的长度计算。感谢TRiG和@ivanhoe011
所有Excel版本(2003 + 2007)和文件类型组合的答案
这里的大多数其他答案仅涉及他们的Excel版本,并不一定会帮助您,因为他们的答案可能不适用于您的Excel版本。
例如,添加BOM字符会引入自动列分隔符识别的问题,但不会引入每个Excel版本的问题。
有3个变量可确定它是否适用于大多数Excel版本:
SAP坚忍的人尝试了每一种组合并报告了结果。最终结果?使用带有BOM和制表符的UTF16le作为分隔符,使其适用于大多数Excel版本。
你不相信我?我也不会,但在这里阅读并哭泣:http://wiki.sdn.sap.com/wiki/display/ABAP/CSV+tests+of+encoding+and+column+separator
在输出CSV数据之前回显UTF-8 BOM。这修复了Windows中的所有字符问题,但不适用于Mac。
echo "\xEF\xBB\xBF";
它适用于我,因为我需要生成一个仅在Windows PC上使用的文件。
在没有任何服务包的情况下,UTF-8在办公室2007中不起作用,有或没有BOM(U + ffef或0xEF,0xBB,0xBF,都不起作用)安装sp3使UTF-8工作时0xEF,0xBB,0xBF BOM是前缀。
UTF-16在python中使用“utf-16-le”进行编码,前面加上0xff 0xef BOM,并使用tab作为分隔符。我不得不手动写出BOM,然后使用“utf-16-le”而不是“utf-16”,否则每个encode()都会将BOM前置到写出的每一行,这些行在第一列上显示为垃圾。第二行和之后。
无法判断UTF-16是否可以在没有安装任何sp的情况下工作,因为我现在无法返回。叹
这是在windows上,dunno关于MAC的办公室。
对于这两种工作情况,导入在直接从浏览器启动下载并且文本导入向导不干预时起作用,它的工作方式与您期望的一样。
正如弗雷格尔所说,\ 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
%>
我也注意到这个问题在前一段时间“已经回答”但是我不明白那些说你不能在不使用文本向导的情况下在Excel中成功打开utf8编码的csv文件的故事。
我可重现的经验:在记事本中键入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
好。记事本在前面放了一个BOM。
现在进入Windows资源管理器,双击文件名,或右键单击并使用“打开方式...”,然后向上弹出Excel(2003)并按预期显示。