如何从主报告传递参数和资源束到子报告

4

目前我正在使用JasperReports生成PDF,显示支付列表,每个实体一张页面。以下是用于一个实体的代码:

 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());

我需要做的是在一个文件中显示两个实体。我正在尝试使用子报表来实现。

  1. 如何将带有参数的Map传递给我的子报表?
  2. 如果需要,如何更改我的子报表文件以从父级获取参数?
  3. 如何将ResourceBundle从主报表传递到子报表?
  4. 如何设置子报表的名称?

主报表:

<?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> 

子报表:

<?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 代码:

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());

@AlexK,第一个不适合我,因为我没有相同对象的列表,它们是不同的。我需要根据我拥有的对象类型动态加载jasper文件(例如,paymentA.jasper用于paymentA,paymentB.jasper用于paymentB)。在第二个中,他们将REPORT_DATA_SOURCE从主报告传递到子报告。但是我没有从JRDataSource获取数据,而是从Hashmap获取数据(即$P {REPORT_PARAMETERS_MAP} .get(“amount”)) - user1328889
你遇到了什么问题?你可以使用 subreportExpression + 传递 REPORT_PARAMETERS_MAP 到子报表。 - Alex K
@AlexK 我尝试了<dataSourceExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}]]></dataSourceExpression>,但是出现了错误'java.util.HashMap cannot be cast to net.sf.jasperreports.engine.JRDataSource'。 - user1328889
你应该发布小样本(主报告+子报告)。 - Alex K
2个回答

8

问题

如何将带有参数的Map传递给我的子报表?

您是正确的,您可以通过REPORT_PARAMETERS_MAP参数或使用subreportParametersubreportParameterExpression来传递参数。

如何设置子报表的名称?

您可以使用带有参数的subreportExpression

如何从主报表传递ResourceBundle到子报表?

如果您将REPORT_PARAMETERS_MAP传递给子报表,则无需执行其他操作。


您已经接近解决问题了。您的错误是:

  1. 您未为报表设置resourceBundle属性 - 使用$P{REPORT_RESOURCE_BUNDLE}
  2. 您未使用parametersMapExpressionREPORT_PARAMETERS_MAP参数传递给子报表 - 以在子报表中使用参数

另一个建议是在模板中添加参数声明。这样易于支持报表,而且是一种良好的风格。


工作示例

此示例将使用主报表和两个子报表。将通过Java代码传递要使用的子报表的名称。我将为en_US区域设置国际化支持。只使用参数显示数据(不使用任何数据源)。

资源包

使用小的资源包master_en_US.properties

user=User:
payment=Payment:
from=From:

主报告模板

如果我们从Java代码中传递所有参数,有两种方法:我们可以在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="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>

在第二种情况下:

<?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>

子报表

其中一个子报表将带有参数声明块,另一个则不带。

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>

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>

Java代码

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());

输出结果

我使用了 PDFExporter,对于 subreport_1,生成的结果如下:

生成的pdf文件

对于 subreport_2,生成的结果如下:

生成的pdf文件


注:


谢谢您的答复!我按照您的方式更改了我的子报表部分(parametersMapExpression和connectionExpression)。我没有更改我的子报表。我将资源包放在参数中,就像这样 parameters.put(JRParameter.REPORT_RESOURCE_BUNDLE, resBundle)。您说我“没有为报表设置resourceBundle属性”,但我不确定在哪里设置它以及为什么需要这样做。如果我只生成我的子报表,它可以正常工作。但是,如果我尝试使用我的主报表生成,则子报表就无法显示。 - user1328889
不用客气 :) <jasperReport ... resourceBundle="master" .. > - 这是主报告的标题,您可以在iReport/JSS或手动设置。 - Alex K
我已将其添加到我的主报告中,但没有任何变化。PDF仍然为空。顺便说一下,奇怪的是,当我将子报表属性更改为whenNoDataType="AllSectionsNoDetail"时,甚至不会生成pdf,它只是挂起了。(我还编辑了帖子,在那里添加了Java代码) - user1328889
你尝试将subReport1参数的类型更改为JasperReport类了吗?您发布的jrxml文件的代码是否实际(添加resourceBundle后)?您尝试过我的示例吗?它对您有效吗? - Alex K

0
  1. 在主文件中:

  2. 在子文件中:输入代码

  3. 在Java文件中:ResourceBundle resourceBundle = ResourceBundle.getBundle("application", new LOCALE("en"));

HashMap参数 = new HashMap(); 参数.put("REPORT_RESOURCE_BUNDLE", resourceBundle);
JasperFillManager.fillReport(report, 参数, source);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接