Microsoft Excel在.csv文件中破坏了音标符号?

207

我通过 PHP 5.2 编程方式将数据导出到 .csv 测试文件中。
例如数据:Numéro 1(请注意重音符号的e)。 数据是 utf-8 格式(没有前置 BOM)。

当我在 MS Excel 中打开此文件时,它显示为 Numéro 1

我能够在文本编辑器(UltraEdit)中打开并正确显示。 UE 报告该字符为 十进制 233

我该如何导出文本数据到 .csv 文件中,以便 MS Excel 能够正确呈现,最好不需要强制使用导入向导或非默认向导设置?


3
选择的工作解决方案是:
  • 包括一个BOM; utf-8
  • 使用此标题:'Content-type: text/plain; charset=utf-8'
这在Excel 2003和Excel 2007上“可行”--其中“可行”=无需导入向导即可打开并正确呈现变音符号。我没有验证是否需要BOM。
- Freddo411
2
需要BOM,我刚刚测试过了。没有它,特殊字符无法正确显示。 - Alex Ciminian
2
希望有人能够更详细地说明如何添加BOM(字节顺序标记)。如果我只是像Response.Write(EF BB BF")这样做,那么这些字符就会出现在文件的开头。 - sydneyos
请查看以下链接: https://dev59.com/BGIk5IYBdhLWcg3wNrq8#20952812 这对我也有效。 - jacob spitzer
看看这个: https://dev59.com/BGIk5IYBdhLWcg3wNrq8#20952812 对我来说非常好用。 - jacob spitzer
显示剩余3条评论
22个回答

1

在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'),也可以参见如何在java中添加UTF-8 BOM - tsauerwein
看看这个。对我也有效。 - jacob spitzer

1

我只能在Excel 2007中以制表符分隔的小端UTF-16格式开始于正确的字节顺序标记下正确解析CSV。


1

Excel 2007 可以正确读取带有 BOM (EF BB BF) 编码的 UTF-8 csv 文件。

Excel 2003(以及可能更早版本)可以读取带有 BOM (FF FE) 的 UTF-16LE 文件,但是使用制表符而不是逗号或分号。


1
这只是一个字符编码的问题。看起来你正在将数据导出为UTF-8:在UTF-8中,é是由两个字节0xC3 0xA9组成的序列,而在Windows-1252中解释时则是é。当你将数据导入Excel时,请确保告诉它你正在使用的字符编码是UTF-8。

我已确认数据是UTF-8编码。我需要在文件中添加什么内容,让Excel知道我的数据是UTF-8编码?(是否需要BOM?) - Freddo411
我认为您需要更改文件编码,Excel使用系统默认代码页来处理CSV文件。 - albertein
我不是很确定,因为我当前使用的机器上没有安装Excel,但是在OpenOffice中,当您导入CSV文件时,会有一个字符编码下拉框。从那里选择Unicode(UTF-8)。 - Adam Rosenfield
据我所知,Excel没有下拉菜单。 - albertein
看看这个。对我也有效。 - jacob spitzer

1

CSV格式在Excel中是以ASCII而不是Unicode实现的,因此会破坏变音符号。我们遇到了同样的问题,这就是我追踪官方CSV标准被定义为基于ASCII的原因。


实际上,CSV并没有绑定到特定的编码。是Excel假定了ASCII编码。http://en.wikipedia.org/wiki/Comma-separated_values - spoulson
这就是我说的。“在Excel中实现为ASCII”,“在Excel中定义CSV为基于ASCII的”。不确定你想表达什么观点,因为你似乎同意我的看法。 - Jeff Yates
2
实际上,你说"CSV格式是以ASCII实现的",我认为这就是混淆的根源所在。 - RichardOD

1
我发现的另一个解决方案是将结果编码为Windows Code Page 1252(Windows-1252或CP1252)。例如,可以通过适当设置Content-Typetext/csv; charset=Windows-1252并类似地设置响应流的字符编码来完成此操作。

谢谢这个。在Excel Windows和Mac上都可以使用。我正在使用它。 - Sebastian Sastre
只有在你的非ASCII字符范围完全落在Windows-1252之内,这个方法才有效。所以例如,没有韩文/中文/日文,没有西里尔文等等。不过我猜对于大多数西欧语言来说,这种做法还是可以勉强适用的。 - Tom McClure

1
请注意,包括UTF-8 BOM并不一定是一个好主意 - Excel的Mac版本会忽略它,并且实际上会将BOM显示为ASCII...这是您电子表格中第一个字段开头的三个讨厌字符。

我知道这条评论是6年后的,但是FWIW:在Mac Excel 15.19.1(2016)上使用JavaScript下载文件,例如'\uFEFF' + myCsvString,可以按预期工作。 - bobjones

0

使用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]

0

请检查您生成文件时使用的编码,为了使Excel正确显示文件,您必须使用系统默认代码页。

您使用的是哪种语言?如果是 .Net,您只需要在生成文件时使用 Encoding.Default 即可。


导出的数据是 utf-8 编码。我正在使用 php 5 写入导出文件。 - Freddo411
转码数据为Windows-1252代码页,我不确定如何在php中实现。 - albertein

0
我找到了解决问题的方法。这是一个不太正规但有效的办法:用Open Office打开文档,然后保存成任意Excel格式;保存后的.xls或.xlsx文件将会显示带重音符号的字符。

1
OP说他正在进行程序化导出,因此他不需要需要手动干预的解决方案。 - Christiaan Westerbeek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接