アップクロス株式会社の西元です。
後編では、JasperReportsで帳票出力を行うプログラムについて説明していきます。
まずは、以下の3つのzipファイルをダウンロードして、開発用PCに展開してください。
帳票出力プログラム一式(JasperToPDF.zip)
※帳票出力プログラム・ソース一式には、Javaプログラムのコンパイル&実行に必要なライブラリ(jarファイル)が含まれていません。Javaプログラムを修正したりビルドし直す場合は自身で下記Jarファイルをlibフォルダにコピーしてください。
・jasperreports-5.6.1-project.zipに含まれる以下のJarファイル
jasperreports-5.6.1/lib/*.jar
jasperreports-5.6.1/dist/*.jar
・ipa_fonts.jar ・・・ 前編でiReportからエクスポートしたIPAフォントファイル
・cfx.jar ・・・ColdFusionのインストール先フォルダ wwwroot/WEB-INF/lib から取得
前編「ColdFusionからJasperReportsを利用する方法」で書いた通り、今回紹介する方法では、JasperReportsライブラリを使って帳票を作成する処理をDaemon(常駐プログラム)として実行し、ColdFusionからJava RMIを使用して帳票作成の処理を依頼します。
Javaで作成するソースファイルは以下の3ファイルです。帳票出力プログラム・ソース一式(JasperToPDF_src.zip)のsrcフォルダにあります。
いずれも100ステップに満たないコードですので、ソースを読めばすぐに分かるかと思いますが、以下に簡単な説明だけ書いておきます。
JasperToPdfServer.java
インターフェースなので、特に処理はありません。RMIでクライアントから呼び出されるdoPrintメソッドの定義があるだけです。
JasperToPdfServerImpl.java
JasperToPdfServerImplはJasperToPdfServerインターフェースのdoPrintメソッドを実装しています。また、RMIサーバにもなるためUnicastRemoteObjectを継承しています。
doPrintメソッドで行っている事は、
JasperToPdf.java
Java CFXタグとするため、CustomTagインターフェースのprocessRequestメソッドを実装しています。
processRequestメソッドでは、14〜17行目でCFXタグで指定されたパラメータ(属性)を受け取り、値の必須チェックやファイルの存在チェックを行った後で、RMIを使ってJasperToPdfServerのdoPrintメソッドをコールします。
これらをコンパイルしたクラスファイルのうち、帳票生成Daemon(常駐プログラム)となるJasperToPdfServer.jarは
JasperToPdfServer.classとJasperToPdfServerImpl.classで構成され、Java CFXタグの実体となるJasperToPdf.jarは
JasperToPdf.classとJasperToPdfServer.classで構成されています。
便宜上、この記事ではJasperToPdfServer.jarとJasperToPdf.jarを合わせて「帳票出力プログラム」と表記しています。
(1) 帳票出力プログラム一式をWebサーバにコピー
(2) 帳票生成Daemon(常駐プログラム)の実行
Webサーバでコマンドプロンプトを開き、カレントディレクトリを JasperToPDFServer.jar があるフォルダに移動してから、以下のコマンドを実行してください。
(3) Java CFXタグの登録
ブラウザを起動し、WebサーバのColdFusion Administratorにログインしてください。
左のメニューから「拡張機能>CFXタグ」を選択して、[Java CFXの登録]ボタンを押してください。
以上で、ColdFusionアプリケーションでcfx_JasperToPdfタグを記述すればJasperReportsの帳票出力が使えるようになります。
cfx_JasperToPdfタグの書式:
今回使用する帳票出力サンプル(JasperToPDF_sample.zip)は、『利用者一覧表出力画面で、性別と都道府県を選択して[印刷]ボタンを押すと、ユーザマスタ(USER_M)テーブルから対象ユーザを抽出して一覧表のPDFファイルを表示する』と言うものです。
※サンプルなのでエラー処理は考慮していません。また、抽出結果が0件の時は空白のPDFが出力されます。
ソースファイル構成
JasperToPDF_sample.zipのWebフォルダに以下のファイルがあります。
サンプル実行に必要なのは、このうち index.cfm, get_UsersList.cfm, UserList.jasper の3ファイルです。
このサンプルを実行するために、データベースに以下のテーブルを作成してください。
列ID | 列名称 | 型 | サイズ | NOT NULL | 備考 |
---|---|---|---|---|---|
ID | ID | VARCHAR2 | 8 | Yes | Primary Key |
NAME | 氏名 | VARCHAR2 | 20 | Yes | |
GENDER | 性別 | VARCHAR2 | 1 | M:男性/F:女性 | |
BIRTH_DATE | 生年月日 | DATE | |||
ZIP_CD | 郵便番号 | VARCHAR2 | 10 | ||
STATE | 都道府県 | VARCHAR2 | 10 | ||
TEL_NO | 電話番号 | VARCHAR2 | 20 | ||
FAX_NO | FAX番号 | VARCHAR2 | 20 | ||
メールーアドレス | VARCHAR2 | 60 | |||
REGIST_DATE | 登録日 | DATE |
DROP TABLE USER_M; CREATE TABLE USER_M ( ID VARCHAR2(8) NOT NULL, NAME VARCHAR2(20) NOT NULL, GENDER VARCHAR2(1), BIRTH_DATE DATE, ZIP_CD VARCHAR2(10), STATE VARCHAR2(10), TEL_NO VARCHAR2(20), FAX_NO VARCHAR2(20), MAIL VARCHAR2(60), REGIST_DATE DATE, CONSTRAINT USER_M_PK PRIMARY KEY (ID) USING INDEX TABLESPACE USERS ) TABLESPACE USERS; COMMENT ON TABLE USER_M IS 'ユーザマスタ'; COMMENT ON COLUMN USER_M.ID IS 'ID'; COMMENT ON COLUMN USER_M.NAME IS '氏名'; COMMENT ON COLUMN USER_M.GENDER IS '性別'; COMMENT ON COLUMN USER_M.BIRTH_DATE IS '生年月日'; COMMENT ON COLUMN USER_M.ZIP_CD IS '郵便番号'; COMMENT ON COLUMN USER_M.STATE IS '都道府県'; COMMENT ON COLUMN USER_M.TEL_NO IS '電話番号'; COMMENT ON COLUMN USER_M.FAX_NO IS 'FAX番号'; COMMENT ON COLUMN USER_M.MAIL IS 'メールアドレス'; COMMENT ON COLUMN USER_M.REGIST_DATE IS '登録日';DB/INS_USER_M.sql はテストデータを100件登録するINSERT文です。USER_Mテーブルを作成したら、このスクリプトを実行してください。
※USER_Mテーブルを作成したデータベースにColdFusionから接続するために、ColdFusion Administratorの「データとサービス/データソース」画面でデータソースとして登録しておいてください。
get_UsersList.cfm で行っている処理について、簡単に説明します。また、フォルダ名やデータソース名等はご自身のWebサーバの環境に合わせて変更してください。
[get_UsersList.cfm]
<cfprocessingdirective pageencoding="MS932"> <cfcontent type="text/html; charset=MS932"> <cfscript> SetEncoding("url", "MS932"); SetEncoding("form", "MS932"); </cfscript> <cftry> <!--- jasperファイルのフルパス ---> <cfset jasperFile = "C:\www\sample\UserList.jasper" > <!--- XML/PDF一時ファイルの作成フォルダ ---> <cfset tempDir = "C:\temp\" > <!--- XML&PDFの一時ファイル名を取得 ---> <cfset xmlfile = GetTempFile(tempDir, "XML")> <cfset pdffile = GetTempFile(tempDir, "PDF")> <!--- 抽出条件セット(都道府県&性別) ---> <cfset cond = StructNew() > <cfif isDefined("form.selState") > <cfset cond.state = form.selState > <cfelse> <cfset cond.state = "" > </cfif> <cfif isDefined("form.selGender") > <cfset cond.gender = form.selGender > <cfelse> <cfset cond.gender = "0" > </cfif> <!--- DBより帳票に出力するデータを取得 ---> <cfquery name="qry" dataSource="SAMPLE" result="res" > SELECT ID, NAME, DECODE(GENDER, 'M', '男性', 'F', '女性', '不明') GENDER , TO_CHAR(BIRTH_DATE, 'YYYY/MM/DD') BIRTH_DATE , ZIP_CD, STATE, TEL_NO, FAX_NO, MAIL , TO_CHAR(REGIST_DATE, 'YYYY/MM/DD') REGIST_DATE , TRUNC(MONTHS_BETWEEN(SYSDATE, BIRTH_DATE)/12) AGE FROM USER_M WHERE (<cfqueryparam value="#cond.gender#" CFSQLType="CF_SQL_VARCHAR"> = '0' OR GENDER = <cfqueryparam value="#cond.gender#" CFSQLType="CF_SQL_VARCHAR">) <cfif cond.state neq "" > AND STATE = <cfqueryparam value="#cond.state#" CFSQLType="CF_SQL_VARCHAR"> </cfif> ORDER BY ID </cfquery> <!--- クエリーからXML書式のデータを作成 ---> <cfset wkColumnList = ListToArray(qry.columnList, chr(44), true) > <cfset xmlStr = '<?xml version="1.0" encoding="Windows-31J"?>#chr(13)#' > <cfset xmlStr = xmlStr & '<REPORTS>' & chr(13) > <cfset xmlStr = xmlStr & '<PARAM>' & chr(13) > <cfset xmlStr = xmlStr & chr(9) & '<SYSDATE>' & xmlformat(DateFormat(Now(), 'yyyy/mm/dd')) & '</SYSDATE>' & chr(13) > <cfset xmlStr = xmlStr & chr(9) & '<TITLE>' & xmlformat('*** 利用者一覧表 ***') & '</TITLE>' & chr(13) > <cfset xmlStr = xmlStr & '</PARAM>' & chr(13) > <cfset xmlStr = xmlStr & '<ROWSET>' & chr(13) > <cfloop query="qry" > <cfset xmlStr = xmlStr & '<ROW num="#qry.currentRow#">' & chr(13) > <cfloop index="i" from="1" to="#ArrayLen(wkColumnList)#" > <cfset wkColumnName = wkColumnList[i] > <cfset wkColumnData = qry[wkColumnName] > <cfset xmlStr = xmlStr & chr(9) & '<#wkColumnName#>#xmlformat(wkColumnData)#</#wkColumnName#>' & chr(13) > </cfloop> <cfset xmlStr = xmlStr & '</ROW>' & chr(13) > </cfloop> <cfset xmlStr = xmlStr & '</ROWSET>' & chr(13) > <cfset xmlStr = xmlStr & '</REPORTS>' > <!--- XMLデータを一時ファイルに保存 ---> <cffile action="write" file="#xmlfile#" output="#xmlStr#" charset="Windows-31J"> <!--- 帳票作成処理の実行 ---> <CFX_JASPERTOPDF JASPER="#jasperFile#" DATA="#xmlfile#" XPATH="//ROW" OUT="#pdffile#"> <!--- XMLファイルの削除 ---> <cffile action="delete" file="#xmlfile#"> <!--- PDFファイルのダウンロード ---> <cfheader name="Content-Disposition" value="attachment; filename=利用者一覧表.pdf"> <cfcontent type="application/pdf" file="#pdffile#" deletefile="yes"> <cfcatch type="any"> <cfoutput> <cfdump var="#cfcatch#"> </cfoutput> </cfcatch> </cftry>
ブラウザを起動して、Webサーバに置いたindex.cfmにアクセスしてください。
例)ドキュメント・ルートが C:\www で、帳票出力サンプルを C:\www\sample フォルダに置いた場合。
今回紹介した帳票出力プログラムはPDFファイルを作成する機能しか持っていませんが、JasperReportsは様々な出力形式に対応しています。JasperPrintServerImpl.javaに手を加える事で、PDF以外の出力形式にも対応できますし、直接プリンタへ出力する事もできるようになります。
また、今回はコマンドプロンプトで常駐プログラムを実行しましたが、Apacheのcommons-daemonを使用するとWindowsサービスとして実行する事も可能になります。
その他、RMIでの受け渡しをファイルパスではなくデータストリームに変更すればColdFusionと帳票作成処理を別サーバに分離する事も出来そうですし、JSON等他のデータソース形式を使えるようにするのも良いかもしれません。
Java開発に慣れている方なら、意外と簡単に作れるのではないかと思います。
それと、JasperToPdf.javaはJava CFXタグのサンプルにもなるかと思います。ColdFusionのCFMLとCFScriptだけで実現するのが困難だったり、複雑すぎてパフォーマンス的に難がある処理等はJava CFXタグで実装する事を検討しても良いのではないでしょうか。