Rails エクセルを作成してダウンロードする

目的

Rails でDBのデータをエクセルに帳票として出力して、ダウンロードできるようにする
・エクセルは Spreadsheetで作成
・帳票は予めテンプレートを用意し、値を書き込む
・エクセルファイルは画面からダウンロード

課題

・※1:列幅がデフォルトで保存されてしまうので、下記のように指定しても反映されない
・※2:列の削除ができない
・Tempfileでの保存するとファイルが壊れる理由
・xlsxでは使用できない

require 'spreadsheet'
require 'stringio'

def export
    export_template = "#{Rails.root}\\tmp\\excel_template.xls"
    #エンコード
    Spreadsheet.client_encoding = 'UTF-8'
    #テンプレートを開く
    book = Spreadsheet.open(export_template)
    sheet = book.worksheet(0)
    #シートの列幅を変更(※1)
    4.times do |col|
      #数字はエクセル上の値(ピクセルではない)
      sheet.column(col).width = 100
    end
    #シート名変更
    sheet.name = "請求書\s明細"
    #5〜10行を削除(※2)
    (4..9).each do |i|
      sheet.delete_row(i)
    end

    @orders.each_with_index do |order, l|
      #7行目から書き込み
      line = l + 6
      #A列〜F列に値を書き込み
      data = ["", (l + 1), order.address, order.name, order.valume, order.postage]
      sheet.row(line).replace(data)
      # update_row を使うとテンプレートの罫線等の書式設定がデフォルトに戻る
      # sheet.update_row(line, data)
    end
    
    #ディレクトリ固定で保存する場合はpathを指定してwrite
    # file_name = "#{Rails.root}\\帳票_#{Time.now.strftime("%Y%m%d%H%M%S")}.xls"
    # book.write(file_name)

    #Tempfileを使うとエクセルファイルがなぜか壊れてしまう…原因不明
    # tmpfile = Tempfile.new(["excel_tmp", ".xls"])
    # book.write tmpfile
    # tmpfile.open # reopen

    data = StringIO.new ''
    book.write data
    send_data(
      # tmpfile.read,
      data.string,
      :disposition => 'attachment',
      :type => 'application/excel',
      :filename => file_name
    )
  end

参考
http://blog.iotaworks.jp/2013/07/generating-excel-and-download-in-rails.html