インクナビ

[Java] JasperReportで二次元の帳票出力

PDF出力をするときに、何ページにも渡る帳票を出力するのは簡単ですが、二次元方向に伸びるページを出力する方法がなかなか思いつかず、苦労しました。

具体的には、印刷したページを並べてみると以下のような配置になるような帳票の出力です。

+-----+-----+-----+
| A-1 | B-1 | C-1 |
+-----+-----+-----+
| A-2 | B-2 | C-2 |
+-----+-----+-----+
| A-3 | B-3 | C-3 |
+-----+-----+-----+

いろいろ悩んで試行錯誤した結果、以下のような処理で出力することができた!…が、どうにもやり方が回りくどいような。無駄が多い気もするし。でも、とりあえず動いた時点のソースということでメモメモ。

これからデバッグして、問題ないことを確認してから、もっとスマートな方法がないかチャレンジしてみる予定。

FacesContext context = FacesContext.getCurrentInstance();
ExternalContext excon = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) excon.getRequest();
HttpServletResponse response = (HttpServletResponse) excon.getResponse();

// A列用のリスト
List<Map> listA = new ArrayList<Map>();
// B列用のリスト
List<Map> listB = new ArrayList<Map>();
// C列用のリスト
List<Map> listC = new ArrayList<Map>();
// 各列のリストを配列に入れる
List[] list = {listA, listB, listC};

// 上記リストに、実際にはデータが入っているものとして…

int columnNum = list.length;

// InputStream と JRDataSource は配列の数だけ用意していないと
// PDF出力が0byteになってしまうので、ここで用意する。
// fname はコンパイル済みのテンプレートファイルパス
InputStream[] stream = new InputStream[columnNum];
JRDataSource[] ds = new JRDataSource[columnNum];
for (int i = 0; i < columnNum; i++) {
    stream[i] = excon.getResourceAsStream(fname[i]);
    ds[i] = new JRBeanArrayDataSource(list[i].toArray());
}

// ここは特に普段と変更なし
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(
         JRExporterParameter.OUTPUT_STREAM,
         response.getOutputStream());

// いったんA列のデータを変換しておく
JasperPrint jasperPrint = null;
jasperPrint = JasperFillManager.fillReport(
              stream[0], new HashMap(), ds[0]);

// B列以降のデータを変換し、変換したA列に1ページ分ずつ追加していく
for (int i = 1; i < columnNum; i++) {
    JasperPrint jp = JasperFillManager.fillReport(
                     stream[i], new HashMap(), ds[i]);
    for (int j = 0; j < jp.getPages().size(); j++) {
        jasperPrint.addPage((JRPrintPage) jp.getPages().get(j));
    }
}

// PDF出力する
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
request.getSession().setAttribute(
        ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE,
        jasperPrint);
exporter.exportReport();

// 後処理
for (int i = 0; i < columnNum; i++) {
    stream[i].close();
}

JRExporterParameter に JASPER_PRINT_LIST というパラメータがあるんだけど、これを使えばもっとスマートな処理になるかも?ただし、このパラメータの使い方がよくわからないので、今の時点では何とも言えず。

スポンサーリンク

この記事をシェア

アカウントをフォロー