9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

`# frozen_string_literal: true` 内でBOM付きCSVファイルを生成する

Last updated at Posted at 2020-01-09

CSVをExcelで開くにはBOMをつけておけば良い

UTF-8のCSVファイルでも、BOMをつけておけば、Excelで開けるということを昨日知りました!

Rubyでサンプルを書いてみます。

with_bom_csv.rb
# 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

with_bom.csv in Excel
CSVファイルの内容はCSV.generateのリファレンスマニュアルを漢字に書き換えました。

注意事項

# frozen_string_literal: true をファイルの先頭につけていて、文字列が凍結されるので、CSV.generateに渡すbomを +bom と書いて解凍しています。解凍を忘れると、 not opened for writing (IOError) でエラーになってしまいますよ。

コメントを受けての追記(2020-01-09 14:19)

もう少し適切な形に書き換えてみました。

with_bom_csv.rb
# 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

with_bom.csv with CR in Excel
現実のCSV出力をイメージして、データをループで出力するような形にしました。
CSVファイルの内容を一時的な文字列として作成すると、巨大になる恐れもあるので、ファイル出力の形に変えてみました。
BOMをつけるとExcelで開けるという話でしたが、実は改行を含んでいても適切に開けるという点もメリットです。それを表現するためにわざわざ改行コードを入れてみました。

元々は、「CSV.generateに渡す文字列が凍結されているとエラーになるので注意!」というつもりで書いたエントリーだったのですが、CSV.generateを使わなくなっちゃいましたね。。。

参考

9
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?