1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TL;DR

workbook = RubyXL::Parser.parse_buffer(buffer)
workbook.stream

上記コードはStreamとか書いていますが、巨大TEXTファイルを読み取る時みたいに、一行ずつ読んで性能アップすることはないので、かえって遅くなります。
こちらのメソッドは単にWebサーバーに送信されたExcelファイルを、ファイルハンドラーのままで処理可能にして、明示的に一時ファイルを保存しなくて済むように作られています。

オーソドックスなworkbook = RubyXL::Parser.parse("path/to/Excel/file.xlsx")の方が断然早いですが、そもそもRubyXLやPythonのOpenPyXLのようなサードパーティーモジュールは巨大Excelファイルに不向きです。

巨大Excelファイルをプログラム的に処理するには、現段階Excelの中にVBAを書くしかないと思います。

実験

巨大Excelの作成

require 'benchmark'
require 'rubyXL'

file_path = 'test.xlsx'

# Create a test file
COL_SIZE = 50
ROW_SIZE = 5000

def init_xlsx(col_num, row_num)
  workbook = RubyXL::Workbook.new
  sheet = workbook[0]
  add_cells(sheet, row_num, col_num)

  workbook
end

def add_cells(sheet, col_num, row_num)
  (0...row_num).each_with_index do |row, i|
    sheet.add_cell(row, 0, i)
    (1...col_num).each_with_index do |col, j|
      sheet.add_cell(row, col, "#{i}:#{j}")
    end
  end
end

Benchmark.bm do |x|
  x.report("Create Xlsx:") do
    workbook = init_xlsx(COL_SIZE, ROW_SIZE)
    workbook.write(file_path)

    puts "#{COL_SIZE}*#{ROW_SIZE}"
  end
end

Benchmark

       user     system      total        real
Create Xlsx:50*5000
  4.297000   0.032000   4.329000 (  6.334323)

実は上記50列*5000行のExcelはたっだの1.3MBしかなくて、Excelファイル的にぜんぜん「巨大」とは言えないです。

image.png

Batch

file_path = 'test.xlsx'

Benchmark.bm do |x|
  x.report("Batch: ") do
    workbook = RubyXL::Parser.parse(file_path)
    p workbook[0][0][1].value
    p workbook[0][20][10].value
  end
end

Benchmark

       user     system      total        real
Batch: "0:0"
"20:9"
  8.500000   0.140000   8.640000 ( 13.540754)

Stream

file_path = 'test.xlsx'

Benchmark.bm do |x|
  x.report("Stream: ") do
    f = File.open(file_path)
    workbook = RubyXL::Parser.parse_buffer(f)
    workbook.stream
    p workbook[0][0][1].value
    p workbook[0][20][10].value
  end
end

Benchmark

       user     system      total        real
Stream: "0:0"
"20:9"
 13.797000   0.125000  13.922000 ( 21.485774)

考察

XLSXファイルは、ZIPで固めたXMLファイル(群)である。
ZIPにせよ、XMLにせよStreamで処理できるような単純な構造ではないため、この結果も納得できます。

そもそもRubyXLparse_bufferメソッドは、RubyZipZip::File.open_bufferから来たものなので、本家でも「一時ファイルを保存せず、処理したい時使ってね」としか言ってなくて、勝手にStream的な処理ができて、性能アップできるぞと過大解釈した自分が悪かったです。

image.png
image.png

参考

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?