我正在尝试生成带有子报表的JasperReport PDF,但是我无法访问作为参数传递给主报表的JRBeanCollectionDataSource(来自List)。或者说,我只是得到一个空白子报表。自从传递JRBeanCollectionDataSource以来,我希望会出现某种循环。
这是我当前的代码:
Java代码:
@PostMapping(path = "/generate-contract", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity < byte[] > report(
@RequestBody Contract contract) {
Map<String, Object> params = new HashMap<>();
// add params to the MASTER REPORT
params.put("farmName", contract.getFarmName());
params.put("farmLogo", contract.getFarmLogo());
// create a JRBeanCollectionDataSource of the List<Signatory> list
JRBeanCollectionDataSource signatoriesListSubreportDataSource = new JRBeanCollectionDataSource(contract.getSignatoriesList());
// add it as parameters to be read by the master report
params.put("signatoriesListSubreportDataSource", signatoriesListSubreportDataSource);
byte[] bytes = reportService.generatePDFReport("my-master-report", params);
return ResponseEntity
.ok()
.header("Content-Type", "application/pdf; charset=UTF-8")
.header("Content-Disposition", "inline; filename=\"" + contract.getFarmName() + ".pdf\"")
.body(bytes);
}
我正在调用.generatePDF()方法,在该方法中它实际上还会编译主报表和子报表。我不知道这是否正确
@Override
public byte[] generatePDFReport(String inputFileName, Map<String, Object> params) {
return generatePDFReport(inputFileName, params, new JREmptyDataSource());
} // this is where it first goes through
@Override
public byte[] generatePDFReport(String inputFileName,
Map <String, Object> params,
JRDataSource dataSource) { // then proceeds to this method, creating a blank dataSource
byte[] bytes = null;
JasperReport jasperReport = null;
try (ByteArrayOutputStream byteArray = new ByteArrayOutputStream()) {
// Check if a compiled report exists
if (storageService.jasperFileExists(inputFileName)) {
jasperReport = (JasperReport) JRLoader
.loadObject(storageService.loadJasperFile(inputFileName));
}
String mySignatoriesSubReportFileName = "my-subreport-file-name-here";
// Compile report from source and save
String jrxml = storageService.loadJrxmlFile(inputFileName);
String mySubReport = storageService.loadJrxmlFile(mySignatoriesSubReportFileName);
// add logs of master report + subreport here
log.info("{} loaded. Compiling report", jrxml);
log.info("{} loaded. Compiling report", paiwiSignatoriesSubReport);
params.put("SUBREPORT_DIR", FileSystemUtil.rootLocation.toString() + "\\");
// compile the master report together with the subreports
jasperReport = JasperCompileManager.compileReport(jrxml); // master report
JasperReport compiledMySubReport = JasperCompileManager.compileReport(mySubReport); // sub-report
// Save compiled report. Compiled report is loaded next time
JRSaver.saveObject(jasperReport,
storageService.loadJasperFile(inputFileName));
JRSaver.saveObject(compiledMySubReport,
storageService.loadJasperFile(mySignatoriesSubReportFileName));
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params,
dataSource);
bytes = JasperExportManager.exportReportToPdf(jasperPrint);
} catch (JRException | IOException e) {
e.printStackTrace();
log.error("Encountered error when loading jasper file", e);
}
return bytes;
}
这是我的master-report.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="Autogen-contract" pageWidth="612" pageHeight="1008" columnWidth="540" leftMargin="36" rightMargin="36" topMargin="36" bottomMargin="36" whenResourceMissingType="Error" uuid="4d5cd764-f78c-4d28-b2cc-4dadc9e584a1">
<!-- Location of the compiled subreport. -->
<parameter name="SUBREPORT_DIR" class="java.lang.String"/>
<!-- For data source of sub-reports -->
<parameter name="mySignatoriesListSubReportDataSource" isForPrompting="true" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<!-- This one works as of the master report -->
<parameter name="farmName" class="java.lang.String"/>
<!-- More details of the master report here.. -->
<textField>
<reportElement key="" x="135" y="120" width="270" height="20" isRemoveLineWhenBlank="true" uuid="2974af73-36ae-4781-a7b1-1b0a4a498c5c"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="Times New Roman" size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[java.lang.String.format("%s", $P{farmName})]]></textFieldExpression>
</textField>
<subreport>
<reportElement x="1" y="520" width="537" height="20" uuid="fcf375d6-3935-42c9-bc81-1448e6f03ebf"/>
<dataSourceExpression><![CDATA[$P{mySignatoriesListSubReportDataSource}]]></dataSourceExpression>
<subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} + "my-subreport.jasper"]]></subreportExpression>
</subreport>
<!-- More details of the master report here.. -->
</jasperReport>
这是my-subreport.jrxml的样子:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 6.5.1 -->
<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="paiwi-signatories-subreport" pageWidth="612" pageHeight="792" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="55585643-052e-4eee-9632-3c9b06dbec8f">
<subDataset name="Dataset1" uuid="01eaeaca-361c-429f-9e71-e974b4f2beda">
<queryString>
<![CDATA[]]>
</queryString>
</subDataset>
<queryString>
<![CDATA[]]>
</queryString>
<!-- I have a name and address in the Signatory object I passed as a list of Data Source.. -->
<!-- But this doesn't work.. or atleast it doesn't iterate anything -->
<field name = "name" class = "java.lang.String"/>
<field name = "address" class = "java.lang.String"/>
<detail>
<band height="24" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="140" height="20" uuid="5f357ce5-9928-4657-98f7-c7eace9b9e84"/>
<textElement verticalAlignment="Middle">
<font fontName="Times New Roman" size="12"/>
</textElement>
<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="140" y="0" width="400" height="20" uuid="0390ae27-e46b-4bb4-87d0-83d59abfc22e"/>
<textElement verticalAlignment="Middle">
<font fontName="Times New Roman" size="12"/>
</textElement>
<textFieldExpression><![CDATA[$F{address}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
我无法访问子报表中的字段,我什至不知道master-report.xml中的参数farmSignatoriesListSubReportDataSource
是否实际通过并将子报表作为有效数据源输入。
答案 0 :(得分:1)
如果要将报告参数传递给subreport,请使用如下所示的subreportParameter标记。
<subreport>
<reportElement x="-12" y="0" width="553" height="110" uuid="e012100d-4c24-468f-9d97-57cda4a0d64a"/>
<subreportParameter name="cou_ID">
<subreportParameterExpression><![CDATA[$P{mySignatoriesListSubReportDataSource}]]></subreportParameterExpression>
</subreportParameter>
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
<subreportExpression><![CDATA["my-subreport.jasper"]]></subreportExpression>
</subreport>
我希望这会有所帮助。
答案 1 :(得分:0)
首先,您将子报表添加到主报表中。 在主报告中定义参数,您将首先设置farmSignatoriesListSubReportDataSource。
单击添加的子报表,然后打开属性子报表选项卡并打开编辑参数。在那里,您将需要添加一个参数,为subreport的参数命名,并从先前已设置的主报表中选择parameter作为参数表达式。然后,您将在子报表中输入字段。