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

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>

Related

Table shift to left when one column hide in jasper table?

I am using jasper report and trying to make RTL report. My problem is that when I am hiding my column in table using printWhenExpression based on some condition my table shift to left. I am using below code to hide column in table.
<jr:column width="160" uuid="f9b26e92-337e-4fb9-a091-4a81469c6c49">
<printWhenExpression><![CDATA[System.getProperty("vehicle.event.uid.enabled").equals("true")]]></printWhenExpression>
<jr:columnHeader style="ColumnHeader" height="30" rowSpan="1">
<textField>
<reportElement style="ColumnHeader" x="0" y="0" width="160" height="30" uuid="b4043ada-2580-4602-9262-3791ce3c0807"/>
<textElement>
<font size="8" isBold="true" isItalic="false"/>
</textElement>
<textFieldExpression><![CDATA[$R{target.external.id}]]></textFieldExpression>
</textField>
</jr:columnHeader>
<jr:detailCell style="table_TD" height="20" rowSpan="1">
<textField isBlankWhenNull="true">
<reportElement style="TableTextContent" x="0" y="0" width="160" height="20" isPrintWhenDetailOverflows="true" uuid="9dc36daa-d5e5-417c-831d-ff1b92ef1b79"/>
<textElement>
<font size="8" isBold="false" isItalic="false"/>
</textElement>
<textFieldExpression><![CDATA[$F{personExternalId}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
is there is any way so that my table should not shift to left when one of its column which is on left in that table is dynamically hide?
If you want to keep the column and does not want text, remove print when condition on column and add it to text expression :
<textFieldExpression><![CDATA[System.getProperty("vehicle.event.uid.enabled").equals("true")?$R{target.external.id} : ""]]></textFieldExpression>

Jasper Reports - check if table is empty (no records) and hide table label

My scenario: 2 tables on Summary field, each table has its own dataset. Also, each table is labelled so there is a label just on top each table.All is ok, however if there is no data in table, table is not printed but table label is still visible.
I need to hide table label if table has no data. Is it even possible? I can't find any solution how to determine if table is empty or not, to set is as expression that will hide label.
Any ideas?
There is no problem to get the record count from your table component this is done by returning value
<returnValue fromVariable="REPORT_COUNT" toVariable="TABLE_COUNT"/>
However this will not solve you problem since you can not set the evalutationTime of the printWhenExpression, you can only set evalutationTime of the textFieldExpression
The problem is normally solved by moving your "table label" where it is expected to be, in the table header
From IDE group your columns and add the textField in the groupHeader inside the table header.
Example (jrxml result)
<componentElement>
<reportElement key="table" style="table" x="0" y="33" width="360" height="50" uuid="6a7d5ab9-f15d-4676-85b2-1e48f016c155"/>
<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">
<datasetRun subDataset="tableData" uuid="fa5df3de-f4c5-4bfc-8274-bd064e8b81e6">
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
</datasetRun>
<jr:columnGroup width="217" uuid="c96f6ab0-8cce-4dc7-b686-da6928e7cabb">
<jr:tableHeader height="61" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="217" height="61" uuid="98aa260d-7e84-4df7-89cc-fc1eabdcf656"/>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<textFieldExpression><![CDATA["MY TABLE LABEL"]]></textFieldExpression>
</textField>
</jr:tableHeader>
<jr:column width="90" uuid="889a828a-ad48-40a0-81f4-326a95d6585c">
<jr:columnHeader style="table_CH" height="60" rowSpan="1"/>
<jr:detailCell style="table_TD" height="43" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="90" height="43" uuid="82b2a835-4373-4638-b75a-d43f531678ba"/>
<textFieldExpression><![CDATA[$F{myField1}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
<jr:column width="127" uuid="004c3afe-c39f-44e2-a82d-5c96697ebd7e">
<jr:columnHeader style="table_CH" height="60" rowSpan="1"/>
<jr:detailCell style="table_TD" height="43" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="90" height="43" uuid="90287319-765f-49a0-9f80-0851f40f2b13"/>
<textFieldExpression><![CDATA[$F{myField2}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:columnGroup>
</jr:table>
</componentElement>

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>

New lines in server generated report text field but not in iReport

I have a table in iReport which generates to a PDF correctly:
<componentElement>
<reportElement key="server vendor table" style="table" x="272" y="437" width="150" height="115"/>
<jr:table>
<jr:column width="50">
<jr:columnHeader style="table_CH" height="15" rowSpan="1">
<staticText>
<reportElement x="5" y="0" width="45" height="15"/>
<textElement/>
<text><![CDATA[Server Vendor]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell style="table_TD" height="18" rowSpan="1">
<textField>
<reportElement x="5" y="0" width="45" height="15"/>
<textElement/>
<textFieldExpression><![CDATA[$F{vendor}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
<jr:column width="50">
<jr:columnHeader style="table_CH" height="15" rowSpan="1">
<staticText>
<reportElement x="5" y="0" width="45" height="15"/>
<textElement/>
<text><![CDATA[# Hosts]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell style="table_TD" height="18" rowSpan="1">
<textField>
<reportElement x="5" y="0" width="45" height="15"/>
<textElement/>
<textFieldExpression><![CDATA[$F{count}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
<jr:column width="50">
<jr:columnHeader style="table_CH" height="15" rowSpan="1">
<staticText>
<reportElement x="5" y="0" width="45" height="15"/>
<textElement/>
<text><![CDATA[Host %]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell style="table_TD" height="18" rowSpan="1">
<textField>
<reportElement x="5" y="0" width="45" height="15"/>
<textElement/>
<textFieldExpression><![CDATA[$F{pc}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
When generating the report from iReport, the PDF is generated correctly, the result is:
But when generated using Java the text entry for "HP" in the first column is split across multiple lines:
Note that only the "HP" text is split - longer text with a space in it (e.g. "Dell inc.") is not split.
I'm guessing that I need to set some properties, but I can't see figure out which property I need to set.
Class.forName("org.postgresql.Driver");
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/hardwaredata","???","???");
InputStream input = new FileInputStream(new File("/reports/hardware_report.jrxml"));
JasperDesign design = JRXmlLoader.load(input);
input.close();
Map<String, Object> param_map = new HashMap<String, Object>();
JasperReport jReport = JasperCompileManager.compileReport(design);
JasperPrint jPrint = JasperFillManager.fillReport(jReport, param_map, conn);
String path = application.getRealPath("/") + "/"+"static_report.pdf";
JasperExportManager.exportReportToPdfFile(jPrint, path);
I have seen this before. I don't recall finding the true cause. Equally strangely (but happily) I found that strings like "HP " don't exhibit this behavior.
Try changing your text field to display this: $F{Vendor} + " "
Be sure to also log a bug! But that might be good enough to solve immediate problems.
In the properties for the text that is aligning vertically check-mark the field titled "Stretch with overflow"

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.