見出し画像

RubyXLで容量が大きいファイルを扱う方法

なにも考えずにRubyXLを使用すると、エクセルファイルへの書き込みが1回にまとめて行われるため、メモリ不足になることがある。ここでは1行ずつエクセルファイルに書き込みを行うことでメモリ不足を回避する方法を紹介する。

csv_to_xlsx.rb

require 'csv'
require 'rubyXL'

# CSVファイル読み込み
file_name = File.basename(ARGV[0], ".csv")

# エクセルファイル生成
workbook = RubyXL::Workbook.new
worksheet = workbook[0]
workbook.write("#{file_name}.xlsx")

CSV.foreach(ARGV[0]).with_index do |row, row_num| # CSVファイルから1行ずつ読み込む
  workbook = RubyXL::Parser.parse("#{file_name}.xlsx") # 既存のエクセルファイルを開く
  worksheet = workbook['Sheet1'] # エクセルファイルからworksheetを選択
  row.each_with_index do |value, column_num| 
    worksheet.add_cell(row_num, column_num, value)
  end
  workbook.write("#{file_name}.xlsx") # エクセルファイルに出力
end

test.csv

NAME,AGE,SEX
大屋 知佳,57,女
手塚 利恵,22,女
山森 貞治,32,男
二宮 咲来,16,女
中谷 研治,45,男

実行方法

$ ruby csv_to_xlsx.rb test.csv

事前にworkbook.writeでエクセルファイルを生成し、1行ごとにRubyXL::Parser.parseで生成したエクセルファイルを開き、workbook.writeで書き込む点がポイント。こうすることで、変数worksheetに読み込んだデータが蓄積されず、メモリ不足を回避できる。ただし、この方法ではI/O操作が頻繁に発生するため、実行速度が遅くなる点には注意。


いいなと思ったら応援しよう!