Microsoft Excel 破坏 .csv 文件中的变音符号?
Posted
技术标签:
【中文标题】Microsoft Excel 破坏 .csv 文件中的变音符号?【英文标题】:Microsoft Excel mangles Diacritics in .csv files? 【发布时间】:2010-09-14 09:10:03 【问题描述】:我正在以编程方式将数据(使用 php 5.2)导出到 .csv 测试文件中。
示例数据:Numéro 1
(注意带重音的 e)。
数据为 utf-8
(无前置 BOM)。
当我在 MS Excel 中打开此文件时,显示为 Numéro 1
。
我可以在正确显示它的文本编辑器 (UltraEdit) 中打开它。 UE 报告字符为decimal 233
。
我如何导出文本 .csv 文件中的数据,以便 MS Excel 能够正确呈现它,最好不要强制使用导入向导,或者不使用默认向导设置?
【问题讨论】:
我很想了解更多关于您的 BOM 解决方案的信息,因为我相信我已经尝试过对我不起作用的“EF BB BF”。 选择的工作解决方案是: * 包括 BOM ; utf-8 * 使用此标头:'内容类型:文本/纯文本; charset=utf-8' 这在 excel 2003 和 excel 2007 中“有效”——有效 = 在没有导入向导的情况下打开并正确呈现变音符号。我没有验证是否需要 BOM。 BOM是必填项,我刚刚测试了这个。没有它,特殊字符将无法正常显示。 如果有人能详细说明如何添加 BOM(字节顺序标记),我会很高兴的。如果我只是执行类似 Response.Write(EF BB BF") 之类的操作,那么这些字符只会显示在文件的开头。 sydneyos:正如 Fergal 在下面所说的那样;将 \uFEFF 添加到您的字符串中。 【参考方案1】:这只是字符编码的问题。看起来您正在将数据导出为 UTF-8:UTF-8 中的 é 是两字节序列 0xC3 0xA9,在 Windows-1252 中解释为 é。当您将数据导入 Excel 时,请务必告诉它您使用的字符编码是 UTF-8。
【讨论】:
我已确认数据为 UTF-8。我在文件中输入什么让 excel 知道我的数据是 utf-8(BOM?) 我认为需要更改文件编码,excel使用系统默认codepage处理csv文件 我不完全确定,因为我当前使用的机器上没有安装 Excel,但是使用 OpenOffice,当您导入 CSV 文件时,有一个字符编码下拉框。从那里,选择 Unicode (UTF-8)。 Excel 没有 AFAIK 下拉菜单 查看this。对我也有用。【参考方案2】:检查您生成文件的编码,要使excel正确显示文件,您必须使用系统默认代码页。
您使用哪种语言?如果是 .Net,您只需要在生成文件时使用 Encoding.Default。
【讨论】:
导出数据为utf-8。我正在用 php 5 编写导出文件 将数据转码到 Windows-1252 代码页,我不知道如何用 php 完成它【参考方案3】:CSV 格式在 Excel 中实现为 ASCII,而不是 unicode,从而破坏了变音符号。我们遇到了同样的问题,这就是我发现官方 CSV 标准在 Excel 中被定义为基于 ASCII 的方式。
【讨论】:
其实 CSV 并没有绑定特定的编码。假设 ASCII 是 Excel。 en.wikipedia.org/wiki/Comma-separated_values 我就是这么说的。 “在 Excel 中实现为 ASCII”、“在 Excel 中定义为基于 ASCII 的 CSV”。不知道你在说什么,因为你似乎同意我的观点。 其实你说“CSV 格式被实现为 ASCI”,我想这就是混乱的根源。【参考方案4】:格式正确的 UTF8 文件可以将 Byte Order Mark 作为其前三个八位字节。这些是十六进制值 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 à 和其他类似的 Windows- 1252 个字符。 添加 UTF8 BOM 可能是您最好、最快的解决方法。
如果您在使用旧版 Excel 时遇到用户问题,并且 Excel 是 CSV 的唯一使用者,您可以通过导出 UTF16 而不是 UTF8 来解决此问题。 Excel 2000 和 2003 将正确双击打开这些。 (其他一些文本编辑器可能会遇到 UTF16 问题,因此您可能需要仔细权衡您的选择。)
* 除非你不能,(至少)Excel 2011 for Mac 的导入向导实际上并不总是适用于所有编码,不管你告诉它什么。 轶事证据> :)
【讨论】:
花了我很长时间才找到指定编码的位置。保存对话框 > 工具按钮 > Web 选项 > 编码选项卡。他们确实很擅长隐藏这些重要的事情。 错误:将 BOM 添加到 UTF-8 文件可以正确加载该文件,而不需要 Excel 2007 中的导入向导。 我们发现了和 Victor 今天说的一样的东西(使用 Excel 2010,这是我们可用的全部)。添加 UTF-8 BOM/签名 (EF BB BF) 似乎修复了使用系统默认编码的双击问题,并正确使用了 UTF8 :) 一般而言,UTF-8 编码的文件应该不在前面加上字节顺序标记。 UTF-8 没有可变字节顺序,将其放在那里会破坏 UTF-8 的 ASCII 兼容性。有一些特定的文件格式允许或鼓励使用 UTF-8 仿 BOM,否则应避免使用。 CSV 完全不了解编码,因此任何人都可以猜测给定工具是否会将字节序列 0xEF 0xBB 0xBF 解释为 UTF-8 的指示符;第一个单元格中的不可见控制字符;第一个单元格中的字符
;或完全不同的东西。
@Ian:没有人确切知道它是 UTF-8 with BOM - 0xEF 0xBB 0xBF 在大多数遗留编码中也是一个有效序列(因此它经常被误解为ISO-8859-1 或 cp1252 并显示为 
)。它仅有助于猜测算法,以及专门考虑它的文件格式(例如 XML)。在 UTF-8 文件中包含虚假 BOM 的缺点是您破坏了它们的 ASCII 兼容性(UTF-8 的一个主要卖点)许多不了解编码的文本工具会在面对意想不到的领先虚假 BOM 时崩溃。【参考方案5】:
导入时选择 UTF-8 编码。如果您使用 Office 2007,这是您选择它的地方: 打开文件后。
【讨论】:
这很有用。我已修改问题以询问如何在不求助于向导的情况下执行此操作【参考方案6】:预置 BOM (\uFEFF) 对我有用 (Excel 2007),因为 Excel 将文件识别为 UTF-8。否则,保存它并使用导入向导可以,但不太理想。
【讨论】:
它仍然会打开文本导入向导,所以不同之处在于您可以简单地双击,所以仍然不理想,但无论如何都是唯一已知的解决方案。 对我来说,Excel 2007 不会出现导入向导。 我也没有导入向导 - 如果存在 UTF8 BOM/签名 (EF BB BF),它将按预期工作。 另外,\ufeff
是 UTF-16 (BE) BOM 而不是 UTF-8 BOM
不,@AlastairMcCormack,两者都是,取决于它的编码方式。编码为 UTF-8 的 "\ufeff" 正好是 EF BB BF。 (编码为 UTF-16 将只有两个字节。)【参考方案7】:
正如 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
%>
【讨论】:
只需观察并了解使用 BOM 时 Excel 2007 中如何忽略制表符分隔符。你必须想出更多的东西。【参考方案8】:您可以保存扩展名为“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>
【讨论】:
有趣的选项。它会正确打开文本,但由于某种原因,所有页面都是完全白色的。没有分隔行和列的经典电子表格行(Office for mac) 是的,在 Windows 上的 Office 2007 中也是如此。老实说,它总是让我感到惊讶。 (注意,如果您将border="1"
添加到表格中,您确实会得到行,但只是在 4 个单元格周围:)【参考方案9】:
我还注意到,这个问题前段时间已经“回答”了,但我不明白那些说如果不使用文本向导就无法在 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) 并按预期显示。
【讨论】:
@Cocowalla:嗯,我刚刚尝试过这个(再次;我在发布之前测试过它)并且它适用于 Excel 2007(这是我现在使用的)。您是否通过open('oldmac.csv', 'rb').read()
验证您的输入?
我没有尝试使用 Excel 2007(我知道 Excel 2007 可以很好地读取带有 BOM 的 UTF-8 文件),我尝试使用 Excel 2003
@Cocowalla:当我拥有 Excel 2003 时,它对我有用。您确定您拥有最新的 Excel 2003 服务包吗?您是否按照我的建议验证了您的输入?
我确实验证了记事本在文件开头粘贴了一个 BOM,但我使用的是 Excel 2003 SP2(SP3 可用) - 所以我猜这仅适用于 SP3【参考方案10】:
以下是我在项目中向用户发送 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 2007 中对我有用。最重要的更改是使用制表符而不是逗号(即使它是 .csv 文件)和上面的行这会回显两个字符,然后调用 mb_convert_encoding()。我还必须使用 --enable-mbstring 重新编译 PHP 以获得对 mb_convert_encoding() 的支持。谢谢! 这对我也很有效,谢谢。但是,在 Safari 中,我的控制台中出现错误“资源解释为文档但传输为...”我猜这是 WebKit 的怪癖,判断 ***.com/questions/3899426/…,但也许不是和/或有人找到了解决方案。此外,在您的示例中,我建议进行更改:'Content-Disposition: attachment; filename="'.$filename.'.csv"'
因为 Firefox 需要双引号,否则它将在空格后切断您的文件名。
你为什么输出 CSV (text/csv
) 却称它为 Excel (application/vnd.ms-excel
)?
这很好用!我可以确认它也可以在 Mac 上运行(在 Office 2011 中)。
不应该是header('Content-Length: '. mb_strlen($encoded_csv, 'UTF-16LE'));
吗?【参考方案11】:
Excel 2007 可以正确读取带有 BOM (EF BB BF) 编码的 csv 的 UTF-8。
Excel 2003(可能更早版本)使用 BOM (FF FE) 读取 UTF-16LE,但使用制表符而不是逗号或分号。
【讨论】:
【参考方案12】:我只能让 CSV 在 Excel 2007 中正确解析为制表符分隔的 little-endian UTF-16,从正确的字节顺序标记开始。
【讨论】:
【参考方案13】:在输出 CSV 数据之前回显 UTF-8 BOM。这修复了 Windows 中的所有字符问题,但不适用于 Mac。
echo "\xEF\xBB\xBF";
它对我有用,因为我需要生成一个仅在 Windows PC 上使用的文件。
【讨论】:
并非所有类型的列分隔符或每个 Excel 版本都如此。请阅读下面的答案(暂时如下)。【参考方案14】:在 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谢谢大家!
【讨论】:
是的,这适用于 Excel 2010。在 Java 中使用printWriter.print('\ufeff')
,另请参阅 How to add a UTF-8 BOM in java。
查看this。对我也有用。【参考方案15】:
在 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]
【讨论】:
【参考方案16】:我发现的另一个解决方案是将结果编码为 Windows 代码页 1252(Windows-1252 或 CP1252)。这可以通过例如将Content-Type
适当地设置为text/csv; charset=Windows-1252
并类似地设置响应流的字符编码来完成。
【讨论】:
感谢这个。适用于 excel windows 和 mac。我正在使用它。 这仅在您的非 ascii 字符范围完全在 Windows-1252 范围内时才有效。因此,例如,没有韩文/中文/日文,没有西里尔文等。但我想你会在大多数西欧语言中使用这个。【参考方案17】:我找到了解决问题的方法。这是一个令人讨厌的 hack,但它确实有效:使用 Open Office 打开文档,然后将其保存为任何 excel 格式;生成的 .xls
或 .xlsx
将显示重音字符。
【讨论】:
OP 说他正在以编程方式导出,因此他不是在寻找需要手动干预的解决方案。【参考方案18】:如果您像我一样在 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()
【讨论】:
【参考方案19】:UTF-8 在没有任何服务包的 Office 2007 中对我不起作用,无论是否有 BOM (U+ffef 或 0xEF,0xBB,0xBF 都不起作用) 当 0xEF,0xBB,0xBF BOM 被前置时,安装 sp3 会使 UTF-8 工作。
UTF-16 在 python 中使用带有 0xff 0xef 的“utf-16-le”编码时有效 BOM 前置,并使用制表符作为分隔符。 我不得不手动写出 BOM,然后使用“utf-16-le”而不是“utf-16”, 否则每个 encode() 将 BOM 附加到写出的每一行 在第二行的第一列及之后显示为垃圾。
无法判断 UTF-16 是否可以在没有安装任何 sp 的情况下工作,因为 我现在不能回去了。 叹息
这是在 windows 上的,不知道 MAC 的 office。
对于这两种工作情况,直接从 浏览器和文本导入向导不会干预,它会像您期望的那样工作。
【讨论】:
也适用于 Excel 2011 for Mac。 感谢您的帖子,即使您没有安装office 2007 sp3,也可以使用utf-16le,但BOM应该是0xFF 0xFE【参考方案20】:请注意,包含 UTF-8 BOM 不一定是个好主意 - Mac 版本的 Excel 会忽略它,实际上会将 BOM 显示为 ASCII……电子表格第一个字段开头的三个讨厌的字符……
【讨论】:
我知道这条评论是 6 年后的事,但 FWIW:使用 JavaScript 下载像'\uFEFF' + myCsvString
这样的文件在 Mac Excel 15.19.1 (2016) 上可以正常工作。【参考方案21】:
用notepad++打开文件csv 点击编码,选择转换为 UTF-8(不转换为 UTF-8(无 BOM)) 保存 用excel双击打开 希望有所帮助 克里斯托夫·格里森
【讨论】:
这不能回答问题,因为它应该以编程方式完成,并且不需要用户干预来手动重新保存每个文件【参考方案22】:Excel 版本 (2003 + 2007) 和文件类型的所有组合的答案
这里的大多数其他答案仅涉及他们的 Excel 版本,不一定对您有帮助,因为他们的答案可能不适用于您的 Excel 版本。
例如,添加 BOM 字符会导致自动列分隔符识别出现问题,但并非每个 Excel 版本都会出现问题。
有 3 个变量决定它是否适用于大多数 Excel 版本:
编码 BOM 角色存在 单元格分隔符SAP 的一位坚忍不拔的人尝试了所有组合并报告了结果。最终结果?使用 UTF16le 与 BOM 和制表符作为分隔符,使其在大多数 Excel 版本中工作。
你不相信我吗?我也不会,但在这里阅读并哭泣:http://wiki.sdn.sap.com/wiki/display/ABAP/CSV+tests+of+encoding+and+column+separator
【讨论】:
为什么不直接添加sep=,
或您想使用的任何内容?如果您已经添加了 BOM,我假设您不反对向文件中添加内容。
好吧,实际上,要回答我自己的问题,您不会添加字段分隔符声明,因为它会导致此技巧停止工作。所以基本上它是乱码编码或者如果您的用户有错误的区域设置,您的文件没有被正确解释为 CSV。
utf-16le + BOM(0xFF 0xFE) + tab 是最好的以上是关于Microsoft Excel 破坏 .csv 文件中的变音符号?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以通过 PHP 代码将 excel csv 文件直接打开到 microsoft excel 或其他 excel 支持的应用程序中