そこで、まずはPDFへの出力を検討します。
調べてみると、ruport なるものがありました。インストールは簡単で、
gem install ruport gem install ruport-util |
ActiveRecord から出力するには、
class User < ActiveRecord::Base acts_as_reportable end class RuportController < ApplicationController def userlist send_data User.report_table.to_pdf, :type => "application/pdf", :filename=> 'userlist.pdf', :disposition => 'inline' end end |
漢字が出ません。2バイト文字が扱えないのです。これはそもそも pdf-writer が対応していないかららしく、UTF-8 対応も、pdf-writer の対応待ちらしいです。
さて、漢字なしならOKかというと、このままではチト問題が。項目の出力順序が意図したとおりに並ばないのです。select とか、only とか付けてもダメで、しばし悩む。
解決策は次の通りです。
reorder('Field1', 'Field2', 'Field3') |
と、ここまで検証したところで、PDF には見切りを付けました。フリーソフトで日本語を扱うのが難しそうだからです。
次に、PXDoc による出力を検証します。
PXDoc は、xml ベースのテキストを成形印刷する仕組みです。テキストファイルなので出力の作成は柔軟に出来そうですが、クライアントに専用ソフトのインストールが必要になります。PDF でも出力に専用ソフトは必要ですが、PXDoc は PDF のリーダーほどメジャーでないのが欠点でしょうか。Rails からPXD形式で出力するには、例えば sample_controller.rb に、
def report @samples = Sample.find(:all) @response.headers["Content-Type"] = 'application/pxd' @response.headers["Content-Disposition"] = 'inline;filename="report.pxd"' render(:layout => false) end |
.rhtml ではなく、report.rxml とし、
xm = Builder::XmlMarkup.new xml << '<?xml version="1.0" encoding="utf-8"?>' xml.tag!("pxd", "paper-type" => "A4", "orientation" => "landscape", "title" => "出力タイトル", "xmlns:xlink" => "http://www.w3.org/1999/xlink"){ xml.tag!("page"){ xml.tag!("svg", "width" => "29.7cm", "height" => "21cm", "viewBox" => "0 0 2970 2100"){ xml.tag!("style", "type" => "text/css"){ xml.cdata "\ .col1 { x:200; dy:100;}\ .col2 { x:400;}\ .col3 { x:600; text-anchor:end;}\ } xml.tag!("text", "y" => "500", "font-size" => "40"){ for sample in @samples xml.tag!("tspan", "class" => "col1"){ xml.text! sample.field1 } xml.tag!("tspan", "class" => "col2"){ xml.text! sample.field2 } xml.tag!("tspan", "class" => "col3"){ xml.text! sample.field3 } end # for loop } # text } # svg } # page }# pxd |
xml << '<?xml version="1.0" encoding="utf-8"?>' は、xm.instruct! で行けるはずなんですが、うまく出力されず、生のステートメントを書いています。もっとも、どっちにしろテスト環境ではうまくレイアウトされますので、問題は無いんですが。
.rxml テンプレートファイルには、Builder::XmlMarkupが用いられるのですが、これがどう便利なんだか、私にはぜんぜん判っていません。
上記のようにした場合、ページのオーバーフローは無視されます。そこで、出力した行数を数えて、基準を超えたら改ページをさせたいところですが、XmlMarkup でどう実現するのか、しばら〜く悩みました。pagination と組み合わせようかとも思ったのですが、結局、改ページさせたいところで
if rowcounts >= 15 xml << "</text></svg></page>" xml << "<page>" xml << '<svg x="0" y="0" viewBox="0 0 2970 2100" height="21cm" width="29.7cm">' xml.tag!("style", "type" => "text/css"){ xml.cdata "\ .col1 { x:200; dy:100;}\ .col2 { x:400;}\ .col3 { x:600; text-anchor:end;}\ } xml << '<text font-size="40" y="500">' rowcounts = 1 end |
ああ、サンプルにスタイルシート入っていて見にくいですね。別に xml.cdata 使わなくても OK ですので。
上であげたサンプルコードは、実際に私が試したものとは異なります。このままで動くかどうかは保証の限りではありません。詳細については、それぞれのマニュアルなり、ヘルプページなりを参照して下さい。
使ってみれば、PXDoc は結構便利そうです。罫線も引けるし、網掛けも出来るし。グラフはまだ未挑戦です。後でやってみようかな。