Итак, у нас есть это веб-приложение, где мы поддерживаем данные UTF8. Hooray UTF8. И мы можем экспортировать предоставленные пользователем данные в CSV без проблем - он все еще находится в UTF8 в этот момент. Проблема заключается в том, что вы открываете типичный UTF8 CSV в Excel, он читает его как текст, закодированный ANSII, и, соответственно, пытается читать двухбайтовые символы, такие как ø и ü, как два отдельных символа, и в итоге вы получаете сбой.
Итак, я немного поработал (у Intervals у людей интересный пост об этом здесь), и есть некоторые ограничения, если смехотворно раздражающие варианты. Среди них:
- предоставление файла TSV UTF-16 Little Endian, который Excel будет интерпретировать правильно, но который не поддерживает многострочные данные.
- предоставление данных в таблице HTML с расширением mime файла или расширения Excel (не уверен, поддерживает ли этот параметр UTF8)
- Есть три или четыре способа получить XML-данные в различные последние версии excel, и они будут поддерживать UTF8 в теории. SpreadsheetML, используя пользовательский XSLT или создавая новый формат Excel XML с помощью шаблонов.
Похоже, что бы то ни было, я, вероятно, захочу продолжать предлагать простой старый CSV файл для людей, которые в любом случае не используют его для Excel, и отдельный вариант загрузки для Excel.
Какой самый простой способ создания этого файла Just-for-Excel, который будет правильно поддерживать UTF8, мои дорогие? Если этот самый простой вариант поддерживает только последнюю версию Excel, которая все еще интересует.
Я делаю это в стеке Rails, но любопытно, как это делают .Net-пользователи и люди на любых фреймворках. Я сам работаю в нескольких разных средах, и это определенно проблема, которая снова встанет.
Обновление 2010-10-22: Мы использовали камень Ruport в нашей системе отслеживания времени Tempo, чтобы предоставить экспорт CSV когда я впервые разместил этот вопрос. Один из моих коллег, Эрик Холленсби, бросил быстрый фильтр для Ruport, чтобы предоставить нам фактический вывод Excel XSL, и я решил, что я поделился бы этим здесь для любых других рубинов:
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