はじめに
Webシステムにおいては帳票はPDFで出力することが一般的となっています。しかし帳票のデザインから出力の設定には各帳票ベンダーそれぞれのやり方があり、また高価なツールを購入せねばなりません。
今回ご紹介する方法ではOpenOffice.orgとJooTemplatesで帳票レイアウトを作成、編集を行うことで帳票データを作成します。作成された帳票データをOpenOffice.orgとJooConverterを使い、PDF変換を行うことで簡単にPDF帳票を作成することができます。
対象読者
Javaプログラミングを行ったことがある、もしくは、Javaプログラミングに興味のある方を対象としています。
必要な環境
このサンプルはJ2SE Development Kit 5.0 Update 2、Tomcat5.5.7、OpenOffice.org1.1.4日本語版、JooTemplates-1.0b4、JooConverter-1.0b4にて動作確認をしています。WebアプリケーションについてはフレームワークのStruts1.2を使用していますが、サンプルソースに内包しているためJ2SDKとサーブレットコンテナ以外の環境は必要ありません。Java、Tomcat、Strutsについての詳細や設定方法については、「サーバサイド技術の学び舎 - WINGS」にある「サーバサイド環境構築設定」を参照して下さい。
OpenOffice.orgの概要とセットアップ方法
OpenOffice.orgは、1980年代半ばにドイツのStarDivision社で作られたものをSun Microsystemsが買収し、StarOffice(日本ではStarSuite)として発売されたオフィススイートです。Sun Microsystemsは、このStarOfficeのプログラムソースを2000年6月に公開し、公開されたプログラムソースをOpenOffice.orgプロジェクトが引き継ぎました。日本でのユーザ会活動も活発です。
OpenOffice.orgのインストーラは、「OpenOffice.org日本ユーザ会」からダウンロードして下さい。インストール方法は、ダウンロードしたファイル(ここでは「OOo_1.1.4_Win32Intel_install_ja.zip」)を解凍し、「setup.exe」を実行します。もし、インストールがうまくいかない場合などは、「OpenOffice.org日本ユーザ会」の「使い方・ノウハウ」といったページを参照すると良いでしょう。
JooReportsの概要とセットアップ方法
JooReportsは、帳票レイアウトを作成するための「JooTemplate」と、ドキュメントをPDFなどに変換する「JooConverter」から構成されます。JooReportsを入手するには、「Sourceforge.net」からダウンロードしてください。
JooTemplates
JooTemplatesは、OpenOffice.orgの文書ドキュメント(Writer)のSXWファイルに独自のタグを埋め込み、帳票レイアウトを作成するためのツール群です。文書ドキュメントアプリケーションを拡張するためのSXCファイルと、Javaプログラムからデータを設定するためのライブラリで構成されます。
インストールするには、ダウンロードしたファイル(ここでは「jootemplates-1.0b4.zip」)を解凍し、「JooReports-AddOnInstaller.sxc」を開きます。
[install]ボタンをクリックし、ウィザードに従い、インストールを実行します。インストール完了後に文書ドキュメントのツールメニューに[JooReports]のメニューが表示されればインストールは完了です。ここでは[Menu Type Choice]で[Top Menu]を選択しました。
なお、JooTemplatesで作成できる帳票レイアウトの例は以下のようになります。
JooConverter
JooConverterはOpenOffice.orgのコンバート機能をより簡単に利用するためのライブラリです。今回ご紹介するSXWファイルのみでなく、OpenOffice.orgが変換をサポートするドキュメント形式であればPDF形式に変換することが可能です(コンバート可能なフォーマットについては、後述の「OpenOffice.orgがサポートするフォーマット変換」の項をご覧下さい)。
JooConverterを使用するには、「<OpenOffice.orgのインストールパス>/share/registry/data/org/openoffice/Setup.xcu」へ以下の設定を追加する必要があります。
<prop oor:name="ooSetupConnectionURL" oor:type="xs:string"> <value>socket,host=localhost,port=8100;urp;</value> </prop>
これはUNO Remote Protpcol(urp)接続のために、ローカルホストに8100ポートを開放する設定です(ポート番号の設定は読者の環境に合わせて変更してください。詳細は後述の「OpenOffice.orgとの接続ポートの変更」の項をご覧下さい)。なお、設定を追加する箇所は<node oor:name="Office">
です。筆者の場合、上記「ooSetupLocales
」の下に「ooSetupConnectionURL
」の設定を追加しました。
サンプルアプリケーションの概要
サンプルアプリケーションの流れは以下の通りです。
- ブラウザで帳票作成ボタンが押され、サーブレットコンテナへリクエストが送信される。
- JooTemplatesでテンプレートとして用意されたSXWファイルを読み込み、在庫一覧固有の情報をSXWファイルに書き込む。
- JooConverterでSXWファイルをPDF形式に変換する。
- ブラウザにPDFファイルを出力(ダウンロード)する。
タイトルや罫線などの共通レイアウトはテンプレートとしてあらかじめ作成しておき、倉庫名や商品名、数量といった一覧表ごとに異なる値は、プログラムから設定するようにします。
なお、サンプルを実際に動作させてみたい場合には、記事上部のリンクから、ファイル「JooReports.war」をダウンロードしてTomcatなどのアプリケーションサーバの「webapps」フォルダに配置(デプロイ)してください。また、あらかじめOpenOffice.orgのセットアップを完了しておく必要もあります。アプリケーションサーバ起動後に、「http://localhost:8080/JooReports」にアクセスすればサンプルを動作させることができます(ホスト名・ポート番号は読者の環境に合わせて変更してください)。
今回のサンプルの主要ファイルは下記の通りです。
ファイル名 | 説明 |
stocklist.sxw | 帳票のテンプレートとなるSXWファイルです。 |
Input.jsp | 倉庫番号入力画面です。 |
StocklistAction.java | 帳票出力を実行するアクションクラスです。 |
StocklistForm.java | 倉庫番号をやりとりするアクションフォームクラスです。 |
StocklistService.java | 在庫データを取得するサービスクラスです。 |
DetailData.java | 帳票の明細データクラスです。 |
PDFファイルのダウンロード処理
それではソースコードを見ながら、プログラムの流れを確認してみましょう。
ブラウザから「PDF出力」ボタンを押下すると、StrutsのAction
クラスのexecute
メソッドが実行されます。
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //倉庫番号を元に在庫情報を取得します。 StocklistForm sForm = (StocklistForm) form; StocklistService sService = new StocklistService(); List detailList = sService .getStocklistInfoByWarehouseNo(sForm.getWarehouseNo()); //(以下省略) }
ここでは、StrutsのActionForm
からリクエスト情報(倉庫番号)を取り出し、ビジネスロジックにあたるStocklistService
クラスから在庫一覧の詳細データを取得しています。この処理によって、DetailData
オブジェクトに帳票出力用のデータが設定されます。
SXWファイルの読み取り、更新
続いて下記のソースでは、SXWファイルの読込と更新を行っています。
public class StocklistAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //(中略) //テンプレートとなるSXWファイルのパスを取得し、 //ファイルを読み込みます。 final String STOCKLIST_FILE = "/WEB-INF/classes/to/msn/wings/stocklist.sxw"; String filePath = this.getServlet() .getServletContext().getRealPath(STOCKLIST_FILE); Template template = new Template(new FileInputStream(filePath)); //SXWデータマップを作成し、帳票データを設定します。 HashMap map = new HashMap(); map.put("warehouseNo",sForm.getWarehouseNo()); map.put("warehouseName","晴海第3倉庫"); map.put("detailList",detailList); //(以下省略) } }
ここでは、SXWファイルを読み込み、在庫一覧帳票の値(倉庫名、在庫情報など)を設定しています。今回使用した帳票テンプレートを確認してみましょう。
倉庫番号、倉庫名の箇所はField
タグを指定し、それぞれwarehouseNo
,warehouseName
と変数名を指定しました。「map.put("warehouseNo",sForm.getWarehouseNo());
」のように、帳票テンプレートに設定したタグのVaraiable Expressionをキーとした値をMapに設定することで、SXWへ値を挿入することが出来ます。
また、帳票テンプレートには、warehouseName
といったField
以外にも、様々な設定が可能です。
繰り返し箇所の明細部分にはFor Each
タグを指定し、変数名をdetailList
と指定しました。リストに含まれるbean
名をdetail
と指定しています。また明細行の中で項目を指定する場合にはField
タグに次のように指定します(ここでは、detail
が「リストで指定したbean
名」、itemNo
が「プロパティ名」)。
#detail.itemNo
上記のように指定することで、For Each
タグで指定したリストから定義したbean
を取得し、更にbean
よりプロパティ値を取得するこができます。
また表形式で繰り返し出力を行う場合には、Document Elementはtable-rowを選択します。レイアウト確認用にサンプル値として最大桁数で文字を入力しておきます。
SXWファイルの変換
続いて下記のソースでは、更新したSXWファイルをJooConverterを用いて、OpenOffice.orgによってPDFへ変換しています。
public class StocklistAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //(中略) //StreamをOpenし、ディレクトリに書き出します。 final String TMP_INPUT_FILE = "/WEB-INF/input.sxw"+Thread.currentThread().getId(); String tmpInputPath = this.getServlet() .getServletContext().getRealPath(TMP_INPUT_FILE); OutputStream tos = new FileOutputStream(tmpInputPath); template.createDocument(map,tos); tos.close(); //Streamで書き出したファイルを一時ファイルとして開きます。 File inputFile = new File(tmpInputPath); //出力ファイルを作成します。 final String TMP_OUTPUT_FILE = "/WEB-INF/output.pdf"+Thread.currentThread().getId(); String tmpOutputPath = this.getServlet() .getServletContext().getRealPath(TMP_OUTPUT_FILE); File outputFile = new File(tmpOutputPath); DocumentConverter converter = DocumentConverterFactory.getConverter(); try{ //変換を実行します。 converter.convert(inputFile, outputFile, DocumentFormat.PDF_WRITER); }catch (IOException e) { logger.error("PDFへの変換処理に失敗しました。", e); } //(以下省略) }
ダウンロードファイルの送信(レスポンス)
最後に、作成したPDFファイルをブラウザに送ります。
public class StocklistAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //(中略) response.setHeader("Cache-Control", ""); response.setHeader("Pragma", ""); response.setHeader("Content-Disposition", "attachment;filename=stocklist." +DocumentFormat.PDF_WRITER.getFileExtension()); response .setContentType(DocumentFormat.PDF_WRITER.getMimeType()); FileInputStream in = new FileInputStream(outputFile); OutputStream os = response.getOutputStream(); byte[] buffer = new byte[2048]; int bytes; while ((bytes = in.read(buffer, 0, 2048)) != -1) { os.write(buffer, 0, bytes); } in.close(); os.close(); outputFile.delete(); inputFile.delete(); //(以下省略) } }
OpenOffice.orgとの接続ポートの変更
今回取り上げたサンプルではOpenOffice.orgとの接続に8100ポートを利用していますが、他のポートへ変更することも可能です。
変更する場合には、OpenOffice.orgの「Setup.xcu」ファイルを下記の通り書き換えて下さい。host
属性を0に設定することで、すべてのクライアントからのリクエストを受け付けることが可能となります。必要なければセキュリティ上、localhostへ設定しておくことが望ましいでしょう。
<prop oor:name="ooSetupConnectionURL" oor:type="xs:string"> <value>socket,host=0,port=7001;urp;</value> </prop>
UnoConnection
は、コンストラクタへ引数を渡すことで、デフォルトの接続設定から変更することが可能です。
UnoConnection connection = new UnoConnection("socket,host=PC01,port=7001,tcpNoDelay=1");
ちなみにDocumentConverterFactory
を使ってConverterを取得した場合、UnoConnection
を上記のように初期化する方法がありません。 DocumentConverterFactory
を利用する場合にはJooConverter自体に手を加える必要があるでしょう。
JooConverterに関するTips
JooConverter付属のサンプルではリスナーを使ってデプロイ時にUnoConnection
を取得しています。
JooConverterのAPIでは、JooConverterを利用するアプリケーションとOpenOffice.orgは同一マシンで稼動していることが望ましいとあります。そのため、接続ができなくなることは稀であると考え、リスナーなどを使ってコネクションを初期化する方法も一考の価値があると思います。
JooConverterの主なクラスライブラリ
JooConverterの主なライブラリクラスをまとめます。
クラス名 | 説明 |
DocumentConverter | ドキュメントの変換を実行するクラスです。 |
DocumentConverterFactory | DocumentConverterのファクトリークラスです。 |
DocumentFormat | ドキュメントの変換形式を管理するクラスです。変換形式と関連する拡張子、mimetypeを管理しています。 |
UnoConnection | OpenOffice.orgとJooConverter間での内部接続を維持・管理するクラスです。 |
UnoException | OpenOffice.orgとの接続例外(未チェック例外)クラスです。 |
OpenOffice.orgがサポートするフォーマット変換
今回紹介したExcelファイルのPDF変換以外にも、OpenOffice.orgではいくつかのフォーマットをPDFへ変換する機能を提供しています。また、これらはすべてJooConverterからも利用できます。この際に指定するnet.sf.joott.uno.DocumentFormat
クラスの属性名(およびMimeTypeと拡張子)を次にまとめます。
属性名 | mimetype | 拡張子 | プロパティ |
XML_WRITER | application/vnd.sun.xml.writer | sxw | StarOfficeXML(Writer) |
PDF_WRITER | application/pdf | writer_pdf_Export | |
MS_WORD_97 | application/msword | doc | MSWord97 |
RTF | application/rtf | rtf | RichTextFormat |
HTML_WRITER | text/html | html | HTML(StarWriter) |
TEXT | text/plain | txt | Text |
属性名 | mimetype | 拡張子 | プロパティ |
XML_WRITER_WEB | application/vnd.sun.xml.writer | sxw | writer_web_StarOffice_XML_Writer |
PDF_WRITER_WEB | application/pdf | writer_web_pdf_Export |
属性名 | mimetype | 拡張子 | プロパティ |
XML_CALC | application/vnd.sun.xml.calc | sxc | StarOfficeXML(Calc) |
PDF_CALC | application/pdf | calc_pdf_Export | |
MS_EXCEL_97 | application/vnd.ms-excel | xls | MSExcel97 |
HTML_CALC | text/html | html | HTML(StarCalc) |
TEXT_CALC | text/plain | txt | Text-txt-csv(StarCalc) |
属性名 | mimetype | 拡張子 | プロパティ |
XML_IMPRESS | application/vnd.sun.xml.impress | sxc | StarOfficeXML(Impress) |
PDF_IMPRESS | application/pdf | impress_pdf_Export | |
FLASH_IMPRESS | application/x-shockwave-flas | swf | impress_flash_Export |
MS_POWERPOINT_97 | application/vnd.ms-powerpoin | ppt | MSPowerPoint97 |
まとめ
本稿では、簡単な業務帳票を動的に作成する処理を通して、OpenOfficeとJooReportsでPDFを作成する処理について紹介しました。この方法を使えば帳票設計者と実装者の役割分担も明確になり大量の帳票設計、実装がより容易に行えるようになるでしょう。また、PDFを作成する基本的な処理はサンプルの通りですが、OpenOffice.orgでは先にご紹介したさまざまなドキュメント形式の変換が可能です。
なお、今現在SourceForgeのJooReportsのページを開くと最新版は2.0となっています。これはOpenOffice.orgはバージョン2.0のリリース間近となっているためです。OpenOffice.orgもバージョンアップすることでMicrosoft Officeに勝るとも劣らない機能を備える可能性を秘めていますので、一度お使いになってみることをお勧めします。