1. 概要

JasperReports は、PDF、HTML、XLSなどのさまざまな形式で印刷またはエクスポートできるピクセル単位のレポートを作成できるオープンソースのレポートライブラリです。

この記事では、その主要な機能とクラスを調べ、その機能を紹介するための例を実装します。

2. Mavenの依存関係

まず、jasperreports依存関係をpom.xmlに追加する必要があります。

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.4.0</version>
</dependency>

このアーティファクトの最新バージョンはここにあります。

3. レポートテンプレート

レポートデザインはJRXMLファイルで定義されます。 これらは、JasperReportsエンジンが解釈できる特定の構造を持つ通常のXMLファイルです。

ここで、JRXMLファイルの関連する構造のみを見てみましょう。レポート生成プロセスのJava部分をよりよく理解するために、これが私たちの主な焦点です。

従業員情報を表示する簡単なレポートを作成しましょう。

<jasperReport ... >
    <field name="FIRST_NAME" class="java.lang.String"/>
    <field name="LAST_NAME" class="java.lang.String"/>
    <field name="SALARY" class="java.lang.Double"/>
    <field name="ID" class="java.lang.Integer"/>
    <detail>
        <band height="51" splitType="Stretch">
            <textField>
                <reportElement x="0" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression class="java.lang.String">
                  <![CDATA[$F{FIRST_NAME}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="100" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression class="java.lang.String">
                  <![CDATA[$F{LAST_NAME}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="200" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression class="java.lang.String">
                  <![CDATA[$F{SALARY}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

3.1. レポートの編集

レポートエンジンがJRXMLファイルにデータを入力できるように、JRXMLファイルをコンパイルする必要があります。

JasperCompilerManagerクラスを使用してこの操作を実行してみましょう。

InputStream employeeReportStream
  = getClass().getResourceAsStream("/employeeReport.jrxml");
JasperReport jasperReport
  = JasperCompileManager.compileReport(employeeReportStream);

毎回コンパイルしないように、ファイルに保存できます。

JRSaver.saveObject(jasperReport, "employeeReport.jasper");

4. 人口を増やす レポート

コンパイルされたレポートを入力する最も一般的な方法は、データベースのレコードを使用することです。 これには、データを取得するためにエンジンが実行するSQLクエリがレポートに含まれている必要があります。

まず、レポートを変更してSQLクエリを追加しましょう。

<jasperReport ... >
    <queryString>
        <![CDATA[SELECT * FROM EMPLOYEE]]>
    </queryString>
    ...
</jasperReport>

それでは、簡単なデータソースを作成しましょう。

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
      .setType(EmbeddedDatabaseType.HSQL)
      .addScript("classpath:employee-schema.sql")
      .build();
}

これで、レポートに記入できます。

JasperPrint jasperPrint = JasperFillManager.fillReport(
  jasperReport, null, dataSource.getConnection());

レポートはまだパラメータを受け取っていないため、2番目の引数にnullを渡していることに注意してください。

4.1. パラメーター

パラメータは、データソースで検出できないデータをレポートエンジンに渡す場合や、さまざまな実行時の条件に応じてデータが変更される場合に役立ちます。

レポート入力操作で受け取ったパラメーターを使用して、SQLクエリの一部または全体を変更することもできます。

まず、次の3つのパラメーターを受け取るようにレポートを変更しましょう。

<jasperReport ... >
    <parameter name="title" class="java.lang.String" />
    <parameter name="minSalary" class="java.lang.Double" />
    <parameter name="condition" class="java.lang.String">
        <defaultValueExpression>
          <![CDATA["1 = 1"]]></defaultValueExpression>
    </parameter>
    // ...
</jasperreport>

次に、titleパラメータを表示するタイトルセクションを追加しましょう。

<jasperreport ... >
    // ...
    <title>
        <band height="20" splitType="Stretch">
            <textField>
                <reportElement x="238" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression class="java.lang.String">
                  <![CDATA[$P{title}]]></textFieldExpression>
            </textField>
        </band>
    </title>
    ...
</jasperreport/>

次に、minSalaryおよびconditionパラメーターを使用するようにクエリを変更しましょう。

SELECT * FROM EMPLOYEE
  WHERE SALARY >= $P{minSalary} AND $P!{condition}

condition パラメーターを使用する場合は、構文が異なることに注意してください。 これは、パラメーターを標準の PreparedStatement パラメーターとして使用するのではなく、そのパラメーターの値が元々SQLクエリで書き込まれたかのようにエンジンに通知します。

最後に、パラメータを準備してレポートに記入しましょう。

Map<String, Object> parameters = new HashMap<>();
parameters.put("title", "Employee Report");
parameters.put("minSalary", 15000.0);
parameters.put("condition", " LAST_NAME ='Smith' ORDER BY FIRST_NAME");

JasperPrint jasperPrint
  = JasperFillManager.fillReport(..., parameters, ...);

parameters のキーは、レポートのパラメーター名に対応していることに注意してください。 エンジンは、パラメーターが欠落していることを検出すると、パラメーターの defaultValueExpressionから値を取得します(存在する場合)。

5. エクスポート

レポートをエクスポートするには、まず、必要なファイル形式に一致するエクスポータークラスのオブジェクトをインスタンス化します。

次に、以前に入力したレポートを入力として設定し、結果のファイルを出力する場所を定義します。

オプションで、対応するレポートとエクスポート構成オブジェクトを設定して、エクスポートプロセスをカスタマイズできます。

5.1. PDF

JRPdfExporter exporter = new JRPdfExporter();

exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(
  new SimpleOutputStreamExporterOutput("employeeReport.pdf"));

SimplePdfReportConfiguration reportConfig
  = new SimplePdfReportConfiguration();
reportConfig.setSizePageToContent(true);
reportConfig.setForceLineBreakPolicy(false);

SimplePdfExporterConfiguration exportConfig
  = new SimplePdfExporterConfiguration();
exportConfig.setMetadataAuthor("baeldung");
exportConfig.setEncrypted(true);
exportConfig.setAllowedPermissionsHint("PRINTING");

exporter.setConfiguration(reportConfig);
exporter.setConfiguration(exportConfig);

exporter.exportReport();

5.2. XLS

JRXlsxExporter exporter = new JRXlsxExporter();
 
// Set input and output ...
SimpleXlsxReportConfiguration reportConfig
  = new SimpleXlsxReportConfiguration();
reportConfig.setSheetNames(new String[] { "Employee Data" });

exporter.setConfiguration(reportConfig);
exporter.exportReport();

5.3. CSV

JRCsvExporter exporter = new JRCsvExporter();
 
// Set input ...
exporter.setExporterOutput(
  new SimpleWriterExporterOutput("employeeReport.csv"));

exporter.exportReport();

5.4. HTML

HtmlExporter exporter = new HtmlExporter();
 
// Set input ...
exporter.setExporterOutput(
  new SimpleHtmlExporterOutput("employeeReport.html"));

exporter.exportReport();

6. サブレポート

サブレポートは、別のレポートに埋め込まれた標準レポートにすぎません。

まず、従業員の電子メールを表示するレポートを作成しましょう。

<jasperReport ... >
    <parameter name="idEmployee" class="java.lang.Integer" />
    <queryString>
        <![CDATA[SELECT * FROM EMAIL WHERE ID_EMPLOYEE = $P{idEmployee}]]>
    </queryString>
    <field name="ADDRESS" class="java.lang.String"/>
    <detail>
        <band height="20" splitType="Stretch">
            <textField>
                <reportElement x="0" y="0" width="156" height="20"/>
                <textElement/>
                <textFieldExpression class="java.lang.String">
                  <![CDATA[$F{ADDRESS}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

それでは、従業員レポートを変更して、前のレポートを含めましょう。

<detail>
    <band ... >
        <subreport>
            <reportElement x="0" y="20" width="300" height="27"/>
            <subreportParameter name="idEmployee">
                <subreportParameterExpression>
                  <![CDATA[$F{ID}]]></subreportParameterExpression>
            </subreportParameter>
            <connectionExpression>
              <![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
            <subreportExpression class="java.lang.String">
              <![CDATA["employeeEmailReport.jasper"]]></subreportExpression>
        </subreport>
    </band>
</detail>

コンパイルされたファイルの名前でサブレポートを参照し、idEmployeeと現在のレポート接続をパラメーターとして渡すことに注意してください。

次に、両方のレポートをまとめましょう。

InputStream employeeReportStream
  = getClass().getResourceAsStream("/employeeReport.jrxml");
JasperReport jasperReport
  = JasperCompileManager.compileReport(employeeReportStream);
JRSaver.saveObject(jasperReport, "employeeReport.jasper");

InputStream emailReportStream
  = getClass().getResourceAsStream("/employeeEmailReport.jrxml");
JRSaver.saveObject(
  JasperCompileManager.compileReport(emailReportStream),
  "employeeEmailReport.jasper");

レポートに入力してエクスポートするためのコードを変更する必要はありません。

7. 結論

この記事では、JasperReportsライブラリのコア機能について簡単に説明しました。

レポートをコンパイルして、データベースのレコードを入力することができました。 さまざまな実行時条件に従ってレポートに表示されるデータを変更するパラメーターを渡し、サブレポートを埋め込み、それらを最も一般的な形式にエクスポートしました。

この記事の完全なソースコードは、GitHubにあります。