I'm developing a part of an application that's responsible for exporting some data into CSV files. The application always uses UTF-8 because of its multilingual nature at all levels. But opening such CSV files (containing e.g. diacritics, cyrillic letters, Greek letters) in Excel does not achieve the expected results showing something like Г„/Г¤, Г–/Г¶. And I don't know how to force Excel understand that the open CSV file is encoded in UTF-8. I also tried specifying UTF-8 BOM EF BB BF, but Excel ignores that.

有什么解决办法吗?

附注:哪些工具可能像Excel一样?


更新

I have to say that I've confused the community with the formulation of the question. When I was asking this question, I asked for a way of opening a UTF-8 CSV file in Excel without any problems for a user, in a fluent and transparent way. However, I used a wrong formulation asking for doing it automatically. That is very confusing and it clashes with VBA macro automation. There are two answers for this questions that I appreciate the most: the very first answer by Alex https://stackoverflow.com/a/6002338/166589, and I've accepted this answer; and the second one by Mark https://stackoverflow.com/a/6488070/166589 that have appeared a little later. From the usability point of view, Excel seemed to have lack of a good user-friendly UTF-8 CSV support, so I consider both answers are correct, and I have accepted Alex's answer first because it really stated that Excel was not able to do that transparently. That is what I confused with automatically here. Mark's answer promotes a more complicated way for more advanced users to achieve the expected result. Both answers are great, but Alex's one fits my not clearly specified question a little better.


更新2

在最后一次编辑5个月后,我注意到Alex的答案不知为何消失了。我真的希望这不是一个技术问题,我希望现在不再有关于哪个答案更好的讨论。所以我认为马克的答案是最好的。


当前回答

找到了ASP的解决方案。使用POM下载UTF8格式的CSV文件:

byte[] csvBytes = Encoding.Default.GetBytes(csvString);
UTF8Encoding utf8 = new UTF8Encoding(true);
byte[] bom = utf8.GetPreamble();
var result = bom.Concat(csvBytes).ToArray();
return new FileContentResult(result, MediaTypeHeaderValue.Parse("text/csv; charset=utf-8"));

Excel是识别下载的CSV文件而不是UTF8。

其他回答

嗨,我正在使用ruby on rails生成CSV。在我们的应用程序中,我们计划使用多语言(I18n),但在windows excel的CSV文件中查看I18n内容时遇到了一个问题。

Linux (Ubuntu)和mac都没问题。

我们发现windows excel需要重新导入数据才能查看实际数据。在导入时,我们将获得更多选择字符集的选项。

但这不能教育每一个用户,所以我们寻找的解决方案是只需双击打开。

然后利用aghuddleston gist确定了在windows excel中以open模式显示数据和bom格式显示数据的方法。在引用时添加。

示例I18n内容

在Mac和Linux中

瑞典语:Förnamn 中文:名字

在Windows中

瑞典语:Förnamn 中文:名字

def user_information_report(report_file_path, user_id)
    user = User.find(user_id)
    I18n.locale = user.current_lang
    open_mode = "w+:UTF-16LE:UTF-8"
    bom = "\xEF\xBB\xBF"
    body user, open_mode, bom
  end

def headers
    headers = [
        "ID", "SDN ID",
        I18n.t('sys_first_name'), I18n.t('sys_last_name'), I18n.t('sys_dob'),
        I18n.t('sys_gender'), I18n.t('sys_email'), I18n.t('sys_address'),
        I18n.t('sys_city'), I18n.t('sys_state'), I18n.t('sys_zip'),
        I18n.t('sys_phone_number')
    ]
  end

def body tenant, open_mode, bom
    File.open(report_file_path, open_mode) do |f|
      csv_file = CSV.generate(col_sep: "\t") do |csv|
        csv << headers
        tenant.patients.find_each(batch_size: 10) do |patient|
          csv <<  [
              patient.id, patient.patientid,
              patient.first_name, patient.last_name, "#{patient.dob}",
              "#{translate_gender(patient.gender)}", patient.email, "#{patient.address_1.to_s} #{patient.address_2.to_s}",
              "#{patient.city}", "#{patient.state}",  "#{patient.zip}",
              "#{patient.phone_number}"
          ]
        end
      end
      f.write bom
      f.write(csv_file)
    end
  end

这里需要注意的重要事项是open mode和bom

open_mode = "w+:UTF-16LE:UTF-8"

好= "\xEF\xBB\xBF"

在写入CSV之前插入BOM

f.write好

f.write (csv_file)

Windows和Mac

双击即可直接打开文件。

Linux (ubuntu)

当打开一个文件时,询问分隔符选项->选择“TAB”

这是一个老问题,但我刚刚遇到过类似的问题,解决方案可能会帮助其他人:

同样的问题是,将CSV文本数据写入文件,然后在Excel中打开生成的. CSV,将所有文本转移到单个列中。在阅读了上面的答案后,我尝试了下面的答案,这似乎可以解决问题。

在创建StreamWriter时应用UTF-8编码。就是这样。

例子:

using (StreamWriter output = new StreamWriter(outputFileName, false, Encoding.UTF8, 2 << 22)) {
   /* ... do stuff .... */
   output.Close();
}

Excel 2013中忽略BOM的错误似乎已经修复。我有同样的问题与西里尔字母,但添加BOM字符\uFEFF确实有帮助。

如果你想让它完全自动化,点击一下,或者从一个网页自动加载到Excel中,但不能生成适当的Excel文件,那么我建议考虑SYLK格式作为替代方案。好吧,它不像CSV那么简单,但它是基于文本的,非常容易实现,它支持UTF-8没有问题。

我写了一个PHP类,接收数据并输出一个SYLK文件,该文件将通过单击文件直接在Excel中打开(或者如果您将文件写入具有正确mime类型的web页面,将自动启动Excel)。你甚至可以添加格式(如粗体,以特定的方式格式化数字等),改变列的大小,或自动调整列的文本,所有的代码可能不超过100行。

通过创建一个简单的电子表格并保存为SYLK,然后用文本编辑器读取它,就可以非常容易地对SYLK进行逆向工程。第一个块是您可以识别的标头和标准数字格式(您只需在创建的每个文件中反刍它们),然后数据只是一个X/Y坐标和一个值。

令人难以置信的是,有这么多答案,但没有一个能回答这个问题:

“当我问这个问题时,我询问了一种打开UTF-8的方法 CSV文件在Excel没有任何问题的用户,……”

被标记为200+赞成的接受答案对我来说是无用的,因为我不想给我的用户如何配置Excel的手册。 除此之外:本手册将适用于一个Excel版本,但其他Excel版本有不同的菜单和配置对话框。每个Excel版本都需要一个手册。

那么问题是如何使Excel显示UTF8数据与一个简单的双击?

好吧,至少在Excel 2007中,如果你使用CSV文件,这是不可能的,因为UTF8 BOM被忽略,你只会看到垃圾。这已经是Lyubomyr Shaydariv问题的一部分:

“我还尝试指定UTF-8 BOM EF BB BF,但Excel忽略了这一点。”

我也有同样的经历:将俄语或希腊语数据写入UTF8 CSV文件,并使用BOM在Excel中生成垃圾:

UTF8 CSV文件内容:

Colum1;Column2
Val1;Val2
Авиабилет;Tλληνικ

Excel 2007的结果:

A solution is to not use CSV at all. This format is implemented so stupidly by Microsoft that it depends on the region settings in control panel if comma or semicolon is used as separator. So the same CSV file may open correctly on one computer but on anther computer not. "CSV" means "Comma Separated Values" but for example on a german Windows by default semicolon must be used as separator while comma does not work. (Here it should be named SSV = Semicolon Separated Values) CSV files cannot be interchanged between different language versions of Windows. This is an additional problem to the UTF-8 problem.

Excel已经存在了几十年。微软这么多年都没能实现CSV导入这样一个基本的功能,真是太遗憾了。


但是,如果您将相同的值放入HTML文件中,并将该文件保存为UTF8文件,文件扩展名为XLS,您将得到正确的结果。

UTF8 XLS文件内容:

<table>
<tr><td>Colum1</td><td>Column2</td></tr>
<tr><td>Val1</td><td>Val2</td></tr>
<tr><td>Авиабилет</td><td>Tλληνικ</td></tr>
</table>

Excel 2007的结果:

你甚至可以在HTML中使用Excel能正确显示的颜色。

<style>
.Head { background-color:gray; color:white; }
.Red  { color:red; }
</style>
<table border=1>
<tr><td class=Head>Colum1</td><td class=Head>Column2</td></tr>
<tr><td>Val1</td><td>Val2</td></tr>
<tr><td class=Red>Авиабилет</td><td class=Red>Tλληνικ</td></tr>
</table>

Excel 2007的结果:

在这种情况下,只有表本身具有黑色边框和线条。如果你想要所有的单元格显示网格线,这在HTML中也是可能的:

<html xmlns:x="urn:schemas-microsoft-com:office:excel">
    <head>
        <meta http-equiv="content-type" content="text/plain; charset=UTF-8"/>
        <xml>
            <x:ExcelWorkbook>
                <x:ExcelWorksheets>
                    <x:ExcelWorksheet>
                        <x:Name>MySuperSheet</x:Name>
                        <x:WorksheetOptions>
                            <x:DisplayGridlines/>
                        </x:WorksheetOptions>
                    </x:ExcelWorksheet>
                </x:ExcelWorksheets>
            </x:ExcelWorkbook>
        </xml>
    </head>
    <body>
        <table>
            <tr><td>Colum1</td><td>Column2</td></tr>
            <tr><td>Val1</td><td>Val2</td></tr>
            <tr><td>Авиабилет</td><td>Tλληνικ</td></tr>
        </table>
    </body>
</html>

这段代码甚至允许指定工作表的名称(这里是“MySuperSheet”)

Excel 2007的结果: