CSVをExcelで開くにはBOMをつけておけば良い
UTF-8のCSVファイルでも、BOMをつけておけば、Excelで開けるということを昨日知りました!
Rubyでサンプルを書いてみます。
# frozen_string_literal: true
require 'csv'
File.open('with_bom.csv', 'w:UTF-8') do |file|
bom = "\uFEFF"
headers = ['id', 'first name', 'last name', 'age']
csv_data = CSV.generate(+bom, headers: headers, write_headers: true) do |csv|
csv << ['1', '太郎', '田中', '20']
csv << ['2', '次郎', '鈴木', '18']
csv << ['3', '亜海', '佐藤', '19']
csv << ['4', '祐実', '安達', '21']
csv << ['5', '三郎', '近藤', '34']
end
file.write(csv_data)
end
CSVファイルの内容はCSV.generateのリファレンスマニュアルを漢字に書き換えました。
注意事項
# frozen_string_literal: true
をファイルの先頭につけていて、文字列が凍結されるので、CSV.generateに渡すbomを +bom
と書いて解凍しています。解凍を忘れると、 not opened for writing (IOError)
でエラーになってしまいますよ。
コメントを受けての追記(2020-01-09 14:19)
もう少し適切な形に書き換えてみました。
# frozen_string_literal: true
require 'csv'
BOM = "\uFEFF"
headers = ['id', "first\nname", "last\nname", 'age']
data = [
{ id: '1', first_name: '太郎', last_name: '田中', age: '20' },
{ id: '2', first_name: '次郎', last_name: '鈴木', age: '18' },
{ id: '3', first_name: '亜海', last_name: '佐藤', age: '19' },
{ id: '4', first_name: '祐実', last_name: '安達', age: '21' },
{ id: '5', first_name: '三郎', last_name: '近藤', age: '34' }
]
File.open('with_bom.csv', 'w:UTF-8') do |file|
file.write BOM
csv = CSV.new(file, headers: headers, write_headers: true)
data.each do |row|
csv << [row[:id], row[:first_name], row[:last_name], row[:age]]
end
end
現実のCSV出力をイメージして、データをループで出力するような形にしました。
CSVファイルの内容を一時的な文字列として作成すると、巨大になる恐れもあるので、ファイル出力の形に変えてみました。
BOMをつけるとExcelで開けるという話でしたが、実は改行を含んでいても適切に開けるという点もメリットです。それを表現するためにわざわざ改行コードを入れてみました。
元々は、「CSV.generateに渡す文字列が凍結されているとエラーになるので注意!」というつもりで書いたエントリーだったのですが、CSV.generateを使わなくなっちゃいましたね。。。