Conditional Formatting according to value in Jasper Reports - jasper-reports

I would like to know if there's a way to re-use conditional formatting for several textFields each one associated to different parameters.
Right now I´ve manage to do it by writing a custom style for each one, but it´s a nightmare to mantain.
Here´s what I´ve got:
<style name="style_door" mode="Transparent" forecolor="#000000">
<conditionalStyle>
<conditionExpression><![CDATA[$P{door}.equals("REPLACE")]]></conditionExpression>
<style mode="Transparent" forecolor="#CC0000"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[$P{door}.equals("REPAIR")]]></conditionExpression>
<style mode="Transparent" forecolor="#FF9900"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[$P{door}.equals("OK")]]></conditionExpression>
<style mode="Transparent" forecolor="#009900"/>
</conditionalStyle>
</style>
<style name="style_window" mode="Transparent" forecolor="#000000">
<conditionalStyle>
<conditionExpression><![CDATA[$P{window}.equals("REPLACE")]]></conditionExpression>
<style mode="Transparent" forecolor="#CC0000"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[$P{window}.equals("REPAIR")]]></conditionExpression>
<style mode="Transparent" forecolor="#FF9900"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[$P{window}.equals("OK")]]></conditionExpression>
<style mode="Transparent" forecolor="#009900"/>
</conditionalStyle>
</style>
<textField>
<reportElement style="style_door" x="112" y="26" width="53" height="13" uuid="07eacbda-9ed8-418e-9f97-937bb44ca976"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="7"/>
</textElement>
<textFieldExpression><![CDATA[$P{door}]]></textFieldExpression>
</textField>
<textField>
<reportElement style="style_window" x="112" y="26" width="53" height="13" uuid="07eacbda-9ed8-418e-9f97-937bb44ca976"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="7"/>
</textElement>
<textFieldExpression><![CDATA[$P{window}]]></textFieldExpression>
</textField>
Notice that the 2 styles are the same, it just change the condition, because it should match a different parameter. And then I apply the style to each textField.
Is there a way I can write a single style and the condition be matched with the value of the element associated to? Or could I pass the element's value as an argument to the style and be used in the condition?
Thank you!

Here is a answer to a similar question from a while back.
I've done some testing and contradictory to the answer linked above I managed to do it without a additional class. All other statements, especially regarding evaluation time and style.evaluation.time still apply. Please read the explanations linked in the answer above.
Example for your application:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.1.1 -->
<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="Apply style withou name" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="c7e9565b-28fb-4eeb-b6e0-cd9bd8460722">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="New Data Adapter"/>
<property name="net.sf.jasperreports.style.evaluation.time.enabled" value="true"/>
<style name="ColoredText">
<conditionalStyle>
<conditionExpression><![CDATA[((String)$V{STORAGE}.get("key")).equals("OK")]]></conditionExpression>
<style forecolor="#009900"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[((String)$V{STORAGE}.get("key")).equals("REPAIR")]]></conditionExpression>
<style forecolor="#FF9900"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[((String)$V{STORAGE}.get("key")).equals("REPLACE")]]></conditionExpression>
<style forecolor="#CC0000"/>
</conditionalStyle>
</style>
<parameter name="door" class="java.lang.String"/>
<parameter name="window" class="java.lang.String"/>
<variable name="STORAGE" class="java.util.Map" calculation="System">
<initialValueExpression><![CDATA[new java.util.HashMap()]]></initialValueExpression>
</variable>
<detail>
<band height="21">
<textField evaluationTime="Auto" isBlankWhenNull="true">
<reportElement x="0" y="0" width="100" height="20" uuid="d9392134-e246-41c7-8c66-9d21f06e0465"/>
<textFieldExpression><![CDATA[$V{STORAGE}.put("key", $P{window}) == null ? null : null]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto" isBlankWhenNull="true">
<reportElement style="ColoredText" x="0" y="0" width="100" height="20" uuid="fda2f3f5-fe34-424e-8af9-b4f0111936b2"/>
<textFieldExpression><![CDATA[$V{STORAGE}.get("key")]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto" isBlankWhenNull="true">
<reportElement x="100" y="0" width="100" height="20" uuid="6dcf014e-ffc9-47be-81ee-04f1912d3be2"/>
<textFieldExpression><![CDATA[$V{STORAGE}.put("key", $P{door}) == null ? null : null]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto" isBlankWhenNull="true">
<reportElement style="ColoredText" x="100" y="0" width="100" height="20" uuid="54cc1367-8387-4fc0-be00-5ba789cce7e9"/>
<textFieldExpression><![CDATA[$V{STORAGE}.get("key")]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>

Related

How to organize Frames in Jasper Report so they float flawlessly?

In a Jasper report I have 4 Frames (below image) which have some properties set as shown in the same image.
Now, the idea is that given certain parameters showBlue and showRed the frames BLUE and RED respectively are shown or hidden and the subsequent frame "floats" after the previous one (taking in consideration the following order: BLUE <- RED <- GREEN) while BLACK should stay in the same place.
The two left frames (RED and GREEN) were floating up perfectly before the BLACK one was set in place. After that when I set the parameters showBlue and showRed to false (hide BLUE and RED frames) this is the result:
This is the jrxml for the report design:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.5.1.final using JasperReports Library version 6.5.1 -->
<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="Float_UP" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="6578bc34-0c2e-4179-99da-5ec1dd90a422">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<parameter name="showBlue" class="java.lang.Boolean"/>
<parameter name="showRed" class="java.lang.Boolean"/>
<queryString>
<![CDATA[]]>
</queryString>
<detail>
<band height="211" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="400" height="12" uuid="54cb1704-59d8-4272-9ec1-db4cea913cd3"/>
<text><![CDATA[Header 1 (right before conditional frame)]]></text>
</staticText>
<frame>
<reportElement x="0" y="15" width="400" height="66" isRemoveLineWhenBlank="true" uuid="0140ba9b-f2f0-494c-82bc-caf6b5efc63e">
<printWhenExpression><![CDATA[$P{showBlue}]]></printWhenExpression>
</reportElement>
<box>
<pen lineWidth="3.0" lineColor="#2E0DD4"/>
</box>
<staticText>
<reportElement x="1" y="1" width="379" height="59" uuid="a8b7d505-a6ad-4359-9263-23ac087b19ff"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[BLUE: `isRemoveLineWhenBlank=true` and `printWhenExpression` set]]></text>
</staticText>
</frame>
<frame>
<reportElement positionType="Float" x="0" y="85" width="400" height="60" isRemoveLineWhenBlank="true" uuid="c80dd879-ce81-4921-b17e-9882763a3f61">
<printWhenExpression><![CDATA[$P{showRed}]]></printWhenExpression>
</reportElement>
<box>
<pen lineWidth="3.0" lineColor="#F50A25"/>
</box>
<staticText>
<reportElement x="0" y="0" width="380" height="50" uuid="d0cadbd4-b436-47f4-a32d-2b00f0c6b147"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[RED: `isRemoveLineWhenBlank=true`, `printWhenExpression` set and `positionType="Float"`]]></text>
</staticText>
</frame>
<frame>
<reportElement positionType="Float" x="2" y="151" width="398" height="60" uuid="e0a5ed13-d8f2-4acd-ac14-1f5633099542"/>
<box>
<pen lineWidth="3.0" lineColor="#22B002"/>
</box>
<staticText>
<reportElement x="1" y="1" width="377" height="39" uuid="482471b4-4c3b-42c6-892d-f8c42ca320bf"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[GREEN: `positionType="Float"`]]></text>
</staticText>
</frame>
<frame>
<reportElement x="420" y="15" width="130" height="70" uuid="8e057d80-72be-4f66-ae9b-ef80610daf36"/>
<box>
<pen lineWidth="3.0"/>
</box>
<staticText>
<reportElement x="6" y="6" width="118" height="44" uuid="36d8e560-3af5-4edf-b9ef-9b9311877c3a"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[BLACK]]></text>
</staticText>
</frame>
</band>
</detail>
</jasperReport>
And I have set up a Java Project with Swagger in case you want to run it with maven.
Q: How can I make frames RED and GREEN to properly "float-up" after its previous frame while frame BLACK stays in the same place?
Yes the green will not float up since the black box is placed immediately above it
From JRElement API
Float - The element floats in its parent section if it is pushed downward by other elements found above it. It tries to conserve the distance between it and the neighboring elements placed immediately above it
Solution
The solutions obviously is to not have any element immediately above it and one way to achieve this is to use another frame or a subreport. If you need elements to float up also under this design you probably will need a subreport but I will show the parent frame solution, because it is the easiest way to solve your direct problem.
Example using a parent frame
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="Float_UP" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="6578bc34-0c2e-4179-99da-5ec1dd90a422">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<parameter name="showBlue" class="java.lang.Boolean"/>
<parameter name="showRed" class="java.lang.Boolean"/>
<queryString>
<![CDATA[]]>
</queryString>
<detail>
<band height="96" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="400" height="12" uuid="54cb1704-59d8-4272-9ec1-db4cea913cd3"/>
<text><![CDATA[Header 1 (right before conditional frame)]]></text>
</staticText>
<frame>
<reportElement x="0" y="15" width="409" height="78" uuid="82076f1d-b7a9-4b63-ab4a-af54b0817a62"/>
<frame>
<reportElement x="0" y="4" width="400" height="66" isRemoveLineWhenBlank="true" uuid="0140ba9b-f2f0-494c-82bc-caf6b5efc63e">
<printWhenExpression><![CDATA[$P{showBlue}]]></printWhenExpression>
</reportElement>
<box>
<pen lineWidth="3.0" lineColor="#2E0DD4"/>
</box>
<staticText>
<reportElement x="1" y="1" width="379" height="59" uuid="a8b7d505-a6ad-4359-9263-23ac087b19ff"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[BLUE: `isRemoveLineWhenBlank=true` and `printWhenExpression` set]]></text>
</staticText>
</frame>
<frame>
<reportElement positionType="Float" x="-1" y="75" width="400" height="60" isRemoveLineWhenBlank="true" uuid="c80dd879-ce81-4921-b17e-9882763a3f61">
<printWhenExpression><![CDATA[$P{showRed}]]></printWhenExpression>
</reportElement>
<box>
<pen lineWidth="3.0" lineColor="#F50A25"/>
</box>
<staticText>
<reportElement x="0" y="0" width="380" height="50" uuid="d0cadbd4-b436-47f4-a32d-2b00f0c6b147"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[RED: `isRemoveLineWhenBlank=true`, `printWhenExpression` set and `positionType="Float"`]]></text>
</staticText>
</frame>
<frame>
<reportElement positionType="Float" x="0" y="140" width="398" height="60" uuid="e0a5ed13-d8f2-4acd-ac14-1f5633099542"/>
<box>
<pen lineWidth="3.0" lineColor="#22B002"/>
</box>
<staticText>
<reportElement x="1" y="1" width="377" height="39" uuid="482471b4-4c3b-42c6-892d-f8c42ca320bf"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[GREEN: `positionType="Float"`]]></text>
</staticText>
</frame>
</frame>
<frame>
<reportElement x="420" y="15" width="130" height="70" uuid="8e057d80-72be-4f66-ae9b-ef80610daf36"/>
<box>
<pen lineWidth="3.0"/>
</box>
<staticText>
<reportElement x="6" y="6" width="118" height="44" uuid="36d8e560-3af5-4edf-b9ef-9b9311877c3a"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[BLACK]]></text>
</staticText>
</frame>
</band>
</detail>
</jasperReport>
Output
Additional design notes
As you can see in output there is a 4px height difference between the green and black box, this is due to the empty space you have between the frames. If you need pixel perfect reports you need to have zero space between the components that you are removing/floating.
Maybe you can try using multiple Detail bands for your report. Thus you can use the property printWhenExpresion on each band, instead of in each frame.
Here you can find your jrxml code modified with an example.

Conditional Style Based on TextField Value [duplicate]

I want to make text in the textValue to be red when the numeric value of the cell is less than zero. Currently my configuration is like this:
<style name="RedText">
<conditionalStyle>
<conditionExpression><![CDATA[$F{col1}.compareTo(BigDecimal.ZERO) == -1]]></conditionExpression>
<style forecolor="#FF0000"/>
</conditionalStyle>
</style>
I have more cells (col2, col3, col4 ...) that I would need to apply this red text style. Is it possible to make it universal for current value, etc. col*?
The standard/classical way without using Java code
It is impossible without using Java code. In your case you need to create the new style for each field and apply this concrete style for textField element with conditionExpression contains the value of concrete field.
In common case the expression of textField can be complex, the same is true for the conditionExpression. The style does not know to which control it belongs. We can't operate with value of abstract field (parameter/variable), the engine need the concrete names to calculate expression.
Using Java API
Is it possible to solve the task applying style with JasperReports Java API. For example:
JRDesignStyle boldStyle = new JRDesignStyle();
boldStyle.setName("Sans_Bold");
boldStyle.setFontName("DejaVu Sans");
boldStyle.setFontSize(12);
boldStyle.setBold(true);
// ...
textField.setStyle(boldStyle);
JRDesignExpression expression = new JRDesignExpression();
expression.setText("$F{col1}");
textField.setExpression(expression);
Using backdoor or "yes we like to hack"
Look at the beatiful class in Java is Map, it so invaluable in JasperReports. It can help us to crack this task.
We need parameter of Map type for storing the value of field (it will be abstract field - "coln")
We need to enable applying style during resolving expression of a textField. The propery
net.sf.jasperreports.style.evaluation.time.enabled will help to enable this feature.
We need some Java method for putting value in to the Map (as a storage of a "coln") which returns the value we just put. The Map.put(K key, V value) is not good for this purpose. I wrote the small Utility class with wrapper over Map.put method.
The datasouce
The using of simple csv datasource is enough for this example. I like this kind of datasource for testing and debugging.
col1,col2,col3,col4,col5
1,2,3,9,-5
-2,6,-3,4,1
2,-2,-2,7,-3
8,3,4,-5,6
The name of data adapter for this datasource in the example below is numbers.csv. The first line from the file is skipped - it is contains the column's name.
Java code
It is a very simple utility class
public class Storage {
public static Integer add(Map<String, Integer> map, String key, Integer value) {
map.put(key, value);
return value;
}
}
Report template
The import for our utitlity class should be added for using it.
For correct resolving expression of conditional style we need to use in expression some parameter or some variable (you can check the source code of JasperReports). I'll add some fake variable for using in conditionExpression
We need to put the value of "coln" to the Map and then use this value in conditional style. In this case we don't need to know the name of field we are checking in conditional style. The parameter will be used for storing Map.
We need place and draw the value of "coln" in two runs. We can use fake invisible textField to put the field's value to the Map and another textField to show value with applying conditional style. The positions and sizes of this textFields are same - one above the other.
Our condition will be like this:
<style name="ColoredText">
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) < 0)]]></conditionExpression>
<style forecolor="blue"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) > 0)]]></conditionExpression>
<style forecolor="green"/>
</conditionalStyle>
</style>
There is no field in conditionExpression and it works :)
The jrxml file:
<?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="Apply style withou name" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="numbers.csv"/>
<property name="net.sf.jasperreports.style.evaluation.time.enabled" value="true"/>
<import value="some.package.Storage"/>
<style name="ColoredText">
<conditionalStyle>
<conditionExpression><![CDATA[$P{STORAGE}.get($P{KEY}) == null && !"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style forecolor="#CC0000"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) < 0) && !"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style forecolor="#0037FF"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) > 0) && !"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style forecolor="#00BA00"/>
</conditionalStyle>
</style>
<style name="Fake">
<conditionalStyle>
<conditionExpression><![CDATA[!"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style mode="Opaque" forecolor="#FFFFFF" backcolor="#FFFFFF"/>
</conditionalStyle>
</style>
<parameter name="STORAGE" class="java.util.Map">
<defaultValueExpression><![CDATA[new java.util.HashMap()]]></defaultValueExpression>
</parameter>
<parameter name="KEY" class="java.lang.String">
<defaultValueExpression><![CDATA["key"]]></defaultValueExpression>
</parameter>
<field name="col1" class="java.lang.Integer"/>
<field name="col2" class="java.lang.Integer"/>
<field name="col3" class="java.lang.Integer"/>
<field name="col4" class="java.lang.Integer"/>
<field name="col5" class="java.lang.Integer"/>
<variable name="FAKE" class="java.lang.String">
<variableExpression><![CDATA["FAKE"]]></variableExpression>
</variable>
<detail>
<band height="20">
<textField evaluationTime="Auto">
<reportElement style="Fake" x="0" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col1})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="0" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="100" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col2})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="100" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="200" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col3})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="200" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="300" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col4})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="300" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="400" y="0" width="140" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col5})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="400" y="0" width="140" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
The green color is used for positive numbers and blue - for negative. The red color is using to indicate algorithm's problems.
Output result
The generated pdf with help of JRPdfExporter:

How to get current element in JasperReports when using conditionalExpression with styles?

I want to make text in the textValue to be red when the numeric value of the cell is less than zero. Currently my configuration is like this:
<style name="RedText">
<conditionalStyle>
<conditionExpression><![CDATA[$F{col1}.compareTo(BigDecimal.ZERO) == -1]]></conditionExpression>
<style forecolor="#FF0000"/>
</conditionalStyle>
</style>
I have more cells (col2, col3, col4 ...) that I would need to apply this red text style. Is it possible to make it universal for current value, etc. col*?
The standard/classical way without using Java code
It is impossible without using Java code. In your case you need to create the new style for each field and apply this concrete style for textField element with conditionExpression contains the value of concrete field.
In common case the expression of textField can be complex, the same is true for the conditionExpression. The style does not know to which control it belongs. We can't operate with value of abstract field (parameter/variable), the engine need the concrete names to calculate expression.
Using Java API
Is it possible to solve the task applying style with JasperReports Java API. For example:
JRDesignStyle boldStyle = new JRDesignStyle();
boldStyle.setName("Sans_Bold");
boldStyle.setFontName("DejaVu Sans");
boldStyle.setFontSize(12);
boldStyle.setBold(true);
// ...
textField.setStyle(boldStyle);
JRDesignExpression expression = new JRDesignExpression();
expression.setText("$F{col1}");
textField.setExpression(expression);
Using backdoor or "yes we like to hack"
Look at the beatiful class in Java is Map, it so invaluable in JasperReports. It can help us to crack this task.
We need parameter of Map type for storing the value of field (it will be abstract field - "coln")
We need to enable applying style during resolving expression of a textField. The propery
net.sf.jasperreports.style.evaluation.time.enabled will help to enable this feature.
We need some Java method for putting value in to the Map (as a storage of a "coln") which returns the value we just put. The Map.put(K key, V value) is not good for this purpose. I wrote the small Utility class with wrapper over Map.put method.
The datasouce
The using of simple csv datasource is enough for this example. I like this kind of datasource for testing and debugging.
col1,col2,col3,col4,col5
1,2,3,9,-5
-2,6,-3,4,1
2,-2,-2,7,-3
8,3,4,-5,6
The name of data adapter for this datasource in the example below is numbers.csv. The first line from the file is skipped - it is contains the column's name.
Java code
It is a very simple utility class
public class Storage {
public static Integer add(Map<String, Integer> map, String key, Integer value) {
map.put(key, value);
return value;
}
}
Report template
The import for our utitlity class should be added for using it.
For correct resolving expression of conditional style we need to use in expression some parameter or some variable (you can check the source code of JasperReports). I'll add some fake variable for using in conditionExpression
We need to put the value of "coln" to the Map and then use this value in conditional style. In this case we don't need to know the name of field we are checking in conditional style. The parameter will be used for storing Map.
We need place and draw the value of "coln" in two runs. We can use fake invisible textField to put the field's value to the Map and another textField to show value with applying conditional style. The positions and sizes of this textFields are same - one above the other.
Our condition will be like this:
<style name="ColoredText">
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) < 0)]]></conditionExpression>
<style forecolor="blue"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) > 0)]]></conditionExpression>
<style forecolor="green"/>
</conditionalStyle>
</style>
There is no field in conditionExpression and it works :)
The jrxml file:
<?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="Apply style withou name" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="numbers.csv"/>
<property name="net.sf.jasperreports.style.evaluation.time.enabled" value="true"/>
<import value="some.package.Storage"/>
<style name="ColoredText">
<conditionalStyle>
<conditionExpression><![CDATA[$P{STORAGE}.get($P{KEY}) == null && !"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style forecolor="#CC0000"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) < 0) && !"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style forecolor="#0037FF"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA[(((Integer)$P{STORAGE}.get($P{KEY})) > 0) && !"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style forecolor="#00BA00"/>
</conditionalStyle>
</style>
<style name="Fake">
<conditionalStyle>
<conditionExpression><![CDATA[!"null".equalsIgnoreCase($V{FAKE})]]></conditionExpression>
<style mode="Opaque" forecolor="#FFFFFF" backcolor="#FFFFFF"/>
</conditionalStyle>
</style>
<parameter name="STORAGE" class="java.util.Map">
<defaultValueExpression><![CDATA[new java.util.HashMap()]]></defaultValueExpression>
</parameter>
<parameter name="KEY" class="java.lang.String">
<defaultValueExpression><![CDATA["key"]]></defaultValueExpression>
</parameter>
<field name="col1" class="java.lang.Integer"/>
<field name="col2" class="java.lang.Integer"/>
<field name="col3" class="java.lang.Integer"/>
<field name="col4" class="java.lang.Integer"/>
<field name="col5" class="java.lang.Integer"/>
<variable name="FAKE" class="java.lang.String">
<variableExpression><![CDATA["FAKE"]]></variableExpression>
</variable>
<detail>
<band height="20">
<textField evaluationTime="Auto">
<reportElement style="Fake" x="0" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col1})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="0" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="100" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col2})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="100" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="200" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col3})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="200" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="300" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col4})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="300" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="Fake" x="400" y="0" width="140" height="20"/>
<textFieldExpression><![CDATA[some.package.Storage.add($P{STORAGE}, $P{KEY}, $F{col5})]]></textFieldExpression>
</textField>
<textField evaluationTime="Auto">
<reportElement style="ColoredText" x="400" y="0" width="140" height="20"/>
<textFieldExpression><![CDATA[$P{STORAGE}.get($P{KEY})]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
The green color is used for positive numbers and blue - for negative. The red color is using to indicate algorithm's problems.
Output result
The generated pdf with help of JRPdfExporter:

jasper report is not showing table when using java bean datasource

I am using JasperReports in my project using table component in the summary band and
providing data with JRBeanCollectionDataSource but after extracting the report getting only title of the report and table is not displaying.
Here is my .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="CampaignSummary" language="groovy" pageWidth="1400" pageHeight="1000" orientation="Landscape" columnWidth="1360" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ef078799-c539-490f-b244-d493f4522ef2">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="163"/>
<property name="ireport.y" value="0"/>
<style name="table">
<box>
<pen lineWidth="1.0" lineColor="#000000"/>
</box>
</style>
<style name="table_TH" mode="Opaque" backcolor="#00FFFF"/>
<style name="table_CH" mode="Opaque" backcolor="#BFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#000000"/>
</box>
</style>
<style name="table_TD" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#000000"/>
</box>
<conditionalStyle>
<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
<style backcolor="#EFFFFF"/>
</conditionalStyle>
</style>
<subDataset name="TableDataset" uuid="c99fd89d-9d8f-488f-95db-360a7f5aba96">
<field name="CampaignID" class="java.lang.String">
<fieldDescription><![CDATA[me.CampaignID]]></fieldDescription>
</field>
<field name="CampaignName" class="java.lang.String">
<fieldDescription><![CDATA[Campaign Name]]></fieldDescription>
</field>
.
.
.
......some more fields....
.
.
<field name="NetImpact" class="java.lang.String">
<fieldDescription><![CDATA[Net Impact]]></fieldDescription>
</field>
</subDataset>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="54" splitType="Stretch">
<staticText>
<reportElement uuid="8b41287b-3930-416a-ba00-7f4a9c907e26" x="0" y="0" width="1360" height="54"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="Arial Rounded MT Bold" size="24"/>
</textElement>
<text><![CDATA[Campaign Summary Report]]></text>
</staticText>
</band>
</title>
<summary>
<band height="239" splitType="Stretch">
<frame>
<reportElement uuid="61313d06-6df1-4212-ab8f-8e311dc5ad33" x="0" y="0" width="1360" height="87"/>
</frame>
<frame>
<reportElement uuid="c04b08f6-89d3-4104-87ba-adecd3c4f7dd" x="0" y="87" width="1360" height="152"/>
<componentElement>
<reportElement uuid="8afc21c1-7b57-4dab-8178-8810c1183dd9" key="table" style="table" x="0" y="0" width="1360" height="152"/>
<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="TableDataset">
<dataSourceExpression>
<![CDATA[($P{REPORT_DATA_SOURCE})]]>
</dataSourceExpression>
</datasetRun>
<jr:column width="90" uuid="eece2ecf-027d-4ef1-bd05-8d7d6bbbc0b0">
<jr:columnHeader style="table_CH" height="30" rowSpan="1">
<staticText>
<reportElement uuid="c0d108a0-9f4b-4ec3-b9d0-664ea0724584" x="0" y="0" width="90" height="30"/>
<textElement/>
<text><![CDATA[Campaign Name]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell style="table_TD" height="20" rowSpan="1">
<textField>
<reportElement uuid="6a8f7bf6-5e9b-4f77-a524-9a8d7f0ee2ca" x="0" y="0" width="90" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[String.valueOf($F{CampaignName})]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
.
.
.some more columns...
.
<jr:column width="80" uuid="312f9143-cee8-46fb-a296-27172c4fca98">
<jr:columnHeader style="table_CH" height="30" rowSpan="1">
<staticText>
<reportElement uuid="22ec2935-d4a9-4b64-856d-e64d72f0d856" x="0" y="0" width="80" height="30"/>
<textElement/>
<text><![CDATA[Net Impact]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell style="table_TD" height="20" rowSpan="1">
<textField>
<reportElement uuid="071cddad-63f1-47bc-8da5-a2d6752e3abe" x="0" y="0" width="80" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[String.valueOf($F{NetImpact})]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
</frame>
</band>
</summary>
and java code is
CampaignSummaryBeanFactory campaignSummaryBeanFactory =new CampaignSummaryBeanFactory();
JasperFillManager.fillReportToFile("build/reports/CampaignSummary.jasper", null, new JRBeanCollectionDataSource(campaignSummaryBeanFactory.getCampaignSummaryBeans()));
Table will not be displayed if it is empty.
Do you have any element in campaignSummaryBeanFactory.getCampaignSummaryBeans()?
For the case when you have no data, put something in the "No Data" band, some static text like 'No data to display' or even the header of your table, if you want to see the empty table when you have no rows.
As far as you code goes, the table will also be empty if you have 1 element in the datasource. Otherwise it will skeep the first record in the list. See Jasper report missing first row
You will find some people who tells you to put table in summary band. But that is the reason your table is not displaying. Put it in a detail band.

JasperReport - condition in TextElement

I'm new at JasperReports.
I want to get italic text when some variable will be set at '3'.
Here's my code:
<textElement>
<font size="9" pdfFontName="Helvetica" pdfEncoding="Cp1250" isPdfEmbedded="true"
isItalic=<![CDATA[$F{variable}==3 ? "true" : "false"]]> />
</textElement>
What am I doing wrong?
I tried also make conditional style but wherever I put i recive error.
You cannot use set value of the property isItalic (and many others) with help of expressions.
In your case you should use the conditional style.
The sample:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport ..>
<style name="customStyle">
<conditionalStyle>
<conditionExpression><![CDATA[$F{variable} == 3]]></conditionExpression>
<style isItalic="true"/>
</conditionalStyle>
</style>
...
<detail>
<band height="20" splitType="Stretch">
<textField>
<reportElement style="customStyle" mode="Opaque" x="100" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{value}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>