Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print footer on first page only

I would like to have a footer appear only on the first page of jasper reports.

After searching the forums, I have seen this question asked and improperly answered several times here. As many have suggested I have tried putting a print when expression on the footer band to prevent it from printing when it isn't the first page like:

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

This does not work though. The result is that none of the attributes of the page footer print, but the footer block still prints and takes up space preventing the detail from using the whole page. Effectively, you have a footer with data on the first page and a footer with no data on every following page.

Does anyone know a trick how to actually make this work?

like image 671
springcorn Avatar asked Nov 21 '12 02:11

springcorn


1 Answers

Definitely there does not seem to be a direct way of achieving it, at least with current version of Jasper libraries available. However here's a very crude workaround that worked for us in a similar requirement. I separated out only the footer management part of the code into a sample project this morning and it works fine.

Notes:

  • Not sure if this works with complex reports (especially if column-footer needs to be printed, as we manually modify the columnFooterOffsetY value). We had to generate a simple report with only title, detail and footer bands.
  • Importantly, i do not recommend using this solution for complex requirements as it may induce maintainability issues in long run (especially if you migrate to a later version of jasperreports library in future which might have modified the report-filling logic).
  • I have used JasperReports library version 5.0.0 for the testing.

How the example is built:

  • Created JRXML with iReport, with a printwhenexpression, new Boolean($V{PAGE_NUMBER}.intValue() == 1, for the page-footer band.
  • Created a Custom report-filler instance, extending the JRVerticalFiller class.

Sample source XML used: (add additional lines to the XML so that the report wraps to multiple pages)

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

<employees>
    <employee id="1001" name="AAA" email="[email protected]" salary="20500.125"/>
    <employee id="1002" name="BBB" email="[email protected]" salary="10000.500"/>
    <employee id="1003" name="CCC" email="[email protected]" salary="12275.750"/>
    <employee id="1004" name="DDD" email="[email protected]" salary="10750.750"/>
</employees>

JRXML created with iReport (with a printwhenexpression for the footer band):

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

Custom report-filler implementation: (this handles the height resetting logic to ensure detail band stretches longer from page 2 onwards)

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

And the Java code that actually uses the custom filler to export a PDF:

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>);
like image 107
emecheon Avatar answered Sep 20 '22 02:09

emecheon