【実践】RailsでExcelレポート出力(その1)


業務アプリケーションであれば、必ずと言っていいほど、レポート出力機能を作成する必要があるでしょう。PDF出力でよいのならThinReportsがオススメですが、Excelで出力したいことも度々ありますよね。今回はその方法をチュートリアル的にご紹介します。

環境

  • Rails 4.0.2
  • Excel 2007
  • Mac OS X 10.8

出力するレポート

完成イメージです。日別・商品別の売上をクロス集計したレポートです。これをRailsから出力します。

report

サンプルアプリのER図

Product(商品)モデルとSale(売上)モデルの2つだけです。Product has_many Sales の関係になっています。

erd

まずはExcelで完成イメージを作る

Excelを起動して、普通に完成イメージを作成します。本サンプルの完成イメージは以下のように作成してみました。

excel

その他にも・・・

  • ページフッターにコピーライトと印刷時刻を表示
  • A4横1枚印刷できるようページ設定

なんてことをしています。

日付や金額は適当ですが、入力しています。面倒臭がらずにちゃんと入力しておいた方が後々便利です。

作成が完了したら、当然ファイルを保存する必要があるわけですが、ここで重要なポイントがあります。以下のように、xmlスプレッドシート形式で保存するということです。

save

保存が完了したら、Excelでの作業は完了です。この時点で、しっかりとレイアウトに関して検討しておきましょう。これから「後から修正すればいいや」とはいかない世界に入っていくので・・・

コーディング

さて、いよいよコーディングに入っていきます。まずは足場(scaffold)を作っておきます。

📄product.rb
$ rails g scaffold Product name:string
$ rails g scaffold Sale product_id:integer sales_date:date amount:integer

2つのモデルを作成しました。それぞれの関連(association)を定義しておきましょう。

class Product < ActiveRecord::Base
  has_many :sales
end
📄sale.rb
class Sale < ActiveRecord::Base
  belongs_to :product
end

レポートを出力するためのルーティング、コントローラを作成します。

📄routes.rb
ExcelReport::Application.routes.draw do
  resources :sales

  resources :products

  controller :report do
    get 'report' => 'report#index', as: :report
    get 'report/output', as: :output_report
  end
end
📄report_controller.rb
class ReportController < ApplicationController
  def index
  end

  def output
    #TODO
  end
end

outputメソッドはまだ実装していません。先にindexのビューを実装します。app/views/report/index.html.erbを作成します。

📄index.html.erb
<h1>月間売上出力</h1>

<%= form_tag output_report_path(format: :xls), method: :get do %>
  <p>
    <%= label_tag :year, '年' %>
    <%= text_field_tag :year %>
  </p>
  <p>
    <%= label_tag :month, '月' %>
    <%= text_field_tag :month %>
  </p>
  <%= submit_tag '出力' %>
<% end %>

output_report_path に format: :xls を指定しているのがポイントです。出力ボタンをクリックしたときに遷移するパスは report/output.xls になります。画面が正しく描画できるか、試しに report/ にアクセスしてみましょう。

index

ダサいながらも、ちゃんと表示することができましたね。それでは、試しに出力ボタンをクリックしてみましょうか。

TemplateMissing

予定通りTemplate is missingのエラーが表示されました。確かに何もテンプレートを置いていないので当然といえば当然。とりあえず、既に作成済みのxmlスプレッドシートを表示させてみましょう。

xmlスプレッドシートを、app/views/report/output.xls.erb として配置します。拡張子をxls.erbにするのを忘れずに! 配置したら、もう一度出力ボタンをクリックしてみてください。

結果は・・・ああ! まだ Template is missingのままです。何故このエラーが出るのかというと、xlsというMimeTypeがrailsに登録されていないためです。正しく出力させるには、railsの設定を変更する必要があります。

config/initializers/mime_types.rbに1行追記します。

📄mime_types.rb
# Be sure to restart your server when you modify this file.

# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
# Mime::Type.register_alias "text/html", :iphone
Mime::Type.register "application/xls", :xls

編集が完了したら、アプリを再起動してから再度出力ボタンをクリックしてみます。

download

おお! なんかダウンロードできてしまいましたよ! さっそくExcelで開いてみると・・・(小生意気な警告ダイアログが出たら「はい」と答えてあげる)

dowload-xls

作成したまんまのExcelシートが開きました! とりあえずですが、これでアプリケーションとしての疎通は確認できました。

長くなってしまったので、今回はここまでとします。次回はこのExcelテンプレートを編集して、動的に値を変更して出力する方法をご紹介します。

関連する記事