如何将主报表数据源传递给子报表(JasperReports)?

时间:2019-02-19 11:22:50

标签: java jasper-reports subreport

我正在尝试生成带有子报表的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是否实际通过并将子报表作为有效数据源输入。

2 个答案:

答案 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作为参数表达式。然后,您将在子报表中输入字段。