こんにちは
元業務系プログラマ村上です。
業務系システムに必要な機能の1つに「Excel出力」というものがあります。
Javaをやっていたときは「Apache POI」を使ってExcelファイルの作成をしていました。
じゃあ、Rubyにもないのか?
ってことで調べてみるとありました。
「spreadsheet」というgemがあるようです。
spreadsheetについて
1 |
gem install spreadsheet |
ってして、もしくはGemfileに書いて「bundle install」 準備はOK
そして次のコードを実行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# coding: UTF-8 require 'rubygems' require 'spreadsheet' Spreadsheet.client_encoding = 'UTF-8' # セルのセルスタイルの設定 class NormalFormat < Spreadsheet::Format def initialize(opts = {}) self.border = :thin super(opts.merge(:size => 11, :top_color => :black, :top_color => :black, :bottom_color => :black, :left_color => :black, :right_color => :black)) end end # タイトルセルのスタイルを設定 class TitleFormat < NormalFormat def initialize super(:color => :red, :weight => :bold) end end # 複数セルにまとめてセルフォーマットを設定するものがなかったので、メソッドで定義 def set_row_format(row, from_idx, to_idx, format) from_idx.upto(to_idx) do |index| row.set_format(index, format) end end # ワークブックの生成 POIと同じように「ワークブック」⇒「ワークシート」⇒「行」⇒「セル」という構成です。 book = Spreadsheet::Workbook.new normal_format = NormalFormat.new title_format = TitleFormat.new sheet = book.create_worksheet(:name => "member list") # タイトルセルをまとめて設定 配列で設定できる。 配列の先頭に空文字を入れたかったので、unshiftしてます。 sheet.row(1).concat((%w(名前 姓 名 アルファベット 性別 誕生日 電話番号 郵便番号 出身地)).unshift('')) sheet.row(1).height = 14 set_row_format(sheet.row(1), 1, 9, title_format) # データの1行目 sheet.row(2).height = 14 set_row_format(sheet.row(2), 1, 9, normal_format) sheet[2, 1] = '山田太郎' sheet[2, 2] = '山田' sheet[2, 3] = '太郎' sheet[2, 4] = 'Taro Yamada' sheet[2, 5] = '男' sheet[2, 6] = '1983-06-27' sheet[2, 7] = '06-0000-0000' sheet[2, 8] = '630-0003' sheet[2, 9] = '大阪市内' # データの2行目 sheet.row(3).height = 14 set_row_format(sheet.row(3), 1, 9, normal_format) sheet[3, 1] = '田中一郎' sheet[3, 2] = '田中' sheet[3, 3] = '一郎' sheet[3, 4] = 'Ichiro Tanaka' sheet[3, 5] = '男' sheet[3, 6] = '1981-03-27' sheet[3, 7] = '06-1000-0000' sheet[3, 8] = '630-0003' sheet[3, 9] = '神戸市' # データの3行目 sheet.row(4).height = 14 set_row_format(sheet.row(4), 1, 9, normal_format) sheet[4, 1] = '鈴木花子' sheet[4, 2] = '鈴木' sheet[4, 3] = '花子' sheet[4, 4] = 'Hanako Suzuki' sheet[4, 5] = '女' sheet[4, 6] = '1986-02-10' sheet[4, 7] = '06-2000-0000' sheet[4, 8] = '630-0003' sheet[4, 9] = '横浜市' # 保存!! book.write "ruby-excel-#{Time.now.strftime("%Y%m%d%H%M%S")}.xls" |
実行したExcelファイルは
な感じです。
(横幅は見やすいように変更しています。)
RubyでもExcel出力は問題なくできそうですね。
Java Apache POI との比較
気になるのはレスポンスとメモリの消費量です。
POIの時もExcelのそれぞれのcellやスタイルをオブジェクトとして保持するため、大量データのExcel出力には向きませんでした。
なのでちょいとレスポンスを測ってみましょう。
比較対象は「Apache POI」です。
1000行のシートを100シート出力する際の処理時間は
Java (Apache POI) | Ruby (spreadsheet) |
---|---|
0.78秒 | 53.32秒 |
Java爆速です。。。
まとめ
RubyでもExcel出力することは可能なようです。
でも、Excelのバージョンに追従したり、細かいフォーマットスタイルの調整といったコードを書くのはすごく大変です。
前は、2003形式と2007形式を選択可能にしたり、改ページの設定などに大変苦労した記憶があります。
帳票系は会議資料などに使われたりするので、見栄えというのが重要になります。
そのため、画面と同じぐらい変更要望が入ることが多いので、レイアウト部分とデータ生成部分は分けて作る必要があります。
あと、JavaとRubyで比較しましたが、1アプリケーションの中で異なる言語やフレームワークを使うということは稀だと思うので、ここでは「Java、RubyともにExcel出力ができそうだ。」というぐらいに受け取っていただければと思います。