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

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

Related

iReport variable expression returns null

Here's the simple code in XML view of print form:
<variable name="TITLE" class="java.lang.String">
<variableExpression><![CDATA[$F{APP_NUMBER}.replaceAll( "app_", "" )]]></variableExpression>
</variable>
If I use this variable in form, it returns null (while using "$V{TITLE}"). But if I remove replaceAll method, it works and returns correct value.
What is wrong with expression? Should I use something instead of "<variableExpression>"?
If you are printing this variable in Title band change its evaluation time to "Report"
<title>
<band height="79" splitType="Stretch">
**<textField evaluationTime="Report">**
<reportElement x="143" y="43" width="100" height="30" uuid="4fc0ce80-ced5-448e-bdd1-1571b3bc788f"/>
<textFieldExpression><![CDATA[$V{TITLE}]]></textFieldExpression>
</textField>
</band>
</title>

jasper report table show previous page total

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).

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.

How to create a single pdf containing multiple invoices

I feed an xml file to JasperReports in order to generate a single invoice. This works fine.
However, I would also like to generate multiple invoices (i.e. all invoices for a given user) from a single xml file. The output should be just a single pdf file.
The XML file looks like this
<orders>
<order>
...
</order>
<order>
...
</order>
<order>
...
</order>
</orders>
Is this possible with JasperReports by just editing the jrxml file? I know that I could generate a pdf for each invoice by calling JasperReports in a loop. But I'd like to avoid this since it would require modifing a lot of code.
Update
I use the Jasper-Rails plugin for RoR to generate the reports. https://github.com/fortesinformatica/jasper-rails/blob/master/lib/jasper-rails/jasper_reports_renderer.rb
An xml for a single invoice is simply <order> ... </order>
The jrxml (note: xPath has already been changed to reflect mkl's approach) http://pastebin.com/R0vnrQgU
It is possible to generate a single PDF with multiple invoices if it before was possible to generate a PDF for a single invoice.
It is not clear how many changes to the JRXML are required. Unfortunately the OP did not provide a JRXML. To illustrate a simple case:
If the order merely contains some static amount of data and the JRXML, therefore, only essentially works on one data set, there is hardly anything to change. e.g.:
Let's assume you have original XMLs similar to this sample:
<order>
<name>Mr. Smith</name>
<quantity>2</quantity>
<item>bike</item>
<price>200</price>
</order>
and an original JRXML similar to this sample:
<queryString language="xPath">
<![CDATA[/order]]>
</queryString>
<field name="name" class="java.lang.String">
<fieldDescription><![CDATA[name]]></fieldDescription>
</field>
<field name="quantity" class="java.lang.String">
<fieldDescription><![CDATA[quantity]]></fieldDescription>
</field>
<field name="item" class="java.lang.String">
<fieldDescription><![CDATA[item]]></fieldDescription>
</field>
<field name="price" class="java.lang.String">
<fieldDescription><![CDATA[price]]></fieldDescription>
</field>
<variable name="aggregated" class="java.lang.Number">
<variableExpression><![CDATA[java.lang.Integer.parseInt($F{quantity}) * java.lang.Float.parseFloat($F{price})]]></variableExpression>
</variable>
<detail>
<band height="125" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="535" height="20"/>
<textElement/>
<textFieldExpression><![CDATA["Dear " + $F{name} + ","]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="40" width="100" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$F{quantity}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="40" width="235" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{item}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="335" y="40" width="100" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="75" width="535" height="35"/>
<textElement/>
<textFieldExpression><![CDATA["Please pay " + $V{aggregated} + " soon."]]></textFieldExpression>
</textField>
<textField>
<reportElement x="435" y="40" width="100" height="20" backcolor="#CCCCCC"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$V{aggregated}]]></textFieldExpression>
</textField>
</band>
</detail>
Now for multi-invoice XMLs like this sample:
<orders>
<order>
<name>Mr. Smith</name>
<quantity>2</quantity>
<item>bike</item>
<price>200</price>
</order>
<order>
<name>Mr. Fisher</name>
<quantity>3</quantity>
<item>box</item>
<price>10</price>
</order>
</orders>
all you have to do in the JRXML is to change the xPath expression to match all order elements and add a page break between data sets:
...
<queryString language="xPath">
<![CDATA[//order]]>
</queryString>
...
<detail>
<band height="125" splitType="Stretch">
...
<break>
<reportElement x="0" y="124" width="535" height="1"/>
</break>
</band>
</detail>
Even if the order contains more dynamic data, e.g. a variable number of items, it might be just as easy as long as the order element defines the main data set (the variable number of items might be handled by some table element working on a subdataset).
Update
After the OP provided his JRXML file, it turns out that it essentially is of the simple type indicated above. A small correction is required, though:
The OP's JRXML uses only two sections, Title and Page Footer. The latter indeed is used for page footer material but the former is not used for a title but instead for the actual invoice body, i.e. for material which shall be printed not once (as a title) but as many times as there are data sets! To make this ready for multi-invoice outputs, therefore, the title band first has to be moved to become a detail band:
...
</background>
<title>
<band height="616" splitType="Stretch">
...
</band>
</title>
<pageFooter>
...
becomes
...
</background>
<detail>
<band height="616" splitType="Stretch">
...
</band>
</detail>
<pageFooter>
...
And due to the sheer size of this band, this already suffices to make the JRXML ready for multi-order inputs: A page break occurs automatically before the next detail section with information for the next data set because not more than one of these bands fits on a page and the band splitType is "Stretch".
The output into a single pdf isn't the point.
The key is how to use page breaks for each invoice and the use of the headers/bands, I think.

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.