How to split column headers and detail across two or more pages - jasper-reports

We are building a dynamic report designer that is based on JasperReports. For the most part, we use PDF as the default output.
We are facing a serious problem where, for example, if a user selects eight columns in a report, it may be that the only way to print the report is so that the first 4 columns detail and headers show on the first page and the last 4 column detail and headers show on a second page.
It looks like column breaks are the way to do this and I've been trying them in Jasper Reports, but with no luck. Below I've added the detail band in a jrxml file where I'm trying to use the break element to break to a new page after the third column. I'm trying to use a printWhenExpression on the column break to break before the fourth column.
Note that while this test case is small and really doesn't need a break other reports that are being created have 20+ columns that need to be spread across 3 or more pages.
<detail>
<band height="16" splitType="Stretch">
<textField isBlankWhenNull="true">
<reportElement x="24" y="1" width="100" height="15" uuid="4bb1d713-2c34-42e9-aeb4-63aa41d10060"/>
<textFieldExpression><![CDATA[$F{L_BUILDING_CODE}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="140" y="1" width="100" height="15" uuid="9d55a9e3-fa9f-497b-b744-dd853ac21a4a"/>
<textFieldExpression><![CDATA[$F{L_BUILDING_NAME}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="250" y="1" width="100" height="15" uuid="e70b4bc4-a8a7-4e97-abdc-e58346daa002"/>
<textFieldExpression><![CDATA[$F{L_CITY}]]></textFieldExpression>
</textField>
<break type="Column">
<reportElement key="" x="0" y="1" width="250" height="1" uuid="3bf6f2c0-a0d6-43dd-9d3f-ddd1e46d5fc7" >
<printWhenExpression><![CDATA[$V{COLUMN_NUMBER}.intValue() == 4]]></printWhenExpression>
</reportElement>
</break>
<textField>
<reportElement x="600" y="1" width="100" height="15" uuid="19cb12e8-6474-4776-a9fa-2c7d34e69573"/>
<textFieldExpression><![CDATA[$F{L_STATE_PROVINCE}]]></textFieldExpression>
</textField>
</band>
</detail>
Can someone show me an example of how to do this?

Related

How to set table column footer to the bottom of the detail band?

I'm using table in jasperreport and I need to add table column footer to the bottom just before "group footer" band like
But currently it generates table like here
as you can see a lot of spaces between the table (which in detail band) and group footer band..
<detail>
<band height="80">
<componentElement>
<reportElement key="table1" style="tableStyle" x="1" y="0" width="552" height="80" isPrintWhenDetailOverflows="true" uuid="9a24d27b-9228-4f23-8c02-628268479882">
<printWhenExpression><![CDATA[$V{REPORT_COUNT} == 1]]></printWhenExpression>
</reportElement>
<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" whenNoDataType="AllSectionsNoDetail">
<datasetRun subDataset="TableDataset" uuid="aad66998-86ba-485c-b8f4-3f2f6eda4796">
<dataSourceExpression><![CDATA[$P{datasourceItems}]]></dataSourceExpression>
</datasetRun>
<jr:column width="25" uuid="eb2f74b3-8006-4762-a52e-838f5e08a86f">
<jr:columnHeader height="40" rowSpan="2">
<staticText>
<reportElement style="tableProduct_CH" x="0" y="0" width="25" height="40" uuid="6ce8147d-c282-467a-b348-0d5cf3def735"/>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<text><![CDATA[No]]></text>
</staticText>
</jr:columnHeader>
<jr:columnFooter style="tableProductFooterNoLine" height="20" rowSpan="1"/>
<jr:detailCell height="20" rowSpan="1">
<textField isStretchWithOverflow="true">
<reportElement style="tableProduct_TD" x="0" y="0" width="25" height="20" uuid="fc581740-46a3-4602-b769-18beca53d355"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{no}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column> ...
</jr:table>
</componentElement>
</band>
</detail>
AFIK: This is not possible in jasper reports version <=6.7 (current version at date of answer) using the jr:table component.
You could draw the lines in the background band and then add the footer for example in a groupFooter band, but I would instead suggest that you create a subreport to avoid problems with page break.
The subreport will mimic the table using the standard detail and columnFooter band, again you will be adding the vertical lines in the background band.
How the columnFooter will behave is define by the attribute isFloatColumnFooter hence in your case false

How to create different page footer depending on a condition?

I have a requirement to show different footer depending on a condition.
My footer consists of many static labels and theoretically I can define a 'Print When Expression' for each of the labels. But it is inconvenient.
Q: Is it possible to select a different footer depending on a condition?
If not how else can I handle such situation without having to specify the condition in many places?
The xsd allows none or maximum one pageFooter tag with a maximum of one band.
but
This is a typical example where you can use the frame component, to group your data and decide if to display it.
Example displaying different frame with text fields depending on page number
<pageFooter>
<band height="60" splitType="Stretch">
<frame>
<reportElement x="0" y="0" width="540" height="60" uuid="d0198e94-8325-4909-9804-a8d393600ec5">
<printWhenExpression><![CDATA[$V{PAGE_NUMBER}%2!=0]]></printWhenExpression>
</reportElement>
<textField>
<reportElement x="0" y="0" width="100" height="30" uuid="379e2ac0-63ea-4493-bd38-1b7ca7b35d8c"/>
<textFieldExpression><![CDATA["Text Field 1"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="30" width="100" height="30" uuid="6598ba79-08b6-4997-953d-70b64f159e3b"/>
<textFieldExpression><![CDATA["Text Field 2"]]></textFieldExpression>
</textField>
</frame>
<frame>
<reportElement x="0" y="0" width="540" height="60" uuid="d0198e94-8325-4909-9804-a8d393600ec5">
<printWhenExpression><![CDATA[$V{PAGE_NUMBER}%2==0]]></printWhenExpression>
</reportElement>
<textField>
<reportElement x="0" y="0" width="100" height="30" uuid="379e2ac0-63ea-4493-bd38-1b7ca7b35d8c"/>
<textFieldExpression><![CDATA["Text Field 3"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="30" width="100" height="30" uuid="6598ba79-08b6-4997-953d-70b64f159e3b"/>
<textFieldExpression><![CDATA["Text Field 4"]]></textFieldExpression>
</textField>
</frame>
</band>
</pageFooter>
add the different text of the different pageFooter's to different frame's, then set printWhenExpression on the frame component.

How to merge multiple rows in report?

I wanted to merge multiple rows in JasperReports's report without using crosstab. Is it achievable?
Here I have pasted my jrxml code for removing duplicate printing, but it keep lines around the cell although there is no record inside.
<textField pattern="dd.MM.yyyy" isBlankWhenNull="true">
<reportElement isPrintRepeatedValues="false" x="0" y="0" width="110" height="21" isRemoveLineWhenBlank="true"/>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA[$F{DEPARTURE_DATE}]]></textFieldExpression>
</textField>

How do I hide a table column based on its content?

I have a report which contains a table. I would like to hide the columns of that table based on the result set of the query that backs the table. As an example, here is the XML for one of the columns:
<jr:column width="80">
<printWhenExpression>$F{Total1_header} != null</printWhenExpression>
<jr:columnHeader height="30" rowSpan="1">
<textField isStretchWithOverflow="true" isBlankWhenNull="true">
<reportElement x="0" y="0" width="80" height="30" style="table_CH"/>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression>$F{Total1_header}</textFieldExpression>
</textField>
</jr:columnHeader>
<jr:detailCell style="table_TD" height="20" rowSpan="1">
<textField isStretchWithOverflow="true" isBlankWhenNull="true">
<reportElement x="0" y="0" width="80" height="20"/>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression>$F{Total1}</textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
For some reason, my report is complaining about the printWhenExpression. It claims that $F{Total1_header} does not exist. It does not complain however about the instance of $F{Total1_header} in the textFieldExpression.
I can't figure out why the field is avaiable for the textFieldExpression, but not the printWhenExpression.
Column has 'Column print when' property to hide/show the column by an expression.
Another way to delete columns is to modify the jasper design at runtime, then report compilation and then procees as usually. This method makes it possible to distribute unused width to remaining columns.
Roughly goes like this:
JasperDesign design = ...
JRDesignComponentElement tableElement = (JRDesignComponentElement) design.getTitle().getElementByKey(tableKey);
StandardTable tableComponent = (StandardTable) tableElement.getComponent();
col = tableComponent.getColumns().get(0);
tableComponent.removeColumn(col);
// Then compile the JasperDesign
JasperReport result=JasperCompileManager.compileReport(design);
For future readers
You should use this
<printWhenExpression><![CDATA[$F{Total1_header} != null]]></printWhenExpression>
Instead of
<printWhenExpression>$F{Total1_header} != null</printWhenExpression>

stretch a row to fit the data in jasper reports using iReport

How do i stretch a text field to fit the data, If data exceeds the band height the text field doesn't stretch. I have added the text field tag in my jrxml...
The example:
<textField isStretchWithOverflow="true" pattern="" isBlankWhenNull="true" evaluationTime="Now" hyperlinkType="None" hyperlinkTarget="Self" >
<reportElement
style="dNew"
mode="Opaque"
x="200"
y="0"
width="200"
height="19"
key="value-2"
stretchType="RelativeToTallestObject"
positionType="Float"
isPrintInFirstWholeBand="true"
isPrintWhenDetailOverflows="true"/>
<box></box>
<textElement textAlignment="Center" verticalAlignment="Top">
<font fontName="Arial" pdfFontName="Helvetica"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{DATA2}]]></textFieldExpression>
</textField>
Some bands do not stretch, but if you are talking about the detail band you can do something like this:
<textField isStretchWithOverflow="true" isBlankWhenNull="true">
<reportElement style="base" positionType="Float"
isPrintRepeatedValues="false" x="0" y="3"
width="380" height="26" isRemoveLineWhenBlank="true"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$P{information}]]></textFieldExpression>
</textField>
That is pasted from auto generated XML so there is a lot of extra stuff, but the isStretchWithOverflow="true" should work for you. This will make the field stretch down as the text fills it up.
I ususally use iReport to build my reports and it works quiet nicely. You can switch to an XML view in there too.