SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

OpenOffice.orgとJooReportsを利用してJavaからPDFを出力する

OpenOffice.orgとJooReportsを使用したPDFの作成方法


  • このエントリーをはてなブックマークに追加

Webシステムにおいて帳票はPDFで出力することが一般的になっていますが、そのためには高価なツールを購入する必要があります。本稿では、OpenOffice.orgとJooTemplates、JooConverterを利用して、簡単にPDF帳票を作成する方法を解説します。

  • このエントリーをはてなブックマークに追加

はじめに

 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.0b4JooConverter-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」を開きます。

JooReports-AddOnInstaller.sxc
JooReports-AddOnInstaller.sxc

 [install]ボタンをクリックし、ウィザードに従い、インストールを実行します。インストール完了後に文書ドキュメントのツールメニューに[JooReports]のメニューが表示されればインストールは完了です。ここでは[Menu Type Choice]で[Top Menu]を選択しました。

Top Menuへのインストール完了後の文書ドキュメント
Top Menuへのインストール完了後の文書ドキュメント

 なお、JooTemplatesで作成できる帳票レイアウトの例は以下のようになります。

テンプレートとして用意したSXWファイルの例
テンプレートとして用意したSXWファイルの例
補足説明
 SXWファイルとは、OpenOffice.orgの文書ドキュメントであるWriterアプリケーション(Microsoft OfficeでのWordにあたるアプリケーション)のファイル形式です。もし、表計算形式でのテンプレート作成がお好みであれば、POIなどを利用されることをお勧めします。なお、POIを利用したサンプルアプリケーションを利用したい場合は、ファイル「JooConverterPOI.war」を参照してください。

JooConverter

 JooConverterはOpenOffice.orgのコンバート機能をより簡単に利用するためのライブラリです。今回ご紹介するSXWファイルのみでなく、OpenOffice.orgが変換をサポートするドキュメント形式であればPDF形式に変換することが可能です(コンバート可能なフォーマットについては、後述の「OpenOffice.orgがサポートするフォーマット変換」の項をご覧下さい)。

 JooConverterを使用するには、「<OpenOffice.orgのインストールパス>/share/registry/data/org/openoffice/Setup.xcu」へ以下の設定を追加する必要があります。

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」の設定を追加しました。

補足説明
 JooConverterを使用するためには、OpenOffice.orgを常駐させておく必要があります(ウィンドウ右下のタスクバーに「Openoffice.orgのクイック起動」が表示されている必要があります)。また「Setup.xcu」の設定を反映させるためには「Openoffice.orgのクイック起動」を再起動する必要があります。

サンプルアプリケーションの概要

 サンプルアプリケーションの流れは以下の通りです。

  1. ブラウザで帳票作成ボタンが押され、サーブレットコンテナへリクエストが送信される。
  2. JooTemplatesでテンプレートとして用意されたSXWファイルを読み込み、在庫一覧固有の情報をSXWファイルに書き込む。
  3. JooConverterでSXWファイルをPDF形式に変換する。
  4. ブラウザに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メソッドが実行されます。

「StocklistAction.java」のソース
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ファイルの読込と更新を行っています。

「StocklistAction.java」のソース
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ファイルを読み込み、在庫一覧帳票の値(倉庫名、在庫情報など)を設定しています。今回使用した帳票テンプレートを確認してみましょう。

テンプレートとして用意したSXWファイル
テンプレートとして用意したSXWファイル

 倉庫番号、倉庫名の箇所はFieldタグを指定し、それぞれwarehouseNo,warehouseNameと変数名を指定しました。「map.put("warehouseNo",sForm.getWarehouseNo());」のように、帳票テンプレートに設定したタグのVaraiable Expressionをキーとした値をMapに設定することで、SXWへ値を挿入することが出来ます。

 また、帳票テンプレートには、warehouseNameといったField以外にも、様々な設定が可能です。

 繰り返し箇所の明細部分にはFor Eachタグを指定し、変数名をdetailListと指定しました。リストに含まれるbean名をdetailと指定しています。また明細行の中で項目を指定する場合にはFieldタグに次のように指定します(ここでは、detailが「リストで指定したbean名」、itemNoが「プロパティ名」)。

リスト形式でのFieldタグの定義例
#detail.itemNo

 上記のように指定することで、For Eachタグで指定したリストから定義したbeanを取得し、更にbeanよりプロパティ値を取得するこができます。

 また表形式で繰り返し出力を行う場合には、Document Elementはtable-rowを選択します。レイアウト確認用にサンプル値として最大桁数で文字を入力しておきます。

SXWファイルの変換

 続いて下記のソースでは、更新したSXWファイルをJooConverterを用いて、OpenOffice.orgによってPDFへ変換しています。

StocklistAction.javaのソース
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ファイルをブラウザに送ります。

StocklistAction.javaのソース
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();

        //(以下省略)
    }
}
出力されたPDF
出力されたPDF

OpenOffice.orgとの接続ポートの変更

 今回取り上げたサンプルではOpenOffice.orgとの接続に8100ポートを利用していますが、他のポートへ変更することも可能です。

 変更する場合には、OpenOffice.orgの「Setup.xcu」ファイルを下記の通り書き換えて下さい。host属性を0に設定することで、すべてのクライアントからのリクエストを受け付けることが可能となります。必要なければセキュリティ上、localhostへ設定しておくことが望ましいでしょう。

すべてのクライアントから7001ポートへの接続を許可する場合の「Setup.xcu」のソース
<prop oor:name="ooSetupConnectionURL" oor:type="xs:string">
    <value>socket,host=0,port=7001;urp;</value>
</prop>

 UnoConnectionは、コンストラクタへ引数を渡すことで、デフォルトの接続設定から変更することが可能です。

PC01サーバの7001ポートへ接続する場合の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ドキュメントの変換を実行するクラスです。
DocumentConverterFactoryDocumentConverterのファクトリークラスです。
DocumentFormatドキュメントの変換形式を管理するクラスです。変換形式と関連する拡張子、mimetypeを管理しています。
UnoConnectionOpenOffice.orgとJooConverter間での内部接続を維持・管理するクラスです。
UnoExceptionOpenOffice.orgとの接続例外(未チェック例外)クラスです。

OpenOffice.orgがサポートするフォーマット変換

 今回紹介したExcelファイルのPDF変換以外にも、OpenOffice.orgではいくつかのフォーマットをPDFへ変換する機能を提供しています。また、これらはすべてJooConverterからも利用できます。この際に指定するnet.sf.joott.uno.DocumentFormatクラスの属性名(およびMimeTypeと拡張子)を次にまとめます。

文書ドキュメント(Writer)によってサポートされるドキュメント形式
属性名mimetype拡張子プロパティ
XML_WRITERapplication/vnd.sun.xml.writersxwStarOfficeXML(Writer)
PDF_WRITERapplication/pdfpdfwriter_pdf_Export
MS_WORD_97application/msworddocMSWord97
RTFapplication/rtfrtfRichTextFormat
HTML_WRITERtext/htmlhtmlHTML(StarWriter)
TEXTtext/plaintxtText
HTML形式ドキュメント(Writer/Web)によってサポートされるドキュメント形式
属性名mimetype拡張子プロパティ
XML_WRITER_WEBapplication/vnd.sun.xml.writersxwwriter_web_StarOffice_XML_Writer
PDF_WRITER_WEBapplication/pdfpdfwriter_web_pdf_Export
表計算ドキュメント(Calc)によってサポートされるドキュメント形式
属性名mimetype拡張子プロパティ
XML_CALCapplication/vnd.sun.xml.calcsxcStarOfficeXML(Calc)
PDF_CALCapplication/pdfpdfcalc_pdf_Export
MS_EXCEL_97application/vnd.ms-excelxlsMSExcel97
HTML_CALCtext/htmlhtmlHTML(StarCalc)
TEXT_CALCtext/plaintxtText-txt-csv(StarCalc)
プレゼンテーション(Impress)によってサポートされるドキュメント形式
属性名mimetype拡張子プロパティ
XML_IMPRESSapplication/vnd.sun.xml.impresssxcStarOfficeXML(Impress)
PDF_IMPRESSapplication/pdfpdfimpress_pdf_Export
FLASH_IMPRESSapplication/x-shockwave-flasswfimpress_flash_Export
MS_POWERPOINT_97application/vnd.ms-powerpoinpptMSPowerPoint97

まとめ

 本稿では、簡単な業務帳票を動的に作成する処理を通して、OpenOfficeとJooReportsでPDFを作成する処理について紹介しました。この方法を使えば帳票設計者と実装者の役割分担も明確になり大量の帳票設計、実装がより容易に行えるようになるでしょう。また、PDFを作成する基本的な処理はサンプルの通りですが、OpenOffice.orgでは先にご紹介したさまざまなドキュメント形式の変換が可能です。

 なお、今現在SourceForgeのJooReportsのページを開くと最新版は2.0となっています。これはOpenOffice.orgはバージョン2.0のリリース間近となっているためです。OpenOffice.orgもバージョンアップすることでMicrosoft Officeに勝るとも劣らない機能を備える可能性を秘めていますので、一度お使いになってみることをお勧めします。

参考資料

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 奥山 学(オクヤマ マナブ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/131 2006/10/11 19:33

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング