JasperReportsでSwingでプレビュー

最近休んでましたけど、のんべんだらりんゆるゆるとSwingで色々と遊んでるんですが、やっぱり気になるのは帳票で御座居ます。

普通、Web帳票の方がイレギュラーな気がするんですけど、Javaに関しては逆で、どこ調べてもWeb帳票の事ばっかり。せっかくSwingなので、JFrame上でプレビューしたいよね、と。PDFじゃなくて。

そうなるとJooReportsじゃなくてやっぱりJasperReportsに相成る訳でして。

雑誌やWeb上の記述を見ると、Swingでプレビュー出来るって書いてあるんだけど、サンプルコードが何処にもないんだこれが。あるのかも知れないけど見つからない。Jasperのサンプルデモを見てもないんだこれが。探し方が悪いのかも知れないけど。

おっかしいなあと思ってJavaDocを眺めてみたら、うんと下の方にありましたよ、「JasperViewer」なんてそれらしい名前のクラスが。見てみたら、JFrameを継承してるし、これでビンゴじゃないかと。やったぜ。

JasperPrintオブジェクトを生成する所までは結構サンプルが転がってますんで省略、以下こんな感じ。

JasperViewer frame = new JasperViewer(jasperPrint);
frame.setTitle("帳票テストでげす。");
frame.setVisible(true);

出ましたよ。拡大縮小、ページ繰り、保存印刷などなど各ボタン完備のプレビュー画面が。ばんざーいばんざーい。

しかも保存ダイアログの中で、PDF、XLS、RTF、CSV、HTMLなどなどJasperが対応してる形式に変換可能。むむーんいいじゃん、ユーザーさんに選んで貰えるんならそれが一番。

これだけの事なのに、何処にも見当たらないってのは、Swingを使った業務システムってまだまだなんですかね。ふんが。ですんで自分のためにメモ。

iReportでJavaBeansをバインドさせてえ

勿論帳票のデザインは、iReportを使ってやりますとも。XML直書きは死んじゃうDEATH(うわー若作りし過ぎ、しかも賞味期限切れ)。

で、どの入門記事もWebサイトも、DBと直接つないでデザインする話ばっかり。帳票デザインにSQLを埋め込んだり。気持ち悪いよ〜。

クリスタルレポートなんかの入門記事とか書籍なんかでも、なんだかんだゆって動いてるDBとつないでデザインさせるのが多い。

思うんだけど、本当にニーズがあるんですかね。帳票ってビューでしょ、プレゼンテーション層でしょ。DTOを読ませたいと思うのが人情でしょう。

だもんで、DBとつながずにBeanのプロパティ名を突っ込む。TextFieldのTextField expressionって所に、

$F{propertyName}

なんて書けばいいんだけど。と思ったらコンパイルが通らない。やっぱりDBに接続するが如く、対象となるDTOクラスを読み込まねばいかんようじゃのう。

これがまたそのやり方が全然転がってないんだよなあ。みんなDB直接続の例ばっかり。

自力でやったので、明日のためにそのいち。

  • まずは対象となるDTOコンパイルしてclassファイルを作っておく。Jarを作っちゃっても良い。
  • iReportにクラスパスを通す。「Tools」→「Classpath」を選択。表示された画面の「Add JAR/Folder」をクリック。Jarを指定するか、クラスファイル出力ディレクトリを指定する。サブディレクトリまで見てくれます。
  • ツールバーのドラム缶アイコンか、「Datasource」→「Report query」を選択。
  • 「JavaBean Datasource」タブを選択。「ClassName」にパッケージ名フルでDTOクラス名を入力。「Read javabeans attributes」を押すと、DTOのプロパティが読み込まれて一覧表示されます。
  • 右側ペインの「Library」タブの「Fields」に、読み込んだプロパティが表示されてますんで、こいつを帳票デザイン画面にドラッグ出来ます。勿論TextFieldオブジェクトを貼り付けてそのプロパティを編集してもよいです。

ここまで来たら、上で登録したクラスパスを削除してもいいみたい。コンパイル通るし。フィールドの一覧はレポート単位で管理してるらしい。別案件になって、前の案件のクラスパスがうざったくなって削除しても、その前案件のレポートの保守は可能、と。いいんじゃない?

これで、個別帳票固有のDTOを作って〜、と云った、画面と同じ考え方でいけますな。うむ。

呼び出し側のBeanの突っ込み方

これ忘れてた。

実はこれもサンプルが少ない。みんなDBとつないだDataSourceを突っ込んでるのばかり。

DTOの場合はこうします。例はこないだ失注したRSSうんちゃらプロジェクトのスパイクで使った、BlogSiteなんてクラスで。サイト名とURLを持つとします。

List<BlogSite> list = new ArrayList<BlogSite>();
BlogSite site = new BlogSite();
site.setBlogSiteName("ホームラン2号");
site.setUrl("http://www9.big.or.jp/~rokugen");
list.add(site);
site = new BlogSite();
site.setBlogSiteName("うんちゃら");
site.setUrl("http://www.unchara.co.jp");
list.add(site);

JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(list);

てな感じで List を使ってデータソースを作りまして。その後はJasperの定型処理を経てFillすればOK。引数にデータソースを突っ込みます。

JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, ds);

nullの所は本当はレポートタイトルとか色々とパラメータをMapで渡すんだけど、省略。あとはJasperPrint使ってどうにでもしてという感じ。

いやほんとにただのメモだなこりゃ。