Jasper Report Tutorial 1
Jasper Report Tutorial 1
Jasper Report Tutorial 1
es
Jasper Report – Tutorial (English Version) - 1 -
1
INDEX
47917159.doc
Jasper Report – Tutorial (English Version) - 2 -
2
47917159.doc
Jasper Report – Tutorial (English Version) - 3 -
3
JasperReports is a powerful open source reporting tool that has the ability to deliver rich content onto
the screen, to the printer or into PDF, HTML, XLS, CSV and XML files. It is entirely written in Java and
can be used in a variety of Java enabled applications to generate dynamic content.
Its main purpose is to help creating page oriented, ready to print documents in a simple and flexible
manner.
JasperReports organizes data retrieved from a relational database through JDBC according to the
report design defined in an XML file. In order to fill a report with data, the report design must be
compiled first.
The compilation of the XML file representing the report design is performed by the compileReport()
method exposed by the dori.jasper.engine.JasperManager class.
Through compilation, the report design is loaded into a report design object that is then serialized and
stored on disk (dori.jasper.engine.JasperReport). This serialized object is then used when
the application wants to fill the specified report design with data. In fact, the compilation of a report
design implies the compilation of all Java expressions defined in the XML file representing the report
design. Various verifications are made at compilation time, to check the report design consistency. The
result is a ready to fill report design that will be then used to generate documents on different sets of
data.
In order to fill a report design, one can use the fillReportXXX() methods exposed by the
dori.jasper.engine.JasperManager class. Those methods receive as a parameter the report
design object, or a file representing the specified report design object, in a serialized form, and also a
JDBC connection to the database from where to retrieve the data to fill the report.
The result is an object that represents the ready to print document
(dori.jasper.engine.JasperPrint) and can be stored onto the disk, in a serialized form, for
later use, or can be delivered to the printer, to the screen or can be transformed into a PDF, HTML,
XLS, CSV or XML document.
As mentioned, a report design represents a template that will be used by the JasperReports engine to
deliver dynamic content to the printer, to the screen or to the Web. Data stored in the database is
organized according to the report design to obtain ready to print, page oriented documents.
The report designs are defined in XML files and must have a special structure. This structure is
declared in a DTD file supplied with the JasperReports engine. The XML files are then compiled, in
order to use them in report filling operations.
To create a simple report design, we have to edit an XML file with the following structure:
<?xml version="1.0"?>
<!DOCTYPE jasperReport
PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="name_of_the_report" ... >
...
</jasperReport>
47917159.doc
Jasper Report – Tutorial (English Version) - 4 -
4
1.3 Parameters
Parameters are object references that are passed-in to the report filling operations.
They are very useful for passing to the report engine data that it can not normally find in its data
source.
For example, we could pass to the report engine the name of the user that has launched the report
filling operation, if we want it to appear on the report, or we could dynamically change the title of our
report.
An import aspect is the use of report parameters in the query string of the report, in order to be able to
further customize the data set retrieved from the database. Those parameters could act like dynamic
filters in the query that supplies data for the report.
Declaring a parameter in a report design is very simple and it requires specifying only its name and its
class:
<parameter name="ReportTitle" class="java.lang.String"/>
<parameter name="MaxOrderID" class="java.lang.Integer"/>
<parameter name="SummaryImage" class="java.awt.Image"/>
There are two possible ways to use parameters in the query:
1. The parameters are used like normal java.sql.PreparedStatement parameters using the
following syntax:
2. Sometimes is useful to use parameters to dynamically modify portions of the SQL query or to
pass the entire SQL query as a parameter to the report filling routines. In such a case, the
syntax differs a little, like in the following example:
SELECT * FROM Orders ORDER BY $P!{OrderByClause}
There are also the following built-in system parameters, ready to use in expressions:
REPORT_PARAMETERS_MAP
REPORT_CONNECTION
REPORT_DATA_SOURCE
REPORT_SCRIPTLET
JasperReports support various types of data sources using a special interface called JRDataSource.
There is a default implementation of this interface (JRResultSetDataSource class) that wraps a
ResultSet object. It allows the use of any RDMS database through JDBC.
When using a JDBC data source, one could pass a Connection object to the report filling operations
and specify the query in the report definition itself (see the <queryString> element in the XML file) or
could create a new instance of the JRResultSetDataSource by supplying the ResultSet object
directly.
With other types of data sources, things should not be different and all we have to do is to implement
the JRDataSource interface.
47917159.doc
Jasper Report – Tutorial (English Version) - 5 -
5
1.5 Fields
Report fields represent the only way to map data from the data source into the report generating
routines. When the data source of the report is a ResultSet, all fields must map to corresponding
columns in the ResultSet object. That is, they must have the same name as the columns they map
and a compatible type.
For example:
If we want to generate a report using data retrieved from the table Employees, which has the following
structure:
Column Name Datatype Length
--------------------------------------
EmployeeID int 4
LastName varchar 20
FirstName varchar 10
HireDate datetime 8
If we declare a field that does not have a corresponding column in the ResultSet, an exception will
be thrown at runtime. Columns present in the ResultSet object that do not have corresponding fields
in the report design do not affect the report filling operations, but they also wont be accessible.
1.6 Expressions
Expressions are a powerful feature of JasperReports. They can be used for declaring report variables
that perform various calculations, for data grouping on the report, to specify report text fields content or
to further customize the appearance of objects on the report.
Basically, all report expressions are Java expressions that can reference report fields and report
variables.
In an XML report design there are several elements that define expressions:
<variableExpression>, <initialValueExpression>, <groupExpression>,
<printWhenExpression>, <imageExpression> and <textFieldExpression>.
In order to use a report field reference in an expression, the name of the field must be put between $F{
and } character sequences.
For example, if we want to display in a text field, on the report, the concatenated values of two fields,
we can define an expression like this one:
<textFieldExpression>
$F{FirstName} + " " + $F{LastName}
</textFieldExpression>
47917159.doc
Jasper Report – Tutorial (English Version) - 6 -
6
<textFieldExpression>
$F{FirstName} + " " + $F{LastName} + " was hired on " +
(new SimpleDateFormat("MM/dd/yyyy")).format($F{HireDate}) + "."
</textFieldExpression>
To reference a variable in an expression, we must put the name of the variable between $V{ and }
like in the example below:
<textFieldExpression>
"Total quantity : " + $V{QuantitySum} + " kg."
</textFieldExpression>
There is an equivalent syntax for using parameters in expressions. The name of the parameter should
be put between $P{ and } like in the following example:
<textFieldExpression>
"Max Order ID is : " + $P{MaxOrderID}
</textFieldExpression>
1.7 Variables
A Report variable is a special objects build on top of an expression. Variables can be used to simplify
the report design by declaring only once an expression that is heavily used throughout the report
design or to perform various calculations on the corresponding expressions.
In its expression, a variable can reference other report variables, but only if those referenced variables
were previously defined in the report design. So the order in which the variables are declared in a
report design is important.
As mentioned, variables can perform built-in types of calculations on their corresponding expression
values like : count, sum, average, lowest, highest, variance, etc.
A variable that performs the sum of the Quantity field should be declared like this:
<variable name="QuantitySum"
class="java.lang.Double" calculation="Sum">
<variableExpression>$F{Quantity}</variableExpression>
</variable>
For variables that perform calculation we can specify the level at which they are reinitialized. The
default level is Report and it means that the variable is initialized only once at the beginning of the
report and that it performs the specified calculation until the end of the report is reached. But we can
choose a lower level of reset for our variables in order to perform calculation at page, column or group
level. For example, if we want to calculate the total quantity on each page, we should declare our
variable like this:
<variable name="QuantitySum" class="java.lang.Double"
resetType="Page" calculation="Sum">
<variableExpression>$F{Quantity}</variableExpression>
<initialValueExpression>new Double(0) </initialValueExpression>
</variable>
47917159.doc
Jasper Report – Tutorial (English Version) - 7 -
7
Our variable will be initialized with zero at the beginning of each new page.
There are also the following built-in system variables, ready to use in expressions:
PAGE_NUMBER
COLUMN_NUMBER
REPORT_COUNT
PAGE_COUNT
COLUMN_COUNT
GroupName_COUNT
When building a report design we need to define the content and the layout of its sections. The entire
structure of the report design is based on the following sections: <title>, <pageHeader>,
<columnHeader>, <groupHeader>, <detail>, <groupFooter>, <columnFoter>,
<pageFooter>, <summary>.
Sections are portions of the report that have a specified height and width and can contain report
objects like lines, rectangles, images or text fields.
When declaring the content and layout of a report section in an XML report design we use the generic
element <band>.
This is how a page header declaration should look. It contains only a line object and a static text:
<pageHeader>
<band height="30">
<rectangle>
<reportElement x="0" y="0" width="555" height="25"/>
<graphicElement/>
</rectangle>
<staticText>
<reportElement x="0" y="0" width="555" height="25"/>
<textElement textAlignment="Center">
<font fontName="Helvetica" size="18"/>
</textElement>
<text>Northwind Order List</text>
</staticText>
</band>
</pageHeader>
47917159.doc
Jasper Report – Tutorial (English Version) - 8 -
8
1.9 Groups
Groups represent a flexible way to organize data on a report. When filling a report, the JasperReports
engine test all the defined group expressions to see whether a group rupture has occurred and if so it
introduces the corresponding <groupFooter> and <groupHeader> sections on the report.
We can have as many groups as we want on a report. The order of groups declared in a report design
is important because groups contain each other. One group contains the following group and so on.
And when a larger group encounters a rupture, all subsequent groups are reinitialized.
When declaring a report group, along with its corresponding data grouping expression, we have to
declare the two sections: the group's header section and the group's footer section.
See the sample report for an example on how to define groups.
1.11 Scriptlets
All the data displayed on a report comes from the report parameters and from the report fields. This
data can be processed using the report variables and their expressions.
There are specific moments in time when variable processing occurs. Some variables are initialized
according to their reset type when the report starts, or when a page or column break is encountered, or
when a group changes. Furthermore, variables are evaluated every time new data is fetched from the
data source (for every row).
But only simple variable expressions cannot always implement complex functionality. This is where
scriptlets intervene.
Scriptlets are sequences of Java code that are executed every time a report event occurs. Through
scriptlets, users now have the possibility to affect the values stored by the report variables.
Since scriptlets work mainly with report variables, is important to have full control over the exact
moment the scriptlet is executed. JasperReports allows the execution of custom Java code BEFORE
or AFTER it initializes the report variables according to their reset type: Report, Page, Column or
Group.
47917159.doc
Jasper Report – Tutorial (English Version) - 9 -
9
In order to make use of this functionality, users only have to create a scriptlet class by extending
dori.jasper.engine.JRAbstractScriptlet class or
dori.jasper.engine.JRDefaultScriptlet class. The name of this custom scriptlet class has to
be specified in the scriptletClass attribute of the <jasperReport> element.
When creating a JasperReports scriptlet class, there are several methods that developers should
implement or override, like: beforeReportInit(), afterReportInit(),
beforePageInit(), afterPageInit(), beforeGroupInit(), afterGroupInit(), etc.
Those methods will be called by the report engine at the appropriate time, when filling the report.
There is a default report parameter called REPORT_SCRIPTLET which represent a reference to the
scriptlet object instantiated by the report engine when filling the report. It can be used in expressions
throughout the report, to call custom methods on the scriptlet object, making the whole mechanism
even more flexible.
See the scriptlet sample for more details.
1.12 Subreports
Subreports are an import feature for a report-generating tool. They allow the creation of more complex
reports and simplify the design work.
The subreports are very useful when creating master-detail type of reports.
47917159.doc
Jasper Report – Tutorial (English Version) - 10 -
10
The Main classes to use when working with JasperReports are the following:
A report design is represented by an XML file that has the structure defined in the jasperreport.dtd file.
In order to generate reports according to such a report design, it needs to be compiled.
Report design compilation can be done using the compileReportXXX() methods exposed by
dori.jasper.engine.JasperCompileManager class.
When compiling a report design, the engine first performs a validation to ensure that the template is
consistent and then transforms all the report expressions, so that they are stored in a ready-to-evaluate
form, inside the resulting .jasper file.
This transformation implies either the on-the-fly compilation of a Java class file that will be associated
with the report template, or the generation of a BeanShell script to use when evaluating report
expressions during the report filling process.
To make report design compilation process as flexible as possible, a special interface called
dori.jasper.engine.design.JRCompiler was introduced.
As seen above, there are two main types of classes implementing this interface and thus performing
report compilation:
1. Java class generating report compilers. These report compilers generate and compile a Java
class containing the report expressions evaluating methods;
2. The BeanShell report compiler that generates a script for runtime report expressions
evaluation, without requiring bytecode Java compilation.
System properties to customize report compilation:
2.2.1 jasper.reports.compiler.class
By default, when compiling report designs, the library tries to identify the Java generating class type of
a report compiler that is compatible with the Java compiler available on the running platform in this
order: JDK 1.3 compatible compiler, JDK 1.2 compatible compiler and the command-line javac.exe
compiler.
47917159.doc
Jasper Report – Tutorial (English Version) - 11 -
11
To override this default behavior, you can specify the name of a class that implements the
dori.jasper.engine.design.JRCompiler interface to be used to compile the report design by
supplying it to the jasper.reports.compiler.class system property.
The library comes with 5 built-in implementations of this interface:
dori.jasper.engine.design.JRBshCompiler
dori.jasper.engine.design.JRJavacCompiler
dori.jasper.engine.design.JRJdk12Compiler
dori.jasper.engine.design.JRJdk13Compiler
dori.jasper.engine.design.JRJikesCompiler
Note that the classes implementing the JRCompiler interface can also be used directly in the
programs without the need to call them through the JasperCompilerManager class.
2.2.2 jasper.reports.compilation.xml.validation
The XML validation, which is ON by default, can be turned off by setting the system property called
jasper.reports.compilation.xml.validation to false.
When working with a Java class generating type of a report compiler, further customizations can be
made using the following system properties, which only apply to them:
2.2.3 jasper.reports.compile.class.path
By default, JasperReports uses the current JVM classpath to compile the report class
(java.class.path system property). To customize this report compilation process, JasperReports
lets you override the default behavior by supplying a value to the
jasper.reports.compile.class.path system property, which will be used as classpath for the
report class compilation.
2.2.4 jasper.reports.compile.temp
The temporary location for the files generated on-the-fly is by default the current working directory. It
can be changed by supplying a value to the jasper.reports.compile.temp system property.
2.2.5 jasper.reports.compile.keep.java.file
Sometimes, for debugging purposes, it is useful to have the generated .java file in order to fix the
compilation problems related to report expressions. By default, the engine deletes this file after report
compilation, along with its corresponding .class file. To keep it however, you can set the system
property jasper.reports.compile.keep.java.file to true.
47917159.doc
Jasper Report – Tutorial (English Version) - 12 -
12
Since the report design compilation process is more like a design-time job than a runtime
one, an Ant task was provided with the library in order to simplify development.
This Ant task is implemented by the dori.jasper.ant.JRAntCompileTask and is very
similar to the <javac> Ant built-in task, as far as syntax and behavior are concerned.
The report design compilation task can be declared like this, in a project's build.xml file:
In the example above, the lib should contain the jasperreports.jar file along with its
required libraries.
This user-defined Ant task can be then used to compile multiple XML report design files in a
single operation, by specifying the root directory that contains those files or by selecting them
using file patterns.
Attributes of the report design compilation task:
Location of the XML report design files to compile. Required unless nested
srcdir <src> elements are present.
Location to store the compiled report design files (the same as the source
destdir directory by default).
The report design compilation task supports nested <src> and <classpath> elements, just
like the Ant <javac> built-in task.
To see this in action, check the "antcompile" sample provided with the project source files.
47917159.doc
Jasper Report – Tutorial (English Version) - 13 -
13
A compiled report design can be used to generate reports by calling the fillReportXXX() methods
of the dori.jasper.engine.JasperFillManager class.
} catch (Exception e) {
Debug.error(this, e);
return(null);
}
}
47917159.doc
Jasper Report – Tutorial (English Version) - 14 -
14
import dori.jasper.engine.JasperPrint;
import dori.jasper.engine.JRException;
import dori.jasper.view.JRViewer;
import java.awt.BorderLayout;
import javax.swing.JOptionPane;
/**
* Permite la visualización en un panel de un objeto JasperPrint
*/
public class VerInforme
extends javax.swing.JFrame {
/**
* Constructor.
* @param jasperPrint
* €xception JRException
*/
public VerInforme(JasperPrint jasperPrint)
throws JRException {
getRevision();
initComponents();
setTitle("Visualizador de informes.");
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
pnlMain.setLayout(new java.awt.BorderLayout());
47917159.doc
Jasper Report – Tutorial (English Version) - 15 -
15
getContentPane().add(pnlMain, java.awt.BorderLayout.CENTER);
pack();
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setSize(new java.awt.Dimension(800, 600)); //XXX
setLocation(50,50); //XXX
}
/**
* Información de la revisión del fichero fuente
* @return Una cadena con el <i>keyword</i> Id:
*/
public static String getRevision() {
return "$Id: VerInforme.java,v 1.5 2004/06/21 10:27:34 sergio_alonso Exp $";
}
47917159.doc
Jasper Report – Tutorial (English Version) - 16 -
16
exporter.setParameter(
JRPrintServiceExporterParameter.PRINT_REQUEST_ATTRIBUTE_SET,
printRequestAttributeSet);
exporter.setParameter(
JRPrintServiceExporterParameter.PRINT_SERVICE_ATTRIBUTE_SET,
printServiceAttributeSet);
exporter.setParameter(
JRPrintServiceExporterParameter.DISPLAY_PAGE_DIALOG,
Boolean.FALSE);
exporter.setParameter(
JRPrintServiceExporterParameter.DISPLAY_PRINT_DIALOG,
new Boolean(dlgImpresora));
if (servicioImpresora != null) {
exporter.setImpresora(servicioImpresora);
}
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jp);
return(exporter);
}
.......
exporter.exportReport();
After having filled a report, we can also export it in PDF, HTML or XML format using the
exportReportXXX() methods of the dori.jasper.engine.JasperExportManager class.
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jp);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, os);
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "ISO-8859-1");
exporter.exportReport();
47917159.doc
Jasper Report – Tutorial (English Version) - 17 -
17
os.flush();
}
47917159.doc
Jasper Report – Tutorial (English Version) - 18 -
18
Some reports may require that the same kind of data be displayed differently, depending on its
significance.
For example, someone would want to highlight on an orders list, all the orders that have a total value
greater than 100$, like in the following table:
How to do that, since the format of a text field can not change dynamically? The solution is within
reach. We can put in the same place two text fields, one on top of the other, both displaying the same
value, but having different formats: one black and the other bold and red.
In addition, we should make use of the <printWhenExpression> element that is available for every
report element and switch between those two text fields.
The red text field should be displayed only when its value is greater than 100 and the black one in the
rest of the cases.
3.2 “Page i of n”
Quite often we might need to put at the beginning of our reports, values that are calculated only after
the entire document is generated.
The most common situation of this kind would be the display of the total number of pages on the page
footer or header of each page.
How to do that, since the report is filled page by page and the total number of pages is known only
when we reach the end of our document? Well, that's easy.
JasperReports allows us to specify the exact moment at which an expression for a text field is
evaluated. To display the total number of pages, we only need to put on our page footer (or any other
report section) a text field that will use the PAGE_NUMBER report variable in its expression. For this
field we will specify that the evaluation time should be "Report", because only when the end of the
report is reached, this system variable will contain the total number of pages on our report.
The text field declaration in the XML report design file for the total number of pages in a document will
look like this:
<textField evaluationTime="Report">
<reportElement x="280" y="10" width="275" height="20"/>
<textElement textAlignment="Left">
<font fontName="Helvetica" size="14"/>
</textElement>
<textFieldExpression class="java.lang.Integer">
$V{PAGE_NUMBER}
</textFieldExpression>
</textField>
47917159.doc
Jasper Report – Tutorial (English Version) - 19 -
19
If we remove the attribute evaluationTime from the <textField> element, the text field
expression will be evaluated when the section is filled (default behavior) so we will obtain the current
page number on the document.
To display the current page number and the total number of pages simultaneously, like in "Page 3 of
5" phrases, we need two text fields with the same expression (PAGE_NUMBER variable value), but
with different evaluationTime attributes:
Sometimes the content of a particular report band is larger than one page and we have to find a way to
force page breaks at certain points, inside the band structure.
Of course, this issue does not concern all the report bands. I imagine that we shall never have page or
column headers or footers larger than one page ... but who knows?
If the title band or the summary band are larger than one page, you should consider placing their
content into a subreport element and applying the following trick to this particular subreport. This might
even work for the page or column headers, but never for the page or column footers, since the engine
judge them to be of fixed height and do not perform stretch for the elements placed on those sections.
We have eliminated from our discussion some of the report sections and all that remains are the group
headers and footers and the detail band.
The group headers and footers we'll be treated together, so let's start with the detail band.
If we have a detail band that contains so many elements on it that we have to split it on multiple pages,
we have to find a way to introduce page breaks. But there is no such "page break" element available in
JasperReports, so what to do?
The only way to deliberately introduce page breaks in JasperReports is by using the
isStartNewPage attribute of the <group> element. We cannot use this to solve our problem.
Normally, the reporting engine starts a new page or column every time it sees that the band it has to fill
does not fit on the remaining space on the current page. This is why we have that validation performed
when the report design is compiled, so that the bands do not have a height greater than the page
height. Without such a constraint, the reporting engine would get confused and behave uncontrollably.
So, in order to solve our problem, we have to find a way to somehow pass this band height validation
check.
Well, we could do that by splitting the detail band content on multiple bands, each one of them smaller
that one page, so that the report design remains valid.
And what other report bands could we use? Group headers and footers of course.
We could place some of our detail elements on a special group header, some of them will probably
remain on the detail section, and the rest could go on the group footer. The only condition to this is that
the group header and footer should always accompany our detail section, so that all three behave like
a normal large detail band.
47917159.doc
Jasper Report – Tutorial (English Version) - 20 -
20
That's the easiest part, because we can introduce a dummy group that will break with every row in the
data source. Such a group would have an expression like the following:
<groupExpression>$V{REPORT_COUNT}</groupExpression>
If one dummy group is not sufficient for you and you have a giant detail band, you could introduce as
many dummy groups as you want to, all of them with the same dummy expression. Problem solved.
Hey, we forgot about that other situation when one of the group headers or footers is larger than one
page.
No problem. The solution is the same. You just have to introduce a new group, with the same
expression as the one which poses the problem, and to split that group header or footer content
between the two. Those two groups will break together and behave like one, so you can distribute the
elements on their headers and footers as you want to.
The band height validation check could be passed this way.
When generating reports, the JasperReports engine uses the absolute position of each report element
to layout the content of each page. Absolute positioning the report elements allows full control over the
content of the output documents.
The PDF format supports absolute positioning of the text and graphic elements on a document page
and this is why it is widely used on various platforms. You can be sure that once created, a PDF
document will look the same no matter what is the viewer's platform.
The JasperReports proprietary document format (dori.jasper.engine.JasperPrint objects) is
also based on absolute positioning of elements on the page. The position and size of each element are
defined by the x, y, width and height properties.
However, other document formats such as HTML or XLS, do not support absolute positioning of the
text and graphic elements. The content of such documents is arranged in a grid or table structure.
Of course, some may argue that absolute positioning of elements in HTML is possible thanks to CSS,
but you can be sure that the CSS standard functionality is far from being implemented in all browsers
or that the same HTML document won't look the same everywhere.
This is why the JasperReports built-in exporters that produce HTML, XLS or CSV documents use a
special algorithm in order to arrange the elements present on a certain document page in some sort of
a grid.
When the report designs are very complex or agglomerated, passing from absolute positioning to grid
or table layout produces very complex tables with many unused rows and columns, to make it for the
empty space between elements or their special alignment.
There are a few, very simple guidelines that should be followed by those who want to obtain optimized
HTML, XLS or CSV documents when using the built-in JasperReports grid exporters.
47917159.doc
Jasper Report – Tutorial (English Version) - 21 -
21
3.4.1 Minimizing the number of rows and columns in the grid oriented
formats
Minimizing the number of “cuts”. To do that, you have to make sure you align your report elements
as often as you can, both on the horizontal and the vertical axis and that you eliminate the space
between elements.
Inefficient layout
47917159.doc
Jasper Report – Tutorial (English Version) - 22 -
22
JasperReports allows you to use any color for your report elements. However, when exporting to XLS
format, you have to be aware that this type of files supports only a limited set of colors.
If the colors you use in your report designs do not match any of these acceptable colors, the XLS
exporter will use a special algorithm to determine which is the nearest one by comparing the RGB
levels. But the results might not be always what you expect.
Here is the Excel Color Palette containing all the 40 colors that XLS may use. Make sure you use one
of these colors if you want to eventually export your reports to XLS format.
47917159.doc
Jasper Report – Tutorial (English Version) - 23 -
23
47917159.doc
Jasper Report – Tutorial (English Version) - 24 -
24
You can return values from subreports using special parameters as containers. Here’s an example:
Problem: I want to pass to my master report the total number of records that the subreport had.
Solution: In the master report, I define a special container parameter that will hold the values that I
want to return from the subreport.
I pass this container parameter to my subreport, so that it can store the returned values in it.
<subreportParameter name="ReturnedValuesMap">
<subreportParameterExpression>
$P{ReturnedValuesMap}
</subreportParameterExpression>
</subreportParameter>
In the subreport template, I declare the container parameter. Even they both have the same name, the
master report parameter and the subreport parameter are in fact totally different entities.
<parameter name="ReturnedValuesMap" class="java.util.Map"/>
In the subreport, I use the dummy <printWhenExpression> of an invisible line element placed on
the summary section to put in the container parameter the value that I want to return to my master
report:
<line>
<reportElement x="0" y="0" width="0" height="0">
<printWhenExpression>
($P{ReturnedValuesMap}.put(
"MY_RETURNED_VALUE", $V{REPORT_COUNT}) == null
)?Boolean.FALSE:Boolean.FALSE
</printWhenExpression>
</reportElement>
</line>
Remember that the returned value can be placed in the container parameter also using scriptlets. I
chose this trick for simplicity reasons.
Back in the master report, if I want to display the returned value, I just extract it from the container
parameter:
<textField evaluationTime="Group" evaluationGroup="DetailGroup">
<reportElement x="335" y="50" width="175" height="15"/>
47917159.doc
Jasper Report – Tutorial (English Version) - 25 -
25
<textFieldExpression class="java.lang.Integer">
$P{ReturnedValuesMap}.get("MY_RETURNED_VALUE")
</textFieldExpression>
</textField>
You might ask why is it that the text field uses evaluationTime="Group".
This is because one of the problems with the returned values from subreports is that these values are
returned after the content of the band elements has already been evaluated.
If you want to display subreport returned values in the same band as the subreport itself, you'll end up
seeing that they were returned too late for that.
So, in order to be able to display the returned values in the same master report band that contains the
subreport itself, I had to delay the text field evaluation. This was done by introducing a dummy group in
the master report and let my text field be evaluated when this dummy group ends.
This dummy group breaks with every record in the data source and has no header and footer of its
own.
<group name="DetailGroup">
<groupExpression>$V{REPORT_COUNT}</groupExpression>
</group>
This dummy group served my purpose because my subreport and the text field were placed in the
detail section of the master report and it had to break with every detail. If the subreport is placed in a
different report section, the dummy group expression should be adapted to fit the given situation.
The use of a dummy group is not necessary if you do not need to display the returned values in the
same report section that contains the subreport itself.
The title and the summary are special report sections that are not accompanied by the page header
and footer on the pages that they occupy. This is more obvious when the title or the summary
overflows.
Sometimes is useful to have a title section that starts after the page header on the first page or a
summary section that gets accompanied by the page header and footer on all the pages that it
overflows to.
This can be achieved by introducing fake title and summary sections.
A fake title can be the group header section of a report group that breaks only once per report. Such a
dummy group would have an empty group expression. Its header will get printed only once at the
beginning of the report.
The fake summary can be introduced also by using the footer section of such a dummy group wit an
empty group expression.
47917159.doc
Jasper Report – Tutorial (English Version) - 26 -
26
4 FAQs
4.1 System property org.xml.sax.driver not specified
JasperReports uses the SAX 2.0 API to parse the XML files. However, it is not tied to a particular SAX
2.0 implementation, like Xerces for examples, but instead you are able to decide at runtime what XML
parser you are using.
To instantiate the parser class, JasperReports uses the createXMLReader() method of the
org.xml.sax.helpers.XMLReaderFactory class.
In this case, it will be necessary at runtime to set the org.xml.sax.driver Java system property to
the full class name of the SAX driver, as specified in the SAX 2.0 documentation.
You can achieve this in two ways. We shall explain both using the Xerces XML parser, just like we do it
in the provided samples. If you use a different SAX 2.0 XML parser, you have to modify the name of
the parser class accordingly.
The first way you can set a system property is by using the -D switch in the command line when you
launch the Java Virtual Machine:
In all the provided samples we use the ANT build tool to perform different tasks. We supply this system
property to the JVM using the <sysproperty> element of the <java> built-in task:
<sysproperty
key="org.xml.sax.driver"
value="org.apache.xerces.parsers.SAXParser"/>
System.setProperty(
"org.xml.sax.driver",
"org.apache.xerces.parsers.SAXParser"
);
This happens if you directly use the dori.jasper.view.JasperViewer class in your Swing
application.
The viewer application implemented in this class should be considered more like a demo application
that shows how the dori.jasper.view.JRViewer component can be used in Swing applications to
display reports.
Your application unexpectedly terminates when you close the report viewer frame because the
JasperViewer class makes a call to the System.exit(0).
To get around this, use the constructor that allows you to set the "isExitOnClose" to false.
47917159.doc
Jasper Report – Tutorial (English Version) - 27 -
27
But you are encouraged to create your own viewer that uses the more basic visual component
implemented by the dori.jasper.view.JRViewer class. Feel free to copy what code portion you
might want to keep from the supplied JasperViewer class.
4.3 Can not use the && logical operator in report expressions
If you want to create some complex report expressions in which you have to use the Java AND logical
operator, you might be surprised to see an error when compiling you report design. The error message
would say something like this:
"The entity name must immediately follow the '&' in the entity reference."
This is because the '&' character is a special XML character and the XML parser is confused when it
encounters such characters in the body of an XML element.
The solution is to use the XML special syntax that allows you to introduce XML special characters in
the body of an XML element. Put your expression content between the <![CDATA[ and ]]> character
sequences like in the following demo text field expression:
0)?
($F{MyStringField}):("MISSING")
]]>
</textFieldExpression>
]]>
4.4 Java.io.InvalidClassException:…serialVersionUID=xxx
When upgrading to a new version of the library, you need to recompile your XML report design and
regenerate the *.jasper files.
The Jakarta POI library that we use when exporting the report to XLS format does not currently
supports images.
47917159.doc
Jasper Report – Tutorial (English Version) - 28 -
28
5 SCREENSHOTS
47917159.doc
Jasper Report – Tutorial (English Version) - 29 -
29
47917159.doc
Jasper Report – Tutorial (English Version) - 30 -
30
47917159.doc
Jasper Report – Tutorial (English Version) - 31 -
31
5.4 Columns
47917159.doc
Jasper Report – Tutorial (English Version) - 32 -
32
5.5 Groups
47917159.doc
Jasper Report – Tutorial (English Version) - 33 -
33
5.6 Calculations
47917159.doc
Jasper Report – Tutorial (English Version) - 34 -
34
47917159.doc
Jasper Report – Tutorial (English Version) - 35 -
35
5.8 Images
47917159.doc