jasper report table show previous page total - jasper-reports

I am using Jaspersoft® Studio 6.8.0.
I want to have a table which can show previous page total, take following table for example, assume this
table has 3 pages:
grade
10
20
sub total 30
page 1
grade
previous page total 30
40
50
sub total 90
page 2
grade
previous page total 90
60
70
sub total 130
page 3
that is show previous page total from 2nd page to last page.
How to achieve that? thanks!

One way to do it is to create a variable that holds a mutable value set as a side effect by an expression of the text that displays the total on the previous page.
E.g. something like this:
<variable name="TotalVariable" class="java.lang.Integer" calculation="Sum" resetType="Page">
<variableExpression>$F{Column}</variableExpression>
</variable>
<variable name="PreviousTotalHolder" class="java.util.concurrent.atomic.AtomicInteger" calculation="System">
<initialValueExpression>new java.util.concurrent.atomic.AtomicInteger()</initialValueExpression>
</variable>
...display the previous total in the new page
<textField>
<reportElement .../>
<textFieldExpression>"Previous total " + $V{PreviousTotalHolder}.get()</textFieldExpression>
</textField>
...use a dummy property in the page footer to set the total into the holder object
<textField>
<reportElement x="0" y="0" width="90" height="15" uuid="a1ab288e-ae4b-4f12-83a5-e30486bb30d5">
<propertyExpression name="foo">Integer.toString($V{PreviousTotalHolder}.getAndSet($V{TotalVariable}))</propertyExpression>
</reportElement>
<textFieldExpression>"Total " + $V{TotalVariable}</textFieldExpression>
</textField>
There might be other ways to do it depending on the exact design of you report (for instance depending on whether you have a table component or a tabular band report).

Related

How to perform subtraction between Text Field and Variable

I am very new with ireport-5.6.0.
I have one text field(Sanctioned_intake) and one i declare variable(ROPORT_COUNT).Sanctioned_intake is nothing but total number of Student per Department and REPORT_COUNT is return total no of rows which is enter into the report
For Example:
Sanctioned Intake:140 (Total Student per Department)
Actual Admitted: 10 (Actual Admission Taking)
So Difference Should Be:
Vacancy : 130(Remaining Vacancy )
now my question is how to make difference between this two
I declare One Variable
and set the following properties
variable class=java.math.BigDecimal
Calculation Sum
Reset Type Report
Variable Expression: $F{sanctioned_intake}.substract($V{REPORT_COUNT})
But i got this error
Error filling print... Error evaluating expression :      Source text : $F{sanctioned_intake}.substract$V{REPORT_COUNT}
net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression :      
Source text : $F{sanctioned_intake}.substract$V{REPORT_COUNT} 
    at net.sf.jasperreports.engine.fill.JREvaluator.evaluateEstimated(JREvaluator.java:327) 
Caused by: groovy.lang.MissingMethodException: 
No signature of method: java.lang.String.substract() is applicable for argument types: (java.lang.Integer) values: [1]
Possible solutions: substring(int), substring(int, int) 
Data Type of $V{REPORT_COUNT} is integer.
Check data types of each field and variable.
Or if datatype of $F{sanctioned_intake} == BigDecimal then change variable expression to below
$F{sanctioned_intake}.substract(new BigDecimal($V{REPORT_COUNT}))
The error is related to that $F{sanctioned_intake} is declared as java.lang.String.
<field name="sanctioned_intake" class="java.lang.String"/>
However I do not think you will achieve your excepted result changing it to java.math.BigDecimal since jasper report has something called EvalutationTime, the $V{REPORT_COUNT} will start with 0 and reach the total report count only when all records have been displayed.
To the display the difference of 2 fields, declare them as Integer (if you can not, you need to parse them before calculating difference) and then use a text field.
example consider that $F's are java.lang.Integer
<textField>
<reportElement x="163" y="16" width="100" height="20" uuid="4196bd23-306b-44f6-8e3e-4d637facacf6"/>
<textFieldExpression><![CDATA[$F{sanctioned_intake}.intValue()-$F{actual_admitted.intValue()}]]></textFieldExpression>
</textField>
If one needs to be calculated use a variable, calculating (count) and resetting it as needs and then set correct evaluation time on your textField (so that the variables have time to be calculated)
example
<textField evaluationTime="Report">
<reportElement x="163" y="16" width="100" height="20" uuid="4196bd23-306b-44f6-8e3e-4d637facacf6"/>
<textFieldExpression><![CDATA[$F{sanctioned_intake}.intValue()-$V{actual_admitted}.intValue()]]></textFieldExpression>
</textField>
Note: you are using language="groovy" maybe you like to use language="java" on your jasperReport tag.

In JasperStudio, I need to display the text on (n-1)th page alone

In JasperStudio, I need to display the text only on (n-1)th page. unfortunately I am unable to do that.
I have tried doing it with variables below
<variable name="nthpage" class="java.lang.Integer" resetType="None">
<variableExpression><![CDATA[$V{PAGE_NUMBER}]]></variableExpression>
</variable>
and
<variable name="n-1thpage" class="java.lang.Integer" resetType="None">
<variableExpression><![CDATA[($V{PAGE_NUMBER}-1)]]></variableExpression>
</variable>
and for the report text field expression used as
<textField evaluationTime="Report">
<reportElement x="383" y="124" width="136" height="16" uuid="3193a49a-7354-44c2-a5e7-62336419a190"/>
<textFieldExpression><![CDATA[$V{n-1thpage}==($V{nthpage})?"Hi":"Hello"]]></textFieldExpression>
</textField>
I have tried with evaluationTime="Auto". But it's not working for me.
How can I achieve this custom behavior?
You need to use the Print When Expression e.g. to print a report element on the 10th page only fill the Print When Expression with the value $V{PAGE_NUMBER} == 10

How to show number of rows on page and the total numbers of rows in report

In JasperReport's report I have been showing data using table
In column footer I want to show total number of records per page
Page 1 Showing 25 records out of 65
Page 2 Showing 50 records out of 65
Page 3 Showing 15 records out of 65
I am using column count to show number of records per page but for total records in report what should I use
Page 1 Showing 25 records out of 25
Page 2 Showing 50 records out of 50
Page 3 Showing 15 records out of 65
Which variable should I use or any condition to be added?
You can easy solve this task with help of built-in variable $V{REPORT_COUNT} and custom variable.
The working sample
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="no_of_rows_on_page" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="da1c0873-1b22-4592-93a1-c9ffbdcec490">
<queryString>
<![CDATA[SELECT name FROM PRODUCT]]>
</queryString>
<field name="name" class="java.lang.String"/>
<variable name="rowsOnPage" class="java.lang.Integer" resetType="Page">
<variableExpression><![CDATA[$V{rowsOnPage} + 1]]></variableExpression>
<initialValueExpression><![CDATA[0]]></initialValueExpression>
</variable>
<detail>
<band height="20" splitType="Stretch">
<textField>
<reportElement uuid="dc686db4-cb13-46c2-8420-e9ba198116e3" x="0" y="0" width="185" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
</textField>
</band>
</detail>
<pageFooter>
<band height="20">
<textField>
<reportElement uuid="0940bce6-118f-47bc-81f6-ae03ca55ddcb" x="205" y="0" width="112" height="20"/>
<textElement/>
<textFieldExpression><![CDATA["Showing " + $V{rowsOnPage} + " records out of "]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement uuid="b5f1da29-7ac8-40a9-889e-e306a0cd26fe" x="317" y="0" width="60" height="20"/>
<box leftPadding="2"/>
<textElement/>
<textFieldExpression><![CDATA[$V{REPORT_COUNT}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="fb9ca24d-844e-4921-8a79-85c2ec2d2888" x="159" y="0" width="46" height="20"/>
<textElement/>
<textFieldExpression><![CDATA["Page " + $V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>
The result
The output result generated in iReport via preview mode
How it works
I've add 3 textFields on Page Footer band:
1st one is for showing current page number. The expression is: "Page " + $V{PAGE_NUMBER} and the Evaluation Time is Now
2nd one is for showing count of rows on current page. The expression is: `"Showing " + $V{rowsOnPage} + " records out of "' and the Evaluation Time is Now
3rd one is for showing total rows in whole report. The expression is: $V{REPORT_COUNT} and the Evaluation Time is Report.
As you can see I've add custom variable rowsOnPage for counting number of rows on page.
The variable definition:
Expression: $V{rowsOnPage} + 1
Type: Integer
Initial value: 0
Reset type: Page
See details about:
Variables
Built-in variables in JasperReports Ultimate Guide
The variable "$V{REPORT_COUNT}" can solve your problem, use it at the evaluation time "report".
If you are using Ireport designing tool, then u can show total very easily by placing Page X of Y from palette.
Ireport 5.5 has palette under Window menu.

Hide or show Subreport

I have a requirement where i need to show or hide subreport based on user selection.
Say I have a Main report and two sub reports: sub1 and sub2.
User selects to show only sub1. The boolean value will be sent through Java.
I need to show main report with sub1 in it and hide sub2.
I tried <printwhenexpression> but no matter what it shows only main report.
<subreport>
<reportElement uuid="25895ea2-ed3d-49d2-997b-f0e4e6e304a3" mode="Transparent" x="0" y="0" width="555" height="38">
<printWhenExpression><![CDATA[($P{flag}==Boolean.TRUE)]]></printWhenExpression>
</reportElement>
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
<subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "subreport1.jasper"]]></subreportExpression>
</subreport>

How can I pass sub-report value to main-report?

Here's the relation table
StudentName
Course
Marks
Peter
Bio
65
Peter
Chem
70
Peter
Music
80
David
Chem
50
How can I make something like the followings
Peter Total : 215
Subject : Bio - 65
Subject : Chem - 70
Subject : Music - 80
Peter Total : 50
Subject : Chem - 50
I would not use a subreport for this as this can be achieved in a simpler way: You can utilize Report groups and variables to achieve this. Make sure that the data is sorted accordingly to the output.
Preparation
Create a report group based on StudentName. Right Click in iReport in the report inspector on the report and select Add Report group. Follow the wizard, give it a name (e.g. Student), select field StudentName as group expression, add header but no footer.
Create a variable that holds the total for a student. Right Click in iReport in the report inspector on Variables and select Add Variable. In the properties panel configure as follows: Name: totalMarkByStudent, Variable Class: java.lang.Long, Calculation: Sum, Reset Type: Group, Reset Group: Student, Variable Expression: $F{Marks}. Leave the rest to its default values.
Report Design
Drag and drop the Field StudentName from the report inspector into the report designer into the Student group header band. There will be a popup asking what kind of value shall be displayed, select The field value and click Ok.
Drag and drop the Variable totalMarksByStudent from the report inspector into the report designer into the Student group header band. Click on the text field and modify following settings in the properties panel:
Width: 200 (to allow more space)
Text field expression: "Total : " + $V{totalMarkByStudent}
Expression Class: java.lang.String
Evaluation Time: Group (meaning that the value gets evaluated once the processing of the group is finished)
Evaluation Group: Student
Drag and drop the fields Course and Marks from the report inspector into the detail band in the report designer. Right click on the course field and select Edit Expression. CHange the expression to "Subject : " + $F{Course} and click on Apply.
With this configuration you achieve a report output as in the image below.
For further reference here the complete JRXML using report group and variable:
<?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="report3" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="0dfbb9b2-a9ce-4447-beee-37d653140dd1">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<queryString>
<![CDATA[select * from (
Select 'Peter' as StudentName, 'Bio' as Course, 65 as Marks
union select 'Peter', 'Chem', 70
union select 'Peter', 'Music', 80
union select 'David', 'Chem', 50
) tbl
order by StudentName, Course]]>
</queryString>
<field name="StudentName" class="java.lang.String"/>
<field name="Course" class="java.lang.String"/>
<field name="Marks" class="java.lang.Long"/>
<variable name="totalMarkByStudent" class="java.lang.Long" resetType="Group" resetGroup="Student" calculation="Sum">
<variableExpression><![CDATA[$F{Marks}]]></variableExpression>
</variable>
<group name="Student">
<groupExpression><![CDATA[$F{StudentName}]]></groupExpression>
<groupHeader>
<band height="50">
<textField>
<reportElement uuid="ea996b6c-d41d-47bb-bef1-5df580b5c161" x="0" y="30" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{StudentName}]]></textFieldExpression>
</textField>
<textField evaluationTime="Group" evaluationGroup="Student">
<reportElement uuid="8ddc9b5b-9c57-4fce-8ed0-587c6b54143c" x="180" y="30" width="200" height="20"/>
<textElement/>
<textFieldExpression><![CDATA["Total : " + $V{totalMarkByStudent}]]></textFieldExpression>
</textField>
</band>
</groupHeader>
</group>
<detail>
<band height="20">
<textField>
<reportElement uuid="f67b4e51-4da6-4758-b3d3-bd75de70c0f7" x="0" y="0" width="180" height="20"/>
<textElement/>
<textFieldExpression><![CDATA["Subject : " + $F{Course}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="ea82c278-d2f3-4467-bf5d-8dab9ff99ae3" x="180" y="0" width="277" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{Marks}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
If you use a subreport instead
I assume that the subreport is paraemterized with the student id shows the data for a given student. The main report shows the field StudentName and the subreport in the detail panel.
Create a variable total in the subreport that calculates the total for the student.
Create a variable totalByStudent in the main report with calculation type set to System.
Click on the subreport and in the properties panel click on Return values. Click Add and select: Subreport variable: total, Local Destination Variable: totalByStudent, rest leave to default. Click on Ok.
Drag and drop the variable totalByStudent into the detail band. Select it and in the Properties panel set Evaluation time to Band. The output will be the same as shown above.
I recommend to use the approach with report group and variable as it reduces the complexity of the report, as well as performance for this way would be better.