色々試してて、多少は形になったのでメモしときます。
まず、RubyでExcelを作らないといけません。色々方法はありますが、というか素直な方法はJRuby+POIなんじゃないかとも思いますが、今回は「spreadsheet」を使います。
spreadsheet ライブラリとは
spreadsheetは普通にgemでインストールできます。
1 | sudo gem install spreadsheet |
spreadsheet自体には、 .to_blob に当たるインスタンスメソッドがありません(ようです)が、書き込み先にFile IOを指定できます。なので、いったんTempfileに書き込んで、 read して send_data する方法で出来るんじゃないかと思いました。
emvironment.rbで require 'spreadsheet' すると、一緒にtempfile.rbも読み込まれる模様です。
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 | class ExcelExportController < ApplicationController def download birds = Bird.find(:all) legend = ["名前", "色", "鳴き声"] book = Spreadsheet::Workbook.new sheet1 = book.create_worksheet(:name => '鳥類') sheet1.row(0).concat legend sheet1.row(0).default_format = Spreadsheet::Format.new( :color => :red, :weight => :bold, :horizontal_align => :center ) sheet1.row(0).height = 12 rownum = 1 birds.each do |bird| sheet1.row(rownum).concat [bird.name, bird.color, bird.twitter] sheet1.row(rownum).height = 12 rownum += 1 end # 横幅を自動調整 legend.size.times do |i| sheet1.column(i).width = sheet1.column(i).max_by(&:size).size * 0.85 end tmpfile = Tempfile.new ["excel_tmp", ".xls"] book.write tmpfile tmpfile.open # reopen send_data( tmpfile.read, :disposition => 'attachment', :type => 'application/octet-stream', :filename => "excel-#{Time.now.strftime('%y%m%d%H%M%S')}-#{'%03d' % rand(999)}.xls" ) tmpfile.close(true) end end |
こんな感じでしょうか。ちなみに、動作検証してません。。特に :type の指定とか怪しいと思う。
色々と読み替えてお使い下さい。
参考になるサイト
- spreadsheet プロジェクトページ
- spreadsheet-0.6.4.1 Documentation
- Linux 上の Ruby で Excel ファイルを作成する
- tempfile – Ruby(旧)リファレンスマニュアル
tips: Tempfile
マニュアルのどこにも書いてませんが、newの引数basenameに配列を渡すと、[元となるファイル名, 拡張子]みたいなTempfileを作れます。
1 | t = Tempfile.new(["temp", ".xls"]) |
ソースはこんな感じでした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Tempfile < DelegateClass(File) #... def make_tmpname(basename, n) case basename when Array prefix, suffix = *basename else prefix, suffix = basename, '' end t = Time.now.strftime("%Y%m%d") path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-#{n}#{suffix}" end private :make_tmpname #... end |




