我正在以编程方式将数据(使用 PHP 5.2)导出到 .csv 测试文件中。
示例数据:( Numéro 1
注意带重音的 e)。数据是utf-8
(没有前置 BOM)。
当我在 MS Excel 中打开此文件时,显示为Numéro 1
.
我可以在正确显示它的文本编辑器(UltraEdit)中打开它。UE 报告字符为decimal 233
.
如何在 .csv 文件中导出文本数据,以便MS Excel 正确呈现它,最好不强制使用导入向导或非默认向导设置?
我正在以编程方式将数据(使用 PHP 5.2)导出到 .csv 测试文件中。
示例数据:( Numéro 1
注意带重音的 e)。数据是utf-8
(没有前置 BOM)。
当我在 MS Excel 中打开此文件时,显示为Numéro 1
.
我可以在正确显示它的文本编辑器(UltraEdit)中打开它。UE 报告字符为decimal 233
.
如何在 .csv 文件中导出文本数据,以便MS Excel 正确呈现它,最好不强制使用导入向导或非默认向导设置?
格式正确的 UTF8 文件可以将字节顺序标记作为其前三个八位字节。这些是十六进制值 0xEF、0xBB、0xBF。这些八位字节用于将文件标记为 UTF8(因为它们与“字节顺序”信息无关)。1 如果此 BOM 不存在,则留给消费者/读者来推断文本的编码类型。不支持 UTF8 的阅读器会将字节作为其他编码(例如 Windows-1252)读取,并
在文件开头显示字符。
有一个已知错误,即 Excel 在通过文件关联打开 UTF8 CSV 文件时假定它们采用单字节编码,而忽略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 的导入向导实际上并不总是适用于所有编码,不管你告诉它什么。</轶事证据> :)
预先添加 BOM (\uFEFF) 对我有用 (Excel 2007),因为 Excel 将文件识别为 UTF-8。否则,保存它并使用导入向导可以,但不太理想。
以下是我在向用户发送 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;
}
更新:文件名改进和错误修复正确的长度计算。感谢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 在没有任何服务包的 Office 2007 中对我不起作用,无论有无 BOM(U+ffef 或 0xEF,0xBB,0xBF,均不起作用)安装 sp3 使 UTF-8 在 0xEF,0xBB,0xBF BOM 为前置。
UTF-16 在 python 中使用带有 0xff 0xef BOM 前缀的“utf-16-le”编码并使用制表符作为分隔符时有效。我必须手动写出 BOM,然后使用“utf-16-le”而不是“utf-16”,否则每个 encode() 都会将 BOM 附加到写出的每一行之前,这些行在第一列上显示为垃圾第二行及之后。
不知道 UTF-16 是否可以在没有安装任何 sp 的情况下工作,因为我现在不能回去。叹
这是在windows上,不知道MAC的office。
对于这两种工作情况,直接从浏览器启动下载时导入工作,并且文本导入向导不会干预,它的工作方式与您预期的一样。
正如 Fregal 所说,\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
%>
您可以保存扩展名为“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>
我还注意到这个问题前段时间得到了“回答”,但我不明白那些说如果不使用文本向导就无法在 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) 并按预期显示。
这只是字符编码的问题。看起来您正在将数据导出为 UTF-8:UTF-8 中的 é 是两字节序列 0xC3 0xA9,在 Windows-1252 中解释为 é。当您将数据导入 Excel 时,请确保告诉它您使用的字符编码是 UTF-8。
CSV 格式在 Excel 中实现为 ASCII,而不是 unicode,因此会破坏变音符号。我们遇到了同样的问题,这就是我发现官方 CSV 标准在 Excel 中被定义为基于 ASCII 的方式。
Excel 2007 正确读取带有 BOM (EF BB BF) 编码的 csv 的 UTF-8。
Excel 2003(可能更早)使用 BOM (FF FE) 读取 UTF-16LE,但使用制表符而不是逗号或分号。
我只能让 CSV 在 Excel 2007 中正确解析为制表符分隔的 little-endian UTF-16,从正确的字节顺序标记开始。
在 Django 中,将 BOM 写入输出 CSV 文件实际上对我有用:
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……电子表格第一个字段开头的三个讨厌的字符……</p>
检查您生成文件的编码,要使 excel 正确显示文件,您必须使用系统默认代码页。
您使用哪种语言?如果是 .Net,您只需要在生成文件时使用 Encoding.Default。
使用 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]
我找到了解决问题的方法。这是一个令人讨厌的 hack,但它有效:使用Open Office打开文档,然后将其保存为任何 excel 格式;结果.xls
or.xlsx
将显示重音字符。
如果您像我一样在 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()
使用记事本++ clic 在编码上打开文件 csv,选择转换为 UTF-8(不转换为 UTF-8(不带 BOM))保存通过双击打开的 excel 希望对 Christophe GRISON 有所帮助