Currently I'm using JasperReports to generate pdfs displaying a list of payments, one entity per page. Code for that (for one entity):
Map<String, Object> parameters = new HashMap<String, Object>();
JasperReport jasperReport = (JasperReport) JRLoader.loadObjectFromFile(path + "WEB-INF/jasper/PaymentOrder.jasper");
report = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
What I need to do is to display two enitities in one file. I'm trying to use subreports to do that.
Master report:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report name" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<title>
<band height="531" splitType="Stretch">
<textField isBlankWhenNull="true">
<reportElement x="0" y="0" width="555" height="20"/>
<textElement verticalAlignment="Middle">
<font fontName="Times New Roman" isUnderline="false" pdfEncoding="UTF-8" isPdfEmbedded="true"/>
</textElement>
<textFieldExpression><![CDATA["* MASTER REPORT *"]]></textFieldExpression>
</textField>
<subreport runToBottom="false">
<reportElement positionType="Float" x="0" y="55" width="555" height="15" isPrintInFirstWholeBand="true" isPrintWhenDetailOverflows="true"/>
<dataSourceExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get( "subReport1Params" )]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get( "subReport1" )]]></subreportExpression>
</subreport>
</band>
</title>
</jasperReport>
Subreport:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report name" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<title>
<band height="531" splitType="Stretch">
<textField isBlankWhenNull="true">
<reportElement x="0" y="0" width="555" height="20"/>
<textElement verticalAlignment="Middle">
<font fontName="Times New Roman" isUnderline="false" pdfEncoding="UTF-8" isPdfEmbedded="true"/>
</textElement>
<textFieldExpression><![CDATA[$P{REPORT_RESOURCE_BUNDLE}.getString( "user" ) + ": "+$P{REPORT_PARAMETERS_MAP}.get( "user" )]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="0" y="22" width="555" height="22"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="Times New Roman" isUnderline="false" pdfEncoding="UTF-8" isPdfEmbedded="true"/>
</textElement>
<textFieldExpression><![CDATA[$P{REPORT_RESOURCE_BUNDLE}.getString( "payment" ) + " № "+$P{REPORT_PARAMETERS_MAP}.get( "docNumber" )+" "+$P{REPORT_RESOURCE_BUNDLE}.getString( "from" ) + " "+$P{REPORT_PARAMETERS_MAP}.get( "date" )]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
java code:
HashMap<String, Object> parameters = getParametersForPayment(doc1, user, locale);
String path = ((WebApplication) Application.get()).getServletContext().getRealPath("/");
File fileSubReport1 = new File(path + "WEB-INF/jasper/PaymentOrder.jasper");
parameters.put("subReport1", JRLoader.loadObject(fileSubReport1));
File f = new File(path + "WEB-INF/jasper/PaymentMaster.jasper");
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(f);
report = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
You are right, you can pass parameters via REPORT_PARAMETERS_MAP parameter or with help of subreportParameter, subreportParameterExpression.
You can use subreportExpression with parameters.
In case you are passing the REPORT_PARAMETERS_MAP to the subreport you do not need to do anything else.
You was so close to solve your task. Your mistakes are:
$P{REPORT_RESOURCE_BUNDLE}
Another recommendation is too add parameters declaration in template. It is easier to support reports in this case and it is a good style.
The main report and two subreports will be used in example. The name of the subreport to use will be passed via parameters from Java code. I'll add internationalization support for en_US locale. Only parameters will be used for showing data (without any datasource).
The small resource bundle master_en_US.properties is using.
user=User:
payment=Payment:
from=From:
There are two ways if we are passing ALL parameters from the Java code: we can declare parameters in jrxml file or we can skip this step. As I said, I prefer the variant with declaration in template (first case).
In first case the template will be:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="master" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" resourceBundle="master" whenNoDataType="AllSectionsNoDetail">
<parameter name="user" class="java.lang.String" isForPrompting="false"/>
<parameter name="docNumber" class="java.lang.String"/>
<parameter name="date" class="java.lang.String"/>
<parameter name="subReportName" class="java.lang.String">
<defaultValueExpression><![CDATA["subreport_1"]]></defaultValueExpression>
</parameter>
<title>
<band height="241" splitType="Stretch">
<subreport>
<reportElement x="0" y="20" width="326" height="59" uuid="f629d1c8-658f-4ae0-a492-2912a7868e96"/>
<parametersMapExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}]]></parametersMapExpression>
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
<subreportExpression><![CDATA[$P{subReportName} + ".jasper"]]></subreportExpression>
</subreport>
</band>
</title>
</jasperReport>
And in the second case:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="master" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" resourceBundle="master" whenNoDataType="AllSectionsNoDetail">
<title>
<band height="241" splitType="Stretch">
<subreport>
<reportElement x="0" y="20" width="326" height="59" uuid="f629d1c8-658f-4ae0-a492-2912a7868e96"/>
<parametersMapExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}]]></parametersMapExpression>
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
<subreportExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get("subReportName") + ".jasper"]]></subreportExpression>
</subreport>
</band>
</title>
</jasperReport>
The one subreport will be with parameters declaration block and another one - without.
The subreport_1.jrxml:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="subreport_1" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" whenNoDataType="AllSectionsNoDetail">
<parameter name="user" class="java.lang.String" isForPrompting="false"/>
<parameter name="docNumber" class="java.lang.String"/>
<parameter name="date" class="java.lang.String"/>
<title>
<band height="79" splitType="Stretch">
<textField>
<reportElement x="0" y="10" width="400" height="15" />
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[$P{REPORT_RESOURCE_BUNDLE}.getString("user") + " " + $P{user}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="25" width="400" height="15" />
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[$P{REPORT_RESOURCE_BUNDLE}.getString("payment") + " № " + $P{docNumber} + " " +
$P{REPORT_RESOURCE_BUNDLE}.getString("from") + " " + $P{date}]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
The subreport_2.jrxml:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="subreport_2" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" whenNoDataType="AllSectionsNoDetail">
<title>
<band height="79" splitType="Stretch">
<textField>
<reportElement x="0" y="10" width="400" height="15" />
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$P{REPORT_RESOURCE_BUNDLE}.getString("user") + " " + $P{REPORT_PARAMETERS_MAP}.get("user")]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
String subreportName;
// some code
JasperReport jasperReport;
try (InputStream inputStream = JRLoader.getResourceInputStream("master.jrxml")) {
jasperReport = JasperCompileManager.compileReport(JRXmlLoader.load(inputStream));
}
Map<String, Object> params = new HashMap<>();
params.put(JRParameter.REPORT_LOCALE, Locale.US);
params.put("user", "Bruce Wayne");
params.put("docNumber", "Some #");
params.put("date", "03.06.2010");
if (!isNullOrEmpty(subreportName)) {
params.put("subReportName", subreportName); // the default name in this case will be set in master report (<defaultValueExpression><![CDATA["subreport_1"]]></defaultValueExpression>)
}
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JREmptyDataSource());
I've used the PDFExporter and in case of subreport_1 the result will be:
in case of subreport_2 the result will be:
Notes:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With