JasperReports: using variable in variable's expression - variables

I am using Jaspersoft Studio and am trying to set a variable to the value of another variable (well actually, I will need a sum of two variables in another variable)
So I have two variables, A and B. I need to put A in B. Whenever I use a textfield to output A, it works fine. If in the variable B, I put a ($V{A}), and I try to print B, I get a null.
Does anyone have a clue as to why this happens?
Report X contains subreport Y which returns a variable
<returnValue subreportVariable="EXPENDITURES_TOTAL_VAR" toVariable="EXPENDITURES_TOTAL_VAR" incrementerFactoryClass=""/>
(note the same variable name in both reports)
Report X then contains another variable
<variable name="STOTAL_VAR" class="java.lang.Double" calculation="Sum">
<variableExpression><![CDATA[$V{EXPENDITURES_TOTAL_VAR}]]></variableExpression>
</variable>
This WORKS:
<textField>
<reportElement x="120" y="1" width="70" height="30" uuid="f0e81b0f-ddd3-4f31-9711-cfdeb64f36b2"/>
<textFieldExpression><![CDATA[$V{EXPENDITURES_TOTAL_VAR}]]></textFieldExpression>
</textField>
This does not:
<textField>
<reportElement x="310" y="1" width="100" height="30" uuid="263973e7-33b1-4343-a76c-3edbe5506d66"/>
<textFieldExpression><![CDATA[$V{STOTAL_VAR}]]></textFieldExpression>
</textField>

As this is one of the first SO hits when searching for Jasper reports and use variable within other variable and this doesn't give any help - maybe this answer here can help others who search for an answer for how to use a variable within another variable in an iReport:
Taken from here: http://www.jasperassistant.com/docs/guide/ch06s08.html, the short answer is:
Yes you can use a variable within another variable within an iReport - but the variable which you want to use in the other variable must be declared first - so the sequence of the variable matters.
Hope this helps someone.

Related

How to create a running total over pages?

What I want to achieve is a cumulative subtotal on the bottom of each page.
On the first page the total for that page of a column (let’s call this column A ) would be displayed. On the second page the total of page one and page two for column A is displayed and so on until the last page on which the overall total is shown.
Can someone provide me with a way to achieve this?
To create accumulate sum's over page, columns, group's you can used the evaluationTime attribute on the textField
The setup is:
Create a variabile that calculates the value (in your case a sum on a field)
<variable name="mySumVar" class="java.lang.Double" calculation="Sum">
<variableExpression><![CDATA[$F{myFieldToSum}]]></variableExpression>
</variable>
Important do not set resetType on variabile, this would reset the value accordingly and instead we want a accumulative value
Now as report is running (detail band iterating) this variabile will have the current value (sum of fields iterated).
To display an accumulative value relative to page, group etc, we use a textField with relative evaluationTime (if on bottom of page for example in columnFooter if on top you can use columnHeader).
In your case you want accumulative on page so you set evaluationTime="Page"
<textField evaluationTime="Page">
<reportElement x="0" y="0" width="100" height="30" uuid="6736d772-987d-4ad0-af4c-9d19e631eb07"/>
<textFieldExpression><![CDATA[$V{mySumVar}]]></textFieldExpression>
</textField>

How to increment variable to count headlines, titles?

I have a JasperReports template, where I need to count the headlines of different "detail bands".
Now, since the headlines can vary (some datasets can be empty and then the whole band is not rendered), I wanted to use a variable for that.
The build-in variables does not suite, since they don't have a "detail_band_count" or something.
Moreover there is not always a headline in one detail band, there can be 1 or 10 following detail bands, where band 2 - 10 shares the same headline declared in band 1.
However, I managed to create a variable in this manner; but it only counts the pages.
Is there a possibility to call the Variable Expression on Variable access? So it would always increment, as soon as I write $V{headline_COUNT}?
It's hard for me to see how you can use variables, you would probably need to restructure report, find a grouping strategy, since you need to set incrementType to one of the available values and you are correct you can't select "header line" or similar.
However, there is a workaround that you can use to count how many time a specific element is showed using the parameter map $P{REPORT_PARAMETERS_MAP}
Define your counting parameter with a default value (avoid it starting as null)
<parameter name="countReportElement" class="java.lang.Integer" isForPrompting="false">
<defaultValueExpression><![CDATA[0]]></defaultValueExpression>
</parameter>
Now on any text field or other element in the band you like to count, you can use a fake printWhenExpression, to increment this parameter
<reportElement x="0" y="262" width="320" height="25" uuid="8fa62997-ffa2-4777-923b-999d372ce09e">
<printWhenExpression><![CDATA[($P{REPORT_PARAMETERS_MAP}.put("countReportElement",((Integer)$P{REPORT_PARAMETERS_MAP}.get("countReportElement"))+1))!=null?true:false]]></printWhenExpression>
</reportElement>
Note the ternary operation will always evaluate true (since Map.put(K key, V value) will return previous object) and put into the parameter map the value incremented by one every time element is evaluated.
To display the value of your count you access the parameter map directly.
<textField>
<reportElement x="57" y="13" width="100" height="20" uuid="7ca30577-0ca9-47c2-91ae-c7002fbbfbf7"/>
<textFieldExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get("countReportElement")]]></textFieldExpression>
</textField>
be sure to set evaluationTime as need in report.

Jasper Report How to print ReportElement on next page when it doesn't fit on the same page?

In my code I have large amount of data that is generated to a jasper report inside a subreport that's larger than one page.
When I print it an unwanted page break happens. One element is sometimes printed on the next page when it doesn't fit on the same page.
what I want to happen:
what happens instead:
here's my code:
<group name="ExampleGroup">
<groupExpression><![CDATA[null]]></groupExpression>
<groupHeader>
<band height="17" splitType="Stretch">
<subreport isUsingCache="true">
<reportElement key="subreport-1" positionType="Float" x="0" y="0" width="594" height="16" uuid="some uuid"/>
<parametersMapExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}]]></parametersMapExpression>
<dataSourceExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get("DataSource")]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get("Data")]]></subreportExpression>
</subreport>
</band>
</groupHeader>
<groupFooter>
<band splitType="Stretch"/>
</groupFooter>
</group>
I already tried to solve the problem by adding parameters, e.g. splitType="Prevent" or keepTogether="true" but both caused an empty page to happen. The parameters I found are only useful when the band should be printed on the same page. But in my case the generated reportElements shouldn't be splitted up. It's not about the group or the band! Because its content is anyway larger than one page. I didn't found anything about that topic.
Probably it would be helpful adding an expression like Group Expression? But I don't know what to add here to say that the row should be printed on the next page when there's not enough space left.
How could I solve that? I'm thankful for any suggestion.
I solved it by adding splitType="Prevent" to the band inside the detail that is called in the subreport.

Displaying an ArrayList parameter with a certain format in JasperSoft Studio report

I'm new to Jaspersoft Studio, so I'd like to know if it's possible to do the following:
The problem
For my report in Jaspersoft Studio, I'm passing in parameters from a java class, and one of the parameters is an ArrayList that contains information such as this:
ArrayList<String> benefits = new ArrayList<String>();
benefits.add("benefit_1");
benefits.add("benefit_2");
benefits.add("benefit_3");
benefits.add("benefit_4");
In my report, I need to display the information like this:
- Benefit: benefit_1
- Benefit: benefit_2
- Benefit: benefit_3
- Benefit: benefit_4
This ArrayList has a variable amount of items, so sometimes there are 4, sometimes only 2, etc.
How can I iterate through this list in the report and output it in this format?
What I've tried
From reading other stackoverflow questions, I've tried adding a subreport with the ArrayList as the data source:
<subreport>
<reportElement ... />
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{benefits})]]></dataSourceExpression>
<subreportExpression><![CDATA["benefits.jasper"]]></subreportExpression>
</subreport>
But in the subreport, how would I display the ArrayList elements?
Or is it possible to do what I'm trying to do without the subreport?
Well, I couldn't figure out how to get it to work with the ArrayList I mentioned in my question. I ended up having to change it from an ArrayList of Strings to an ArrayList of HashMaps:
ArrayList<HashMap> benefits = new ArrayList<HashMap>();
// quick and easy, though not optimal, way of adding HashMaps for testing
benefits.add(new HashMap<String, String>(){{put("benefit","benefit_1");}});
benefits.add(new HashMap<String, String>(){{put("benefit","benefit_2");}});
benefits.add(new HashMap<String, String>(){{put("benefit","benefit_3");}});
benefits.add(new HashMap<String, String>(){{put("benefit","benefit_4");}});
Then I updated the code in my main report like this:
<subreport>
<reportElement ... />
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRMapCollectionDataSource($P{benefits})]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{TEMPLATE_DIR}+"benefits.jasper"]]></subreportExpression>
</subreport>
Basically, instead of using JRBeanCollectionDataSource I had to use JRMapCollectionDataSource.
Finally I created the subreport named "benefits", using only the detail band like this:
<detail>
<band height="14" splitType="Stretch">
<textField>
<reportElement ... />
<textElement>...</textElement>
<textFieldExpression><![CDATA["- Benefit: "+$F{benefit}]]></textFieldExpression>
</textField>
</band>
</detail>
The $F{benefit} uses the key from the HashMap inside the ArrayList to get the correct value. That's why I couldn't use a simple ArrayList of Strings.

Show filter parameter in Jasper Report?

I have a jasper report with parameters(names and date) and want to the following on my report.
Filter by : Name - Stevie
Date - 20/4/1909
How do I NOT show if the user never filters by Name but date? Im pretty new to Jasper report and hope someone can enlighten me. Thank you.
Try this for all text field and static text. You need to add xml for printWhenExpression value and put there your value, on base of that you can show hide your text field.
<textField isStretchWithOverflow="true">
<reportElement x="210" y="3" width="160" height="15" uuid="8e21ca6a-7eb9-4deb-8b36-9df9db27314c">
<printWhenExpression><![CDATA[($F{your condition will be here})]]></printWhenExpression>
</reportElement>
<textElement textAlignment="Right">
</textElement>
<textFieldExpression><![CDATA[$F{your text field value}]]></textFieldExpression>
</textField>