11

我想让页脚只出现在碧玉报告的第一页上。

在搜索论坛后,我看到这个问题在这里被问了好几次,并且回答不当。正如许多人所建议的那样,我尝试在页脚带上放置一个 print when 表达式,以防止它在不是第一页时打印,例如:

new Boolean($V{PAGE_NUMBER}.intValue() == 1)

但这不起作用。结果是没有打印页脚的任何属性,但页脚块仍然打印并占用空间,从而阻止细节使用整个页面。实际上,您在第一页上有一个带有数据的页脚,而在每一页上都有一个没有数据的页脚。

有谁知道如何真正做到这一点的技巧?

4

4 回答 4

6

显然,似乎没有直接的方法来实现它,至少在当前版本的 Jasper 库可用的情况下。然而,这是一个非常粗略的解决方法,它在类似的要求中对我们有用。今天早上我只将代码的页脚管理部分分离到一个示例项目中,它工作正常。

笔记:

  • 不确定这是否适用于复杂的报告(特别是如果需要打印列页脚,因为我们手动修改了 columnFooterOffsetY 值)。我们必须生成一个只有标题、详细信息和页脚区域的简单报告。
  • 重要的是,我不建议将此解决方案用于复杂的需求,因为它可能会导致长期的可维护性问题(特别是如果您将来迁移到可能修改了报告填充逻辑的更高版本的 jasperreports 库)。
  • 我使用 JasperReports 库版本 5.0.0 进行测试。

示例是如何构建的:

  • 使用 iReport 创建了 JRXML,带有 printwhen 表达式,new Boolean($V{PAGE_NUMBER}.intValue() == 1用于页脚带。
  • 创建了一个自定义报告填充器实例,扩展了 JRVerticalFiller 类。

使用的示例源 XML:(在 XML 中添加额外的行,以便报告换行到多个页面)

<?xml version="1.0" encoding="UTF-8"?>

<employees>
    <employee id="1001" name="AAA" email="aaa@somecorp.com" salary="20500.125"/>
    <employee id="1002" name="BBB" email="bbb@somecorp.com" salary="10000.500"/>
    <employee id="1003" name="CCC" email="ccc@somecorp.com" salary="12275.750"/>
    <employee id="1004" name="DDD" email="ddd@somecorp.com" salary="10750.750"/>
</employees>

使用 iReport 创建的 JRXML(带有用于页脚区域的 printwhen 表达式):

<?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="jr_footer_display_test" pageWidth="792" pageHeight="288" orientation="Landscape" columnWidth="752" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="27ac3ae2-27da-484b-b088-b4d79aa973cc">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="0"/>
    <queryString language="xPath">
        <![CDATA[//employee]]>
    </queryString>
    <field name="email" class="java.lang.String">
        <fieldDescription><![CDATA[./@email]]></fieldDescription>
    </field>
    <field name="id" class="java.lang.String">
        <fieldDescription><![CDATA[./@id]]></fieldDescription>
    </field>
    <field name="name" class="java.lang.String">
        <fieldDescription><![CDATA[./@name]]></fieldDescription>
    </field>
    <field name="salary" class="java.lang.String">
        <fieldDescription><![CDATA[./@salary]]></fieldDescription>
    </field>
    <background>
        <band splitType="Stretch"/>
    </background>
    <columnHeader>
        <band height="50">
            <staticText>
                <reportElement uuid="c3d42e71-672e-402f-9fbb-4889be2a269b" x="29" y="2" width="100" height="20"/>
                <textElement/>
                <text><![CDATA[ID]]></text>
            </staticText>
            <staticText>
                <reportElement uuid="a4c42dc4-4276-485a-b5a6-b4e6bd2bc217" x="136" y="2" width="100" height="20"/>
                <textElement/>
                <text><![CDATA[Name]]></text>
            </staticText>
            <staticText>
                <reportElement uuid="157e527b-7ad5-46bf-a06d-2fa0a2686b1e" x="253" y="2" width="100" height="20"/>
                <textElement/>
                <text><![CDATA[Email]]></text>
            </staticText>
            <staticText>
                <reportElement uuid="4d87c542-7057-4bc1-9a7e-fbd6a554f33a" x="386" y="2" width="100" height="20"/>
                <textElement/>
                <text><![CDATA[Salary]]></text>
            </staticText>
        </band>
    </columnHeader>
    <detail>
        <band height="21" splitType="Stretch">
            <textField>
                <reportElement uuid="31d09543-a128-469a-be38-3d8987ba781b" x="29" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement uuid="ce5c11f8-68da-4efd-93fa-e1f1b5ce407f" x="136" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement uuid="300dcc3b-8a2a-489d-8518-7283c95b2f88" x="253" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression><![CDATA[$F{email}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement uuid="a37f2df9-2459-446d-bc47-488a336aa60e" x="386" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression><![CDATA[$F{salary}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
    <pageFooter>
        <band height="40" splitType="Stretch">
        <printWhenExpression><![CDATA[new Boolean($V{PAGE_NUMBER}.intValue() == 1)]]></printWhenExpression>
            <textField>
                <reportElement uuid="3d9beff7-69b8-44d9-af80-2962b9262368" x="29" y="12" width="80" height="20"/>
                <textElement textAlignment="Left"/>
                <textFieldExpression><![CDATA["Page: "+$V{PAGE_NUMBER}]]></textFieldExpression>
            </textField>
        </band>
    </pageFooter>
</jasperReport>

自定义报告填充器实现:(这处理高度重置逻辑以确保从第 2 页开始的详细信息带延伸更长)

public class CustomVerticalFiller extends JRVerticalFiller {

    private JRFillBand detailBand = null;

    private int pageNumber = -1;

    protected CustomVerticalFiller(JasperReportsContext jasperReportsContext, JasperReport jasperReport) throws JRException {
        super(jasperReportsContext, jasperReport);

        detailBand = detailSection.getFillBands()[0];
    }

    // this method gets called after each detail band row is filled
    protected void resolveBandBoundElements(JRFillBand band, byte evaluation) throws JRException {
        if(band == detailBand) {
            if((detailBand.getBreakHeight() > columnFooterOffsetY - offsetY) && (columnIndex == columnCount - 1)) {
                // we have reached end of a page

                pageNumber++;

                // we reset the offset when we are at the end of page 2, so that jasper continues to fill data
                if(pageNumber == 1) {
                    columnFooterOffsetY += pageFooter.getHeight();
                }
            }
        }
    }
}

以及实际使用自定义填充器导出 PDF 的 Java 代码:

InputStream inputStream = new FileInputStream(new File(<my jrxml file path>));

JRDataSource dataSource = new JRXmlDataSource(new File(<my source xml file path>), "//employee");

Map parameters = new HashMap();

JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);

CustomVerticalFiller customVerticalFiller = new CustomVerticalFiller(DefaultJasperReportsContext.getInstance(), jasperReport);
JasperPrint jasperPrint = customVerticalFiller.fill(parameters, dataSource);

JasperExportManager.exportReportToPdfFile(jasperPrint, <target pdf file path>);
于 2013-03-20T14:12:20.147 回答
3

当 PageFooter 的表达式时,您应该将此代码放在 Band Properties Print 上

new Boolean( $V{PAGE_NUMBER}.intValue() == 1 )
于 2014-02-06T07:18:18.070 回答
2

不幸的是,@emecheon 的答案不适用于当前的 jasper 版本(我使用6.7.0),但治疗方法几乎相同。

columnFooterOffsetY在第一页后更改。

这样,您可以为每个页面设置不同大小的页脚。

public class CustomVerticalFiller extends JRVerticalFiller {

    private int pageNumber = 0;

    public CustomVerticalFiller(JasperReportsContext jasperReportsContext, JasperReport jasperReport) throws JRException {
        super(jasperReportsContext, jasperReport);
    }


    @Override
    protected void addPage(JRPrintPage page) {
        super.addPage(page);
        pageNumber++;
        if (pageNumber == 2) {
            columnFooterOffsetY += pageFooter.getHeight();
        }
    }
}
于 2018-10-16T06:59:15.640 回答
0

我用于仅在第一页上打印页脚的表达式如下:
Print When Expression字段中

IF($V{PAGE_NUMBER}.intValue()==1,TRUE( ),FALSE( ))

它检查这是否是第一页,如果是,则返回 true 并打印带区。如果没有,它不会打印任何东西。

如果您想在第一页打印一个页脚,在后面的页面打印一个不同的页脚。我将此代码用作子报表属性的表达式。(表达式时不打印)

IF($V{PAGE_NUMBER}.intValue()==1,"subreportFooter1.jasper","subreportFooter2.jasper")
于 2015-05-04T11:15:10.977 回答