将UTF8数据导出到Excel的最佳方法是什么?

28
我们有一个支持UTF8数据的web应用程序,可以将用户提供的数据导出到CSV文件中,这时数据仍然是UTF8编码。问题在于,当你在Excel中打开一个典型的UTF8 CSV文件时,它会将其读取为ANSII编码的文本,并尝试将像ø和ü这样的双字节字符作为两个单独的字符读取,从而导致失败。
经过一番挖掘(Intervals的人们在这里有一篇有趣的文章),我们发现有一些非常令人恼火的有限选项,其中包括:
  • 提供一个UTF-16小端TSV文件,Excel会正确解释该文件,但不支持多行数据
  • 提供一个带有Excel MIME类型或文件扩展名的HTML表格(不确定此选项是否支持UTF8)
  • 有三到四种方法可以将XML数据导入到各个最新版本的Excel中,这些方法理论上支持UTF8。电子表格ML,使用自定义XSLT,或通过模板生成新的Excel XML格式。
看起来无论怎样,我可能还想继续为那些不使用Excel的人提供一个普通的CSV文件,以及一个专门为Excel设计的单独下载选项。
亲爱的Stack Overflowers,生成那个正确支持UTF8的"Just-For-Excel"文件的最简单方法是什么呢?如果这个最简单的选项只支持最新版本的Excel,那也很有趣。
我正在使用Rails堆栈进行此操作,但是好奇.Net开发人员和任何框架上的人如何处理此问题。我自己在几个不同的环境中工作,这绝对是一个将再次出现的问题。
更新2010-10-22:当我第一次发布这个问题时,我们一直在我们的时间跟踪系统Tempo中使用Ruport gem来提供CSV导出。我的一位同事Erik Hollensbee为Ruport快速编写了一个过滤器,以向我们提供实际的Excel XSL输出,我想在这里分享给其他ruby-ists。
require 'rubygems'
require 'ruport'
require 'spreadsheet'
require 'stringio'

Spreadsheet.client_encoding = "UTF-8"

include Ruport::Data

class Ruport::Formatter::Excel < Ruport::Formatter
  renders :excel, :for => Ruport::Controller::Table

  def output
    retval = StringIO.new

    if options.workbook
      book = options.workbook
    else
      book = Spreadsheet::Workbook.new
    end

    if options.worksheet_name
      book_args = { :name => options.worksheet_name }
    else
      book_args = { }
    end

    sheet = book.create_worksheet(book_args)

    offset = 0

    if options.show_table_headers
      sheet.row(0).default_format = Spreadsheet::Format.new(
        options.format_options || 
        { 
          :color => :blue,
          :weight => :bold,
          :size => 18
        }
      )
      sheet.row(0).replace data.column_names
      offset = 1
    end

    data.data.each_with_index do |row, i|
      sheet.row(i+offset).replace row.attributes.map { |x| row.data[x] }
    end

    book.write retval
    retval.seek(0)
    return retval.read
  end
end
8个回答

9
我发现,如果您将网页的字符集编码设置为utf-8,然后在csv文件顶部使用Response.BinaryWrite输出UTF-8字节顺序标记(0xEF 0xBB 0xBF),那么Excel 2007(不确定其他版本)将识别它为utf-8并正确打开它。

我在这里发布了一些代码,可以实现这个功能 - http://stackoverflow.com/a/9907364/150342 - Colin
如何在Java中添加UTF-8 BOM的讨论可参见https://dev59.com/fW855IYBdhLWcg3wXS8I。 - Piran

7

在为同一个问题苦苦挣扎了几个小时后,我发现了这篇关于该主题的优秀文章

http://blog.plataformatec.com.br/2009/09/exporting-data-to-csv-and-excel-in-your-rails-app/ 引用:

因此,处理与Excel兼容的CSV文件有以下三条规则:

  1. 使用制表符而不是逗号。
  2. 字段不能包含换行符。
  3. 使用UTF-16 Little Endian将文件发送给用户。并手动包含一个Little Endian BOM。

然而,如果你正在使用ruby,你的问题就可以解决: 首先你需要FasterCSV gem

但我最终使用了生成excel电子表格的spreadsheet gem (我有链接限制,请在谷歌上搜索spreadsheet + rubyforge) 太棒了!


5
你忘记创建一个OleDB数据源和Excel Interop,但这些也存在问题。
我建议使用SpreadsheetML选项。它运行良好,你的平台很可能有一些不错的工具来构建xml文件,并且它完全支持OfficeXP。 Office2000不支持,但个人经验是它在有限的方式下工作。

你忘记了...一个OleDB...嘘!这是一个Unix环境,所以我想避免那种巫术。谢谢你的提示! - Billy Gray
@Richard - 因为第二段不依赖于oledb。尽管从发布超过1年半后的更新中,应该有一个答案指向Ruby Rupert。 - Joel Coehoorn

1

我在查找有关Ruby的答案时发现这篇帖子,解决了Excel无法正确加载具有utf-8字符的CSV文件的问题。经过搜索和实验,这个解决方案对我有效:

csv_content = CSV.generate(col_sep: "\t", headers: :first_row, encoding: 'utf-8') do |csv|
  csv << ["header1", "header2"]
  csv << ["content1", "content2"]
end
write_content = Iconv.conv("utf-16le", "utf-8", "\xEF\xBB\xBF")
write_content += Iconv.conv("utf-16le", "utf-8", csv_content)
File.open("listing.csv", 'wb') {|f| f.write(write_content) }

1
如果您使用utf编码创建XML并将其保存为.xls文件,则即使是双字节字符也可以打开它:
xml version="1.0" encoding="utf-8"

我曾尝试将表格数据保存为扩展名为.xls的XML文档,然后在Excel for Mac 2003中打开它,但程序无法解析。我们的不少用户都是Mac用户。 - Billy Gray
1
我从来没有在MAC上尝试过,但它应该能够工作。XML是一种标准。 - Rulas

1

我曾经遇到过将UTF8数据发送到Excel的问题,我的解决方案如下:

当前版本的Perl Spreadsheet::WriteExcel cpan代码可以正确地使用UTF8数据编写Excel文件。

因此,我编写了一个Rails插件,它: a)打开一个双向管道到一个perl程序 b)逐行将数据发送到perl程序。我使用Yaml作为消息数据格式。(标准Ruby yaml不是UTF8,有一个特殊版本可用,ya2yaml) c)perl程序创建Excel文件 d)当Rails程序通过Yaml消息指示已发送最后一行时,perl程序创建Excel文件并将状态发送回Rails程序。

当然,通过并行进程和管道将perl程序添加到rails项目中非常符合“工程”范畴,而不是“计算机科学”。(它可以完成工作,但不够优雅。)但它确实很好地工作,并节省了我将WriteExcel代码移植到Ruby所需的几周时间。还要注意,当前可用的Ruby WriteExcel端口不处理utf8。

我的软件是宽松的开源,但我还没有发布它。如果你想要它的当前状态,请查看http://sandbox.kluger.com/write_excel_v.5.tar

请注意,您需要在后台进程中创建Excel文件,而不是在Rails控制器的进程中,因为这会阻塞其他浏览器客户端,而您将一直生产Excel文件。我使用DelayedJob插件,效果很好。

希望这可以帮助到你,

Larry


-1

Excel无法正确处理UTF-8编码。您应该使用满足您需求的代码页。

Response.ContentType = "text/plain";
// codepage: 28591, codepage name:iso-8859-1, codepage display name: Western European (ISO)
Response.ContentEncoding = System.Text.Encoding.GetEncoding(28591);

只要添加UTF8签名/BOM(EF BB BF),对我来说似乎工作正常。 - Danny Tuppeny

-3
试试OpenOffice Calc - 它更加友好于Unicode - 导入和导出CSV文件采用UTF-8编码。

3
这个问题是关于如何从一个Web应用程序中导出数据的,以便用户可以在Excel中打开。仅仅告诉所有客户使用OpenOffice可能行不通。请问你需要怎样导出数据才能实现这一目标? - vezult
公正地说,海报是正确的,OpenOffice比Excel更友好地支持Unicode。我来这里是为了找到使用Excel的方法,因为我不想再使用OpenOffice了。 - NielW

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