カスタム検索

2009年5月1日金曜日

Grailsで帳票! fop編

帳票、というか組版の部類になると思うんですが、fopでPDFを作成してみました。

帳票というと帳票ソフト+帳票ツールという概念が強かったのですが、
mottsniteさんから
「HTML組む時にGUIソフト使わないっしょ?帳票もGUI使わずにfopでタグ書いたらいいんじゃないの?」
と言われ妙に納得してしまったので、使ってみる事に。

日本語出力までに微妙な所でハマってしまったのでメモっておきます。

・まずはApache fopをダウンロードします。(0.95を使いました)

・Grailsのプロジェクトにライブラリを追加します。
buildフォルダから fop.jar と、libフォルダから以下のファイルを grails プロジェクトの lib フォルダにコピーします。
xmlgraphcs-commons-1.3.1.jar
batik-all.jar
avalon-framework-4.2.0.jar

その他のjarファイルはgrailsが持っているもので補えるので必要ありません。

・FOPの設定ファイルをコピーします
conf/fop.xconf ファイルを適当な場所にコピーして以下のように書き換えます。

<?xml version="1.0"?>
<fop version="1.0">
<base>.</base>
<source-resolution>72</source-resolution>
<target-resolution>72</target-resolution>

<default-page-settings height="11in" width="8.26in"/>

<renderers>
<renderer mime="application/pdf">
<filterList>
<value>flate</value>
</filterList>

<fonts>
<auto-detect/>
</fonts>

</renderer>
</renderers>
</fop>


昔のバージョンではフォントファイルからフォントメトリクスを作成し、その定義をちまちまと書く必要があったのですが、
今はfontsのauto-detectでOSがもってるTTFのフォントが使えるようになります。
(一回目の起動時はフォントファイルを全部読み込むので時間がかかります。)

・簡単なFoファイルを用意します

<?xml version="1.0" encoding="UTF-8" ?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="PageMaster">
<fo:region-body margin-top="3cm"/>
</fo:simple-page-master>
</fo:layout-master-set>

<fo:page-sequence master-reference="PageMaster">
<fo:flow flow-name="xsl-region-body">
<fo:block font-family="Batang" font-size="18pt" text-align="center">
Hello: XSL-FO to PDF
日本語
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>


*font-family は実行するPCに入っている適当なTTFフォントを指定します。
(はじめはMS明朝でテストしていたのですが、なぜかMS明朝はうまく乗らないようです、他のTTFフォントを使いましょう。)

・FopFactoryを定義します。
通常は new FopFactoryでいいんですが、せっかくなのでGrailsっぽくSpringBeanとして登録しちゃいます。
conf/spring/resources.groovy を以下のように書き換えます。

import org.apache.fop.apps.FopFactory

beans = {
def fopFactory=fopFactory(FopFactory){
}
}


これでコントローラーやサービスに def fopFactory とするだけで注入されます :)

・レンダリングを実行します
とりあえずコントローラーにでも書いちゃいましょう



def fop={
fopFactory.setUserConfig(new File("fop/fop.xconf"))
OutputStream os = new BufferedOutputStream(new FileOutputStream(new File("fop/fop.pdf")))

try {
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, os)

TransformerFactory factory = TransformerFactory.newInstance()
Transformer transformer = factory.newTransformer()

Source src = new StreamSource(new File("fop/fop.fo"))
Result res = new SAXResult(fop.getDefaultHandler())

transformer.transform(src, res)
} finally {
os.close()
}

render "ok"
}





素晴らしい!
速度も十分です。
グラフを出したりはまた別の仕組みが必要になってしまうのですが、組版的な細かい調整(長体かけたり、外字使ったり、レイアウト組とか・・・)が出来たり、MarkUpBuilder使ってプログラム的に組んでしまえばデータにあわせて微妙に形をかえるような帳票も出来ちゃいますね!

0 件のコメント: