SELECT * FROM
$P!{MyTable} ORDER BY
$P!{OrderByClause}
]]>
在这个例子中,这个引入了参数值得特殊的语法确定了我们为这些参数所提供的值将会替代查询中的参数引用($P!{}的内容)。这些参数将被传给使用java.sql.PrepqredStatement对象的数据库服务器。
事实上,报表引擎首先处理$P!{}参数引用,通过使用他们的值来获取最重的SQL查询,并且仅当这件事完成之后,引擎才会将剩下的普通的$P{}参数引用传递给usual
IN parameters。--实际上就是嵌套查询啦。
第二种用于SQL查询的参数引用允许你在运行期传递整个SQL查询语句:
$P!{MySQLQuery}
注意:你不能在参数值中再加入参数引用,也就是说,参数引用不能嵌套使用。
更详细的信息可以参看工程所带的例程:jasper,subreport,scriptlet,webapp以及最有学习价值的query
5.5 字段(Field)
报表字段是从数据源到报表设计的数据映射的唯一途径。你可以应用报表字段在report表达式中使用数据源中的数据,或获得所需的输出。一旦定义了报表字段,你需要在报表填充的时候确认你所提供的数据源中提供了所有你声明的fields。
例如,如果你使用JRResultSetDataSource作为数据源,你需要确定在SQL查询结束之后所获得的ResultSet中的column包含你生命的全部fields。相应的列名和字段名必须完全相同,并且其数据类型也必须完全一致。
这是一个字段声明的语法,字段的声明需要对应于数据库表中的某一字段。我们来考虑一个Employee的例子,有如下表结构(structure):
报表字段需要像下面这样定义:
如果你定义的字段不能和ResultSet中的某一列相对应,则在运行期将会抛出异常(如果你用IReport,在编译时也会抛出异常)。然而执行SQL查询之后返回的结果集中包含的列不需要与报表字段一一对应(即列可以多于字段,只是在显示的时候不显示出来罢了)。
字段名(Field Name)
元素的name属性是强制属性(即不能省略),你可以在表达式中通过它来引用该字段。字段名必须是一个单词,且不含有特殊字符,如点和分号。
字段类型(Field Class)
这个属性描述了字段值的类型,缺省的类型是java.lang.String,还有其他可选类型如:
java.lang.Object
java.lang.Boolean
java.lang.Byte
java.util.Date
java.sql.Timestamp
java.lang.Double
java.lang.Float
java.lang.Integer
java.io.InputStream
java.lang.Long
java.lang.Short
java.math.BigDecimal
如果某些数据源含有一些自定义的类型,则该类型所对应的字段应该声明为java.lang.Object。但是与参数定义不同的是,你只能选择上述列表中的类型名。
字段描述(Field Description)
当实现一个自定义数据源的时候跟,这一伴随着某个字段的附加的文本块是很有用的。你可以在字段描述中保存一个key或其他任何信息以便于在运行期从自定义数据源中取回字段值。通过使用可选的 元素,你就可以轻松的越过字段名的约束(field naming conventions),在从数据源取数据的时候,使用字段描述而不是字段名来获取相应数据。
PERSON NAME
5.6 变量(Variables)
报表变量是建立在报表表达式之上的一些特殊对象。他们是用表达式定义的,用来执行某些运算,来简化报表中频繁出现或使用某些项目(如页号,页码,某些列的累加和等等)。下面是它的定义语法:
可以看到,在这个语法中,一个变量可以引用其他变量,当且仅当被引用的变量已经在报表中被定义过。所以,在报表设计中,变量定义的顺序非常重要。
变量名(Variable Name)
与字段名和参数名一样, 元素的name属性是强制属性,报表引擎允许在报表表达式中通过这个这个名字来引用变量。变量名的命名规则与参数和字段的规则相同。
变量类型(Variable Class)
每一个变量都有其类型,缺省为java.lang.String,然而只要你所选择的类型可以在classpath中找到,你就可以在报表编译期和填充期声明任何类型的报表变量。
重置类型(Reset Type)
报表变量的值可以在每一次迭代(iteration)中被改变,但也可以在装填过程中的某一特定的时间(specified moments)通过它的初始的value表达式恢复其初始值。这一行为是由resetType属性控制的,这一属性规定了报表装填过程中当报表变量在何时需要重新进行初始化(或恢复到初始值)。该元素有五种选项值:
n
No Reset:变量将不会使用其initial value expression对自身进行初始化,而将仅报表从变量表达式中所求得的值(resetType=”None”)。
n
Report Level Reset
:变量将在报表填充过程的起始阶段使用其初始化表达式初始化一次(resetType=”Report”)。
n
Page Level Reset
:变量将在每一页的起始时被重新初始化(resetType=”Page”)。
n
Colunm Level Reset
:变量将在每个新列的开始被初始化(resetType=”Column”)
n
Group Level Reset:变量将在每次resetGroup属性提供的break的地方被重新初始化(resetType=”Group”)。
缺省的属性为resetType=”Report”
Reset Group
如果存在的话,resetGroup属性包含了报表的组的名字并且仅与resetType=”Gropu”的resetType属性相关联。
5.6.1 运算(Calculations)
像以上所提到的,变量能执行内置的计算类型(build-in types of calculation)。下面是 元素的calculation属性的所有可能的值:
Calculation Nothing
这是变量执行的缺省计算。这意味着变量值在数据源的每次迭代时被重新计算(这里的计算只是简单的通过变量表达式给变量赋值)。
Calculation Count
在每次数据源的迭代的时候(
注:这里和之前我所说的数据源的迭代都是指:例如,在报表装填的时候,引擎执行
SQL
查询返回的
ResultSet
中含有若干记录,每次迭代都是指从
ResultSet
中获得一条记录,并将这条记录的值赋给已经声明的字段),一个计数(count)变量将会把用主表达式(main expression)计算所得的非空(not null)值累加起来。计数变量(Count variables)必须是一个数字类型的变量,但是它的主表达式可以是一个非数字型表达式(non-numeric expression),因为报表引擎不关心表达式类型,而仅仅将这些非空的返回值得数目累加起来—就好像一个累加器一样。
只有变量的初始值表达式必须是数字型的,并且需要和变量的类型相同,因为这个值将会在初始化的时候被直接赋给变量。
Calculation Sum
如果你选择了这种类型的计算,报表引擎将会把变量主表达式的返回值累加到一起,但需要注意的是变量必须是数字类型的。我们不能计算一个java.lang.String或java.util.Date类型的报表变量。
Calculation Average
对于数据源中的每一条记录,报表引擎可以计算通过对变量表达式求值所得的一些列结果的平均值(series of values obtained by evaluating the variable’s expression)。这种类型的计算的也只能是数字类型的变量。
为了完成计算平均值的操作,报表引擎将在后台了创建一个helper报表变量来计算values的累加和(sum),并用它来计算这些value的均值。这个helper sum variables的命名规则是在对应的变量名后面加上“_SUM”前缀。例如,如果你声明了一个数字类型的变量,名为MyAverageVariable,报表引擎将会建立一个MyVerageVariable_SUM的变量来帮助计算均值。如果你需要的话,你可以在其他的报表表达式中使用这个helper变量,就像你使用其他你声明的变量一样。
为了计算均值,报表引擎同时也需要一个计数变量(count variable)。但是对于“Report”,“Page”和“Column”的reset type,引擎将使用我们在下一节即将看到的内置的计数变量。对于resetType=“Group”的情况,引擎将在后台建立一个helper计数变量,这个变量的名字是在原来的均值变量名后面加上一个“_COUNT”后缀。
Calculation Lowest and Highest
对于每一个数据源记录来说,如果你想在一系列从赋值表达式中获得得最大或最小的value,你就需要选择这种类型的计算。
Calculation StandardDeviation(标准偏差) and Variance(方差)
在一些特殊的报表中,你可能会需要执行一些高级的数字运算,而JasperReport已经内置了对的一些经过变量表达式赋值所得到的value的标准偏差和方差进行计算的算法。和前面计算均值的方法一样,报表引擎首先建立一些helper变量来获得相应于当前一系列值的计数和累加和,这些变量命名方式和上面一样,这里不再赘述。
Calculation System
这种类型的计算被用在当你不希望报表引擎干预你的变量运算的时候,这意味着你将自己计算变量的值。对于这种类型的计算,报表引擎唯一可以做的就是从数据源的一个迭代到另一个迭代的过程中将你已经计算好的value保存起来(conserve)。
例子:下面是一个是变量声明的简单例子,这个变量将为所有名为“Quantity”的数字型报表字段求和。
$F{Quantity}
如果我们想求得每一页的这个字段的总合,则应该如下定义:
calculation="Sum">
$F{Quantity}
new Double(0)
在上面的例子中,我们的页累加变量将会在每一新页的开始时被置为0。
5.6.2 内置的报表变量(Build-in Report Variables)
JasperReport提供了一些内置的系统变量可以直接用于表达式中:
Variable PAGE_NUMBER
这个变量保存当前的页号,在报表装填结束的时候,这个变量就保存着最终文档的总页数。所以要在JasperReport的文本字段中显示页号和总页数你都可以用它。
Variable COLUMN_NUMBER
这个变量将记录当前的列号。
Variable REPORT_COUNT
当数据源迭代结束之后,这个变量里将包含被处理的数据record的总数。
Variable PAGE_COUNT
这个变量纪录当前页中处理的record的数目。
Variable COLUMN_COUNT
这个变量纪录生成当前列时所处理的record的数目。
Variable GroupName_COUNT
当我们声明一个group时,引擎将会自动建立一个用户计算构成当前group的记录数的计数变量,即在组和组的rupture之间所处理的纪录的数目。(注意,这里的GroupName是泛指组名,即任意一个组的名字)
至此,JasperReport的大致功能选项就都介绍完了,余下的部分如报表的各个组成部分,Scriptlet,报表元素(文本,图形元素--线,矩形,图片等),要么在JasperReport所给例子中才能有更好的理解,要么你只要用一下IReport就一目了然了(比如报表的各个组成部分在IReport中都是可视化的,文本,图形元素也都是可拖拽到报表上的,非常容易弄懂),至于高级部分SubReport的用法,这片文档也说得比较少,如果你需要的话就看看IReport的文档吧。不过我还是在下面列出了所有的英文原文,共有兴趣的朋友或我自己在遇到某些细节的时候备用。
J
6 Report Sections
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:
, ,
,
,
,
,
,
,
.
Sections are portions of the report template that have a specified height and width and can contain
report elements like lines, rectangles, images or text fields. Those sections are filled repeatedly at report
generating time and make up the final document that is being produced. When declaring the content
and layout of a report section, in an XML report design, we use the generic element
.
XML Syntax
| textField | subreport | elementGroup)*)>
height NMTOKEN "0"
>
Report sections are sometimes referred as report bands and represent a feature that almost all report
tools have and use in the same way.
Band Height
The attribute height available in a report band declaration specifies the height in pixels for that
particular band and is very important in the overall report design.
The elements contained by a certain report band should always fit the band's dimensions, to avoid
potential bad results when generating the reports. The engine issues a warning if it finds elements
outside the band borders, when compiling report designs.
Skipping Bands
All the report sections allow you to define a report expression that will be evaluated at runtime in order
to decide if that particular section should be generated or skipped, when producing the document.
This expression is introduced by the
that is available in any
element of the XML report design and should always return a
java.lang.Boolean
object or
null
.
The JasperReports Ultimate Guide
Page 39
6.1 Main Report Sections
A minimal report design can contain no report section at all, because each one of them is optional. But
such a minimal report design won't produce very interesting documents.
XML Syntax
So let's take a closer look at each report section and see how it behaves.
Title
This is the first section of the report. It is generated only once during the report filling process and
makes it for the beginning of the resulting document.
Being the first section of the report means that it will precede even the page header section. Those who
want to have the page header printed somehow before the title section will have to copy the elements
present on the page header also at the beginning of the title section. They could suppress the actual
page header on the first page using the
,
based on the
PAGE_NUMBER
report variable.
As we have already seen in the
4.3 Report Properties
paragraph, the title section could be followed by
a page break, if the attribute
isTitleNewPage
is set to
"true"
.
Page Header
This section appears at the top of each page in the generated document.
Column Header
This section appears at the top of each column in the generated document.
Detail
For each record in the data source, the engine will try to generate this section.
Column Footer
This section appears at the bottom of each column in the generated document. It never stretches
downward to acquire the content of its containing text fields and will always remain of declared fixed
height.
The JasperReports Ultimate Guide
Page 40
Page Footer
This section appears at the bottom of each page in the generated document. Just like the column footer
section above, the page footer never stretches downwards to acquire the content of its containing text
fields and will always remain of declared fixed height.
Summary
This section is generated only once per report and appears at the end of the generated document, but is
not necessarily the last section being generated.
That's because in some cases, the column footer or/and page footer of the last page can follow it.
As mentioned in the
4.3 Report Properties
paragraph, the summary section can start a new page of its
own, by setting the
isSummaryNewPage
attribute to
"true"
. Even if this attribute remains
false
, the
summary section always starts a new page if it does not fit on the remaining space of the last page or if
the report has more than one column and on the last page it has already started a second column.
If the main report sections that we have seen here are not sufficient for what you need, maybe you
should consider introducing supplementary sections like group headers and group footers.
We are now going to see how to group data on the report.
6.2 Data Grouping
Groups represent a flexible way to organize data on a report. A report group is represented by sequence
of consecutive records in the data source that have something in common, like the value of a certain
report field for example.
A report group has 3 components:
_
group expression;
_
group header section;
_
group footer section.
The value of the associated group expression is what makes group records stick tighter. This value is
the thing that they have in common. When the value of the group expression changes during the
iteration through the data source at report filling time, a group rupture occurs and the corresponding
group sections
and
are inserted in the resulting document.
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.
Data grouping works as expected only when the records in the data source are already
ordered accordingly to the group expressions used in the report.
For example, if you want to group some products by country and city of the manufacturer,
the engine expects to find the records in the data source already ordered by country and city.
If not, you should expect to find records belonging to a specific country or city in different
parts of the resulting document, because JasperReports does not sort the data source for you,
before using it.
The JasperReports Ultimate Guide
Page 41
XML Syntax
name NMTOKEN #REQUIRED
isStartNewColumn (true | false) "false"
isStartNewPage (true | false) "false"
isResetPageNumber (true | false) "false"
isReprintHeaderOnEachPage (true | false) "false"
minHeightToStartNewPage NMTOKEN "0"
>
Group Name
The name unequivocally identifies the group and can be used in other XML attributes, when you want
to refer a particular report group. The name of a group is mandatory and obeys the same naming
convention that we mentioned for the report parameters, fields and report variables.
Starting New Page/Column When Group Breaks
Sometimes is useful to introduce a page or column break when a new group starts, probably because
that particular group is more important and should start on a page or column of its own.
To instruct the engine to start a new page or column for a certain group, instead of going to print it on
the remaining space at the bottom of the page or column, you have to set to
"true"
either the
isStartNewPage
or
isStartNewColumn
attribute.
Those two attributes are the only settings in the entire library that let you voluntary
introduce page breaks. In all other situation, the reporting engine introduces page breaks
automatically, if it needs to.
However, in some report designs, you probably want to introduce page breaks on purpose,
because some particular report section of yours is larger than one page. You can achieve that
by introducing special dummy groups as you can see in the
Tips & Tricks
section of the
freely available documentation, published on the
JasperReports site
.
However, if you don't want to consistently introduce page or column breaks for a particular group, but
you rather do that only if the remaining space at the bottom of the page or column is too small, you
should consider using the
minHeightToStartNewPage
attribute.
This attribute specifies the minimum amount of remaining vertical space required so that the group
does not start a new page of its own. It is measured in pixels.
Resetting Page Number
If required, report groups have the power to reset the built-in report variable which contains the current
page number (variable
PAGE_NUMBER
). This could be achieved by setting the
isResetPageNumber
attribute to
"true"
.
The JasperReports Ultimate Guide
Page 42
Group Header
This section is the one that marks the start of a new group in the resulting document, and it is inserted
in the document every time the value of the group expression changes during the iteration through the
data source.
Group Footer
Every time a report group changes, the engine adds the corresponding group footer section before
starting the new group or when the report ends.
Check the provided samples like
jasper
,
datasource
or
query
, to see how report groups can be used.
The JasperReports Ultimate Guide
Page 43
7 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 have the possibility to affect the values stored by the report variables.
Since scriptlets work mainly with report variables, is important to h
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
.
In order to make use of this functionality, users only have to create a scriptlet class by extending one of
the following two classes:
dori.jasper.engine.JRAbstractScriptlet
dori.jasper.engine.JRDefaultScriptlet
The complete name of this custom scriptlet class (including the package) has to be specified in the
scriptletClass
attribute of the
element and has to be available in the classpath,
at report filling time, so that the engine could instantiate it on the fly. If no value is specified for the
scriptletClass
attribute, the engine will instantiate the
JRDefaultScriptlet
class.
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.
For more complex reports, if you need to use very complicate report expressions, for grouping or
displaying data, maybe you should consider transferring this complexity to a separate class to which
you then make calls from simplified report expressions. The scriptlet class is perfect for transferring
this complexity to. This is because the reporting engine supplies you with a reference to the scriptlet
object it creates on the fly using the
REPORT_SCRIPTLET
built-in parameter.
Check the
scriptlet
sample to see this type of functionality used.
The JasperReports Ultimate Guide
Page 44
8 Report Elements
The generated reports would be empty if you would not put some report elements in the report design.
The report elements are displayable objects like static texts, text fields, images, lines or rectangles, that
you put in your report design sections so that they appear in the final document.
As you can see, the report elements come in two flavors:
_
Text elements
: static texts and text fields that display dynamic content;
_
Graphic elements
: lines, rectangles and images.
We shall see those two element categories and their particularities in the following sections. For now
we are going to present in detail the element properties that both categories share.
When you add a report element to one of your report sections, you have to specify the relative position
of this element in that particular section and its size, along with other general report element properties
like color, transparency, stretch behavior, etc.
The properties that are common to all types of report elements are grouped in the
tag that can appear in the declaration of all report elements.
XML Syntax
positionType (Float | FixRelativeToTop | FixRelativeToBottom)
"FixRelativeToTop"
isPrintRepeatedValues (true | false) "true"
mode (Opaque | Transparent) #IMPLIED
x NMTOKEN #REQUIRED
y NMTOKEN #REQUIRED
width NMTOKEN #REQUIRED
height NMTOKEN #REQUIRED
isRemoveLineWhenBlank (true | false) "false"
isPrintInFirstWholeBand (true | false) "false"
isPrintWhenDetailOverflows (true | false) "false"
printWhenGroupChanges CDATA #IMPLIED
forecolor CDATA #IMPLIED
backcolor CDATA #IMPLIED
>
Absolute Position
The
x
and
y
attributes of any report element are mandatory and represent x and y coordinates,
measured in pixels, that mark the absolute position of the top-left corner of the specified element within
its parent report section.
Relative Position
Some report elements such as the text fields have special properties that allow them to stretch
downwards in order to acquire all the information they have to display. Their height is calculated at
runtime and may affect the other neighboring elements present in the same report section, especially
those placed immediately below them.
The
positionType
attribute specifies the behavior that the report element should have if the layout of
the report section in which it is been place is affected by stretch.
The JasperReports Ultimate Guide
Page 45
There are 3 possible values for the
positionType
attribute:
_
Floating position
: The element will float in its parent section if it is pushed downwards by other
elements fount above it. It will try to conserve the distance between it and the neighboring
elements placed immediately above (
positionType="Float"
).
_
Fixed position relative to the top of the parent band
: The current report element will simply ignore
what happens to the other section elements and tries to conserve the y offset measured from the top
of its parent report section (
positionType="FixRelativeToTop"
).
_
Fixed position relative to the bottom of the parent band
: If the height of the parent report section is
affected by elements that stretch, the current element will try to conserve the original distance
between its bottom margin and the bottom of the band
(
positionType="FixRelativeToBottom"
).
A report element called
e2
will float when another report element called
e1
stretches, only
if these three conditions are met:
_
e2
has
postitionType="Float"
_
e1.y + e1.height < e2.y
_
e1.width + e2.width >= max(e1.x + e1.width, e2.x + e2.width) –
min(e1.x, e2.x)
The second and the third conditions together say that the element
e2
must be placed below
the
e1
.
By default, all elements have a fixed position relative to the top of the band.
To see how element stretching and element floating work together, check the
stretch
sample provided.
Element Size
The
width
and
height
attributes are mandatory and represent the size of the report element measured
in pixels. Additional element settings that have to do with the element stretching mechanism will
determine the reporting engine to sometimes ignore the specified element height. But this attribute
remains mandatory since even when the height is calculated dynamically, the element will not be
smaller than the original specified height.
Element Color
There are two attributes that represent colors:
forecolor
and
backcolor
. The fore color is the one
used to draw the text of the text elements and the border of the graphic elements. The back color is the
one used to fill the background of the specified report element, if it is not transparent.
You could specify colors using the decimal or hexadecimal representation of the integer number
corresponding to the desired color. The preferred way to specify colors in XML is using the
hexadecimal representation, because it allows controlling the level for each base color of the RGB
system.
For example, you can display some text in red if you set the
forecolor
attribute of the corresponding
text field like this:
forecolor="#FF0000"
The equivalent using the decimal representation would be:
forecolor="16711680"
but the inconvenience is evident.
The JasperReports Ultimate Guide
Page 46
The default fore color is black and the default back color is white.
Element Transparency
Report elements can be either transparent or opaque, depending on the value you specify for the
attribute
mode
.
The default value for this attribute depends on the type of the report element. Graphic elements like
rectangles and lines are opaque by default, but the images are transparent. Both static texts and text
fields are transparent by default, and so are the subreport elements.
Skipping Element Display
The engine can decide at runtime if it really should display a report element, if you use the
that is available for all types of report elements.
If present, this report expression should return a
java.lang.Boolean
object or
null
and is evaluated
every time the section containing the current element is being generated, to see if this particular
element should appear or not in the report.
If the expression returns
null
, it is equivalent to returning
java.lang.Boolean.FALSE
and if the
expression is missing, the report element will get printed every time, that is if other setting do not
intervene, as we shall see below.
Reprinting Elements on Section Overflows
When generating a report section, the engine might be forced to start a new page or column, because
the remaining space at the bottom of the current page or column was not sufficient for all the section
elements to fit in, probably because some elements have stretched.
In such cases, you might want to reprint some of your already displayed elements, on the new page or
column, to recreate the context in which the page/column break occurred.
To achieve this, you have to set
isPrintWhenDetailOverflows="true"
for all those report
elements you want to reappear on the next page or column.
Suppressing Repeating Values Display
First, let's see what exactly a "repeating value" is.
It very much depends on the type of the report element we are talking about.
For text field elements, this is very intuitive. In the following list containing person names taken from
an usual phone book, you can see that for some consecutive lines, the value of the "Family Name"
column repeats itself (those are only dummy phone numbers
_
).
Family Name First Name Phone
Johnson Adam 256.12.35
Johnson Christine 589.54.52
Johnson Peter 546.85.95
Johnson Richard 125.49.56
Smith John 469.85.45
Smith Laura 459.86.54
Smith Denise 884.51.25
You might want to suppress the repeating "Family Name" values and print something like this:
The JasperReports Ultimate Guide
Page 47
Family Name First Name Phone
Johnson Adam 256.12.35
Christine 589.54.52
Peter 546.85.95
Richard 125.49.56
Smith John 469.85.45
Laura 459.86.54
Denise 884.51.25
You can do that, if for the text field that displays the family name, you set:
isPrintRepeatedValues="false"
The static text elements behave in the same way. As you would expect, their value always repeats and
in fact it never changes, until the end of the report. This is why we call them static texts. So, if you set
isPrintRepeatedValues="false"
for one of your
elements, you should expect to
see it displayed only once, the first time, at the beginning of the report, and never again.
Now, what about graphic elements?
An image is considered to be repeating itself if its bytes are exactly the same from one occurrence to
the next. This could only happen if you choose to cache your images using the
isUsingCache
attribute available in the
element and if the corresponding
returns the
same value from one iteration to the next (the same file name, the same URL, etc).
Lines and rectangles are always repeating themselves, because they are static elements, just like the
static texts we have seen above. So, when deciding to not display repeating values for a line or a
rectangle, you should expect to see it displayed only once, at the beginning of the report and then
ignored until the end of the report.
The
isPrintRepeatedValues
attribute works only if the corresponding
is missing. If this is not missing, it will always dictate if the
element should be printed or not, regardless of the repeating values.
If you decide to not display the repeating values for some of your report elements, you have the
possibility to soften or refine this behavior, by indicating the exceptional occasions to which you might
want to have a particular value redisplayed, during the report generation process.
When the repeating value spans on multiple pages or columns, you have the possibility to redisplay this
repeating value at least once for every page or column.
By setting
isPrintInFirstWholeBand="true"
, you make sure that the report element will
reappear in the first band of a new page or column that is not an overflow from a previous page or
column.
Also, if the repeating value you have suppressed spans on multiple groups, you have the possibility to
make it reappearing at the beginning of a certain report group, is you specify the name of that particular
group in the
printWhenGroupChanges
attribute.
Removing Blank Space
When report elements are not displayed for some reason:
evaluated to
Boolean.FALSE
, or repeated value being suppressed, a blank space remains where that report element
would have stood.
This blank space also appears if a text field displays only blank characters or an empty text.
There is a way to eliminate this unwanted blank space, on the vertical axis, only if some conditions are
met.
The JasperReports Ultimate Guide
Page 48
For example, if you have three successive text fields, one on top of the other like this:
TextField1
TextField2
TextField3
If the second one has an empty string as its value, or contains a repeated value that you chose to
suppress, the output would look like this:
TextField1
TextField3
In order to eliminate the gap between the first text field and the third, you have to set
isRemoveLineWhenBlank="true"
for your second text field. You would obtain something like this:
TextField1
TextField3
But there are certain conditions that have to be met in order for this functionality to work. The blank
space will not be removed, if your second text field shares some vertical space with other report
elements that are printed even this second text fields of your does not print.
For example, you might have some vertical lines on the sides of your report section like this:
| TextField1 |
| |
| TextField3 |
or you might have a rectangle that draws a box around your text fields:
------------------
| TextField1 |
| |
| TextField3 |
------------------
or even other text elements that are placed on the same horizontal with your second text field:
Label1 TextField1
Label2
Label3 TextField3
In all those situations, the blank space between the first and the third text field cannot be remove,
because it is being used by other report elements that are printed as you can see.
The blank vertical space between elements can be removed using the
isRemoveWhenBlank
attribute, only if it is not used by other elements, as explained above.
8.1 Text Elements
There are two kinds of text elements in JasperReports: static texts and text fields.
As their names suggest it, the first are text elements with a fixed, static content, who does not change
during the report filling process and are used especially for introducing labels on the final document.
Text fields however, have an associated expression, which is evaluated at runtime to produce the text
content that will be displayed.
Both types of text elements share some properties and those are introduced using a
element. We are now going to see them in detail.
The JasperReports Ultimate Guide
Page 49
XML Syntax
textAlignment (Left | Center | Right | Justified) "Left"
lineSpacing (Single | 1_1_2 | Double) "Single"
>
Text Alignment
You can specify how the content of a text element should be aligned using the
textAlignment
attribute and choosing one of the 4 possible values:
"Left"
,
"Center"
,
"Right"
or
"Justified".
Text Line Spacing
The amount of space between consecutive lines of text can be set using the
lineSpacing
attribute:
_
Single
: The paragraph text advances normally using an offset equal to the text line height
(
lineSpacing="Single"
).
_
1.5 Lines
: The offset between two consecutive text lines is of 1 ½ lines
(
lineSpacing="1_1_2"
).
_
Double
: The space between text lines is double the height of a single text line
(
lineSpacing="Double"
).
The font settings for the text elements are also part of the
tag, but we are going to see
them in detail, in the following separate section of this book.
8.1.1 Fonts and Unicode Support
Each text element present on your report can have its own font settings. Those settings can be specified
using the
tag available in the tag.
Since most of the time, in a report design, there are only a few types of fonts used, that are shared by
different text elements, there's no point forcing XML report design creators to specify the same font
settings for each text element, over and over again. But rather they could reference a report level font
declaration and adjust only some of the font settings, on the spot, if a particular text element requires it.
Report Fonts
A report font is in fact a collection of font settings declared at report level that can be reused
throughout the entire report design, when setting the font properties of text elements.
The JasperReports Ultimate Guide
Page 50
XML Syntax
name NMTOKEN #REQUIRED
isDefault (true | false) "false"
fontName CDATA "sansserif"
size NMTOKEN "10"
isBold (true | false) "false"
isItalic (true | false) "false"
isUnderline (true | false) "false"
isStrikeThrough (true | false) "false"
pdfFontName CDATA "Helvetica"
pdfEncoding CDATA "CP1252"
isPdfEmbedded (true | false) "false"
>
Report Font Name
The name attribute of a element is mandatory and must be unique, because it will be
used when referencing the corresponding report font throughout the report.
Default Report Font
You can use isDefault="true" for one of your report font declarations, to mark the report font that
you want to be used by the reporting engine as the default base font, when dealing with text elements
that do not reference a particular report font. This default font will also be used by the text elements
that do not have any font settings at all.
All the other report font properties are the same as those for a normal element that we are
going to see below.
XML Syntax
reportFont NMTOKEN #IMPLIED
fontName CDATA #IMPLIED
size NMTOKEN #IMPLIED
isBold (true | false) #IMPLIED
isItalic (true | false) #IMPLIED
isUnderline (true | false) #IMPLIED
isStrikeThrough (true | false) #IMPLIED
pdfFontName CDATA #IMPLIED
pdfEncoding CDATA #IMPLIED
isPdfEmbedded (true | false) #IMPLIED
>
Referencing a Report Font
When introducing the font settings for a text element of your report, you have the possibility to use a
report font declaration as a base, for those font settings you want to obtain.
All the attributes of the element, if present, are used only to override the attributes with the
same name that are present in the report font declaration referenced using the reportFont attribute.
The JasperReports Ultimate Guide
Page 51
For example, if we have a report font like the following:
name="Arial_Normal"
isDefault="true"
fontName="Arial"
size="8"
pdfFontName="Helvetica"
pdfEncoding="Cp1252"
isPdfEmbedded="false"/>
and we want to create a text field that has basically the same font settings like those in this report font,
but only a greater size, the only thing we should do is to reference this report font using the
reportFont attribute and specify the desired font size like this:
When the reportFont attribute is missing, the default report font is used as base font.
Font Name
In Java, there are two types of fonts: physical fonts and logical fonts. Physical fonts are the actual font
libraries consisting of, for example, TrueType or PostScript Type 1 fonts. The physical fonts may be
Arial, Time, Helvetica, Courier, or any number of other fonts, including international fonts.
Logical fonts are the five font types that have been recognized by the Java platform since version 1.0:
Serif, Sans-serif, Monospaced, Dialog, and DialogInput. These logical fonts are not actual font libraries
that are installed anywhere on your system. They are merely font-type names recognized by the Java
runtime, which must be mapped to some physical font that is installed on your system.
In the fontName attribute of the element or the element, you have to specify
the name of a physical font or the name of a logical font. You only have to make sure the font you
specify really exists and is available on your system.
For more details about fonts in Java, check the Java Tutorial or the JDK documentation.
Font Size
The font size is measured in points and can be specified using the size attribute.
Font Styles and Decorations
There are 4 boolean attributes available in the and elements that control the
font style and/or decoration. Those are isBold, isItalic, isUnderline and isStrikeThrough
and their significance should be evident to anybody.
PDF Font Name
When exporting reports to PDF format, the JasperReports library uses the iText library.
As their name states it (Portable Document Format) the PDF files can be viewed on various platforms
and you can be sure they will always look the same. This is partially because in this format there is a
special way of dealing with fonts.
The JasperReports Ultimate Guide
Page 52
If you want to design your reports so that they eventually be exported to PDF, you have to make sure
you choose the appropriate PDF font settings that correspond to the Java font settings of your text
elements.
The iText library knows how to deal with built-in fonts and TTF files. It recognizes the following builtin
font names:
Courier
Courier-Bold
Courier-BoldOblique
Courier-Oblique
Helvetica
Helvetica-Bold
Helvetica-BoldOblique
Helvetica-Oblique
Symbol
Times-Roman
Times-Bold
Times-BoldItalic
Times-Italic
ZapfDingbats
The iText library requires us to specify either a built-in font name from the above list, either the name
of a TTF file that it can locate on disk, every time we work with fonts. The font name introduced by the
fontName attribute previously explained is of no use when exporting to PDF. This is why we have
special font attributes, so that we are able to specify the font settings that the iText library expects from
us.
The pdfFontName attribute can contain the name of a PDF built-in font from the above list or the
name of a TTF file that can be located on disk at runtime, when exporting to PDF.
It is for the report design creator to choose the right value for the pdfFontName attribute
that would perfectly corresponds to the Java physical or logical font specified using the
fontName attribute. If those two fonts, one used by the Java viewers and printers and the
other used in the PDF format, do not represent in fact the same font, or do not at least look
alike, you might get unexpected results when exporting to PDF format.
Additional PDF fonts can be installed on your system if you choose one of the Acrobat Reader's font
packs. For example, by installing the Asian font pack from Adobe on your system, you would be able
to use for the pdfFontName attribute font names like:
Language PDF Font Name
Simplified Chinese STSong-Light
Traditional Chinese MHei-Medium
MSung-Light
Japanese HeiseiKakuGo-W5
HeiseiMin-W3
Korean HYGoThic-Medium
HYSMyeongJo-Medium
For more details about how to work with fonts when generating PDF documents, check the iText
library documentation.
PDF Encoding
When creating reports in different languages and wanting to export them to PDF, you have to make
sure that you choose the appropriate character encoding type.
For example, an encoding type widely used in Europe is Cp1252, also known as LATIN1. Other
possible encoding types are:
The JasperReports Ultimate Guide
Page 53
Character Set Encoding
Latin 2: Eastern Europe Cp1250
Cyrillic Cp1251
Greek Cp1253
Turkish Cp1254
Windows Baltic Cp1257
Simplified Chinese UniGB-UCS2-H
UniGB-UCS2-V
Traditional Chinese UniCNS-UCS2-H
UniCNS-UCS2-V
Japanese UniJIS-UCS2-H
UniJIS-UCS2-V
UniJIS-UCS2-HW-H
UniJIS-UCS2-HW-V
Korean UniKS-UCS2-H
UniKS-UCS2-V
You can find more details about how to work with fonts and character encoding when generating PDF
documents, here, in the iText library documentation.
PDF Embedded Fonts
If you want to use a TTF file when exporting your reports to PDF format and you want to make sure
everybody will be able to view it without problem, you have to make sure that at least one of the
following conditions are met:
_ they all have that TTF font installed on their systems;
_ you embed the font in the PDF document itself.
Its not easy to comply with the first condition and this is why the preferred way to do it is to embed the
TTF in the generated PDF documents that you are distributing.
You can do that by setting the isPdfEmbedded attribute to "true".
Further details about how to embed fonts in the PDF documents you can find in the iText
documentation. A very useful example you can find in the unicode sample provided with the project.
8.1.2 Static Texts
Static texts are text elements with fixed content, which does not change during the report filling
process. They are used mostly to introduce static text label in the generated documents.
XML Syntax
As you can see from the above presented syntax, besides element general properties and text specific
properties that we have already explained, a static text definition has in addition only the tag,
which introduces the fixed text content of the static text element.
8.1.3 Text Fields
Unlike static text elements, which do not change their text content, text fields have an associated
expression that is evaluated with every iteration in the data source, in order to obtain the text content
that has to be displayed.
The JasperReports Ultimate Guide
Page 54
XML Syntax
anchorNameExpression?, hyperlinkReferenceExpression?,
hyperlinkAnchorExpression?, hyperlinkPageExpression?)>
isStretchWithOverflow (true | false) "false"
evaluationTime (Now | Report | Page | Column | Group) "Now"
evaluationGroup CDATA #IMPLIED
pattern CDATA #IMPLIED
isBlankWhenNull (true | false) "false"
hyperlinkType (None | Reference | LocalAnchor | LocalPage |
RemoteAnchor | RemotePage) "None"
>
class (java.lang.Boolean | java.lang.Byte | java.util.Date |
java.sql.Timestamp | java.lang.Double | java.lang.Float | java.lang.Integer
| java.lang.Long | java.lang.Short | java.math.BigDecimal |
java.lang.String) "java.lang.String"
>
Variable Height Text Fields
Given the fact that text fields have a dynamic content, most of the time you wont be able to exactly
anticipate the amount of space you have to provide for your text fields so that they can display all their
content.
If the space you reserve for your text fields is not sufficient, the text content will be truncated so that it
fits in the available area.
This scenario is not always acceptable and you can let the reporting engine to calculate itself at runtime
the amount of space required to display the entire content of the text field and automatically adjust the
size of the report element.
You can achieve this by setting the isStretchWithOverflow to "true" for the particular text field
elements you are interested in. By doing this, you make sure that if the specified height for the text
field is not sufficient, it will automatically be increased (never decreased) in order to be able to display
the entire text content.
When text fields are affected by this stretch mechanism, the entire report section to which they belong
to will be also stretched.
Evaluating Text Fields
Normally, all the report expressions are evaluated immediately, using the current values of all the
parameters, fields and variables at that particular moment. It is like making a photo of all data, for
every iteration in the data source, during the report filling process.
This means that at any particular time, you won't have access to values that are going to be calculated
later, in the report filling process. It perfectly makes sense, since all the variables are calculated step by
step and reach their final value only when the iteration arrives at the end of the data source range they
cover.
For example, a report variable that calculates the sum of a field for each page will not contain the
expected sum until the end of the page is reached. That's because the sum is calculated step by step,
The JasperReports Ultimate Guide
Page 55
when iterating through the data source records, and at any particular time, the sum will be only partial,
since not all the records of the specified range have been processed.
If this is the case, how to display the page sum of a this field, on the page header, since this value will
be known only when the end of the page is reached. At the beginning of the page, when generating the
page header, our sum variable would contain zero, or its initial value.
Fortunately, JasperReports has a very interesting feature that lets you decide the exact moment you
want the text field expression to be evaluated, avoiding the default behavior which makes this
expression be evaluated immediately, when generating the current report section.
It is the evaluationTime attribute we are talking about. It can have one of the following values:
_ Immediate evaluation: The text field expression is evaluated when filling the current band
(evaluationTime="Now").
_ End of report evaluation: The text field expression is evaluated when reaching the end of the
report (evaluationTime="Report").
_ End of page evaluation: The text field expression is evaluated when reaching the end of the current
page (evaluationTime="Page").
_ End of column evaluation: The text field expression is evaluated when reaching the end of the
current column (evaluationTime="Column").
_ End of group evaluation: The text field expression is evaluated when the group specified by the
evaluationGroup attribute changes (evaluationTime="Group").
The default value for this attribute is "Now", as already mentioned. In the example presented above,
you could easily specify evaluationTime="Page" for the text field placed in the page header
section, so that it displays the value of the sum variable only when reaching the end of the current page.
The only restriction you should be aware of, when deciding to avoid the immediate
evaluation of the text field expression, is that in such cases, the text field will never stretch
in order to acquire all its content.
This is because the text element height is calculated when the report section is generated and
even the engine will come back later with the text content of the text field, the element
height will not be adapted, because it will ruin the already created layout.
Suppressing Null Values Display
If the text field expression returns null, your text field will display the "null" text in the generated
document. A simple way to avoid this is to set the isBlankWhenNull attribute to "true". By doing
this, the text field will cease to display "null" and will display an empty string. This way nothing will
appear on your document if the text field value is null.
Formatting Output
Of course, when dealing with numeric or date/time values, you could use the Java API to format the
output of the text field expressions yourself. But there is a more convenient way to do it: by using the
pattern attribute available in the element.
The value you should supply to this attribute is the same that you would supply if it were for you to
format the value using either the java.text.DecimalFormat class or
java.text.SimpleDateFormat class, depending on the type of value to format.
In fact, what the engine does is to instantiate the java.text.DecimalFormat class if the text field
expression returns subclasses of the java.lang.Number class or to instantiate the
java.text.SimpleDataFormat if the text field expression return java.util.Date or
java.sql.Timestamp objects.
For more detail about the syntax of this pattern attribute, check the Java API documentation for those
two classes: java.text.DecimalFormat and java.text.SimpleDateFormat.
The JasperReports Ultimate Guide
Page 56
Text Field Expression
We have already talked about the text field expression. There is nothing more to say about it except
that it is introduced by the element and can return values from only a
limited range of classes listed below:
java.lang.Boolean
java.lang.Byte
java.util.Date
java.sql.Timestamp
java.lang.Double
java.lang.Float
java.lang.Integer
java.lang.Long
java.lang.Short
java.math.BigDecimal
java.lang.String
If the text field expression class is not specified using the class attribute, it is assumed to be
java.lang.String, by default.
8.2 Graphic Elements
The second major category of report elements, besides text elements that we have seen, are the graphic
elements. In this category we have lines, rectangles and images.
They all have some properties in common and those are grouped under the attributes of the
tag.
XML Syntax
stretchType (NoStretch | RelativeToTallestObject |
RelativeToBandHeight) "NoStretch"
pen (None | Thin | 1Point | 2Point | 4Point | Dotted) #IMPLIED
fill (Solid) "Solid"
>
Stretch Behavior
The stretchType attribute of a graphic element can be used to customize the stretch behavior of the
element when on the same report section there are text fields that stretch themselves because their text
content is too large to fit in the original text field height.
When stretchable text fields are present on a report section, the height of the report section itself will be
affected be stretch.
A graphic element can respond to the modification of the report section layout in three ways:
_ Won't stretch: The graphic element preserves its original specified height
(strechType="NoStretch").
_ Stretching relative to the parent band height: The graphic element will adapt its height to match
the new height of the report section it placed on, which has been affected by stretch
(stretchType="RelativeToBandHeight").
_ Stretching relative to the tallest element in group: You have the possibility to group the elements
of a report section in multiple imbricate groups, if you like. The only reason you might have for
grouping your report elements is to be able to customize their stretch behavior. Details about how
to group elements are supplied in the section 8.4 Element Groups that will follow. Graphic
The JasperReports Ultimate Guide
Page 57
elements can be made to automatically adapt their height to fit the amount of stretch suffered by
the tallest element in the group that they are part of
(stretchType="RelativeToTallestObject").
Border Thickness
Unlike text elements, the graphic elements always have a border. You can control the type and
thickness of it using the pen attribute. Remember that the color of the border comes from the
forecolor attribute presented when describing the tag, in a previous chapter.
Here are all the possible types for a graphic element border:
_ No border: The graphic element will not display any border around it (pen="None").
_ Thin border: The border around the graphic element will be half a point thick (pen="Thin").
_ 1 point thick border: Normal border (pen="1Point").
_ 2 points thick border: Thick border (pen="2Point").
_ 4 point thick border: (pen="4Point").
_ Dotted border: The border will be 1 point thick and made of dots (pen="Dotted").
The default border around graphic elements depends on their type. Lines and rectangles have a normal
1 point thick border by default. Images however, do not display any border, by default.
Background Fill Style
The fill attribute specifies the style of the background for the graphic elements, but the only style
supported for the moment is the solid fill style, which is also the default (fill="Solid").
8.2.1 Lines
When displaying a line element, JasperReports draws one of the two diagonals of the rectangle
represented by the x, y, width and height attributes specified for this particular line element.
XML Syntax
direction (TopDown | BottomUp) "TopDown"
>
Line Direction
Which one of the two diagonals of the rectangle should be drawn can be decided using the direction
attribute:
_ The diagonal that starts in the top-left corner of the rectangle and goes to the bottom left corner is
drawn in case you set direction="TopDown".
_ The line will start in the bottom-left corner and will go to the upper-right if you choose
direction="BottomUp".
You can draw vertical lines by specifying width="0" and horizontal lines setting height="0". For
such lines the direction is not important.
The default direction for a line is "TopDown".
The JasperReports Ultimate Guide
Page 58
8.2.2 Rectangles
The rectangles are the most basic graphic elements. This is why there are no supplementary settings to
make for the declaration of a rectangle element, besides those already seen when talking about the
and tags.
XML Syntax
For more detailed examples of lines and rectangles, check the shapes sample.
8.2.3 Images
The most complex graphic elements that you can have on a report are the images.
Just like for the text field elements, their content is dynamically evaluated at runtime, using a report
expression.
XML Syntax
anchorNameExpression?, hyperlinkReferenceExpression?,
hyperlinkAnchorExpression?, hyperlinkPageExpression?)>
scaleImage (Clip | FillFrame | RetainShape) "RetainShape"
isUsingCache (true | false) "true"
evaluationTime (Now | Report | Page | Column | Group) "Now"
evaluationGroup CDATA #IMPLIED
hyperlinkType (None | Reference | LocalAnchor | LocalPage |
RemoteAnchor | RemotePage) "None"
>
class (java.lang.String | java.io.File | java.net.URL |
java.io.InputStream | java.awt.Image) "java.lang.String"
>
Scaling Images
Given the fact that images are loaded at runtime, there is no way knowing their exact size, when
creating the report design. It might be that the dimensions of the image element specified at design time
do not correspond to the actual image loaded at runtime.
This is why you have to decide how you expect the image to behave in order to adapt to the original
image element dimensions you specified in the report design. There is the scaleImage attribute that
allows you to do that, by choosing one of its 3 possible values:
_ Clipping the image: If the actual image is larger than the image element size, it will be cut off so
that it keeps its original resolution, and only the region that fits the specified size will be displayed
(scaleImage="Clip").
The JasperReports Ultimate Guide
Page 59
_ Forcing the image size: If the dimensions of the actual image do not fit those specified for the
image element that displays it, the image can be forced to obey them and stretch itself so that it fits
in the designated output area. It will be deformed if necessary (scaleImage="FillFrame").
_ Keeping image proportions: If the actual image does not fit into the image element, it can be
adapted to those dimensions without needing to deform it and keep its original proportions
(scaleImage="RetainShape").
Retain Shape
Clip
Fill Frame
- figure 7 -
Caching Images
All image elements have dynamic content. There are no special elements to introduce static images on
the reports, like we have special static text elements.
However, most of the time, the images on a report are in fact static and do not necessarily come from
the data source or from parameters. In the majority of cases, they are loaded from files on disk and
represent logos and other static resources.
If we have to display the same image multiple times on a report, if it is about a logo appearing on the
page header for example, there is no point on loading the image file every time we have to display it.
We can instruct the reporting engine to cache this particular image. This way we are making sure that
the image will be loaded from disk or from its particular location only once and then it will only be
reused every time it has to be displayed.
By setting the isUsingCache attribute to "true", the reporting engine will try to recognize
previously loaded images using their specified source. For example, it will recognize an image if the
image source is a file name that it has already loaded, or if it is the same URL.
This caching functionality is available only for image elements that have expressions returning
java.lang.String objects as the image source, representing file names, URLs or classpath
resources. That's because the engine uses the image source string as the key to recognize that it is the
same image that it has already cached.
Evaluating Images
As we have already seen when talking about text fields, you have the possibility to postpone the
evaluation of the image expression, which by default is performed immediately.
This would allow you to display in some region of a document, images that are going to be built or
chose only later in the report filling process, due to complex algorithms or whatever.
The same attributes, evaluationTime and evaluationGroup, that we have talked about in the text
fields section are available also in the element. The evaluationTime attribute can have the
following values:
_ Immediate evaluation: The image expression is evaluated when filling the current band
(evaluationTime="Now").
_ End of report evaluation: The image expression is evaluated when reaching the end of the report
(evaluationTime="Report").
_ End of page evaluation: The image expression is evaluated when reaching the end of the current
page (evaluationTime="Page").
The JasperReports Ultimate Guide
Page 60
_ End of column evaluation: The image expression is evaluated when reaching the end of the current
column (evaluationTime="Column").
_ End of group evaluation: The image expression is evaluated when the group specified by the
evaluationGroup attribute changes (evaluationTime="Group").
The default value for this attribute is "Now".
Image Expression
The value returned by the image expression is used as the source for the image that is going to be
displayed. The image expression is introduced by the element and can return
values from only a limited range of classes listed below:
java.lang.String
java.io.File
java.net.URL
java.io.InputStream
java.awt.Image
When the image expression returns a java.lang.String value, the engine will try to see
whether the value represents an URL from which to load the image. If it is not a valid URL
representation, it will try to locate a file on disk and load the image from it, assuming that
the value represents a file name. If no file is found, it will finally assume that the string
value represents the location of a classpath resource and will try to load the image from
there. Only if all those fail, an exception will be thrown.
If the image expression class is not specified using the class attribute, it is assumed to be
java.lang.String, by default.
The images sample provided with the project contains several examples of image elements.
8.2.4 Charts and Graphics
The JasperReports library does not produce charts and graphics itself. This is not one of its goals.
However, it can easily integrate charts and graphics produces by other, more specialized Java libraries.
The great majority of available Java libraries that produce charts and graphics can output to image files
or to in-memory Java image objects. This is why it shouldn't be hard for anybody to put a chart or a
graphic generated by one of those libraries into a JasperReports document using a normal image
element that we have presented in the previous section of this book.
You can see this working in the sample called chart, which comes with the project.
8.3 Hyperlinks
JasperReports allows you to create drill-down reports, to introduce tables of contents in your
documents or to redirect viewers to other external documents using special report elements called
hyperlinks.
Hyperlinks are special elements that contain a reference to a local destination within the current
document or to an external resource to which the viewer of the document will be redirected if he or she
clicks on that particular hyperlink element.
Hyperlinks are not the only actors in this viewer-redirecting scenario. There has to be a way for you to
specify what are the destinations in a document. These local destinations are called anchors.
The JasperReports Ultimate Guide
Page 61
There are no special report elements that introduce hyperlinks or anchors in a report design, but rather
some special setting that make an usual report element to be a hyperlink or/and an anchor.
In JasperReports, only text field elements and image elements can be hyperlinks or anchors. This is
because for both types of elements, there are special settings that allow you to specify the hyperlink
reference to which the hyperlink will point or the name of the local anchor. Note that a particular text
field or image can be both anchor and hyperlink at the same time.
XML Syntax
Hyperlink Type
When presenting the XML syntax for text field elements and image elements, you probably saw that
there was an attribute called hyperlinkType, which we didn't explain at that moment. We are going
to do that right now and here are the possible values for this attribute along with their significance:
_ No hyperlink: By default, neither the text fields nor the images represent hyperlinks, even if the
special hyperlink expressions are present (hyperlinkType="None").
_ External reference: The current hyperlink points to an external resource specified by the
corresponding element, usually an URL
(hyperlinkType="Reference").
_ Local anchor: The current hyperlink points to a local anchor specified by the corresponding
element (hyperlinkType="LocalAnchor").
_ Local page: The current hyperlink points to a 1 based page index within the current document
specified by the corresponding element
(hyperlinkType="LocalPage").
_ Remote anchor: The current hyperlink points to an anchor specified by the
element, within an external document indicated by the
corresponding element
(hyperlinkType="RemoteAnchor").
_ Remote page: The current hyperlink points to a 1 based page index specified by the
element, within an external document indicated by the
corresponding element
(hyperlinkType="RemotePage").
Anchor Expression
If present in a text field or image element declaration, the tag will
transform that particular text field or image into a local anchor of the resulting document, to which
hyperlinks can point. The anchor will bare the name returned after evaluating the anchor name
expression, which should always return java.lang.String values.
Hyperlink Expressions
Depending on the current hyperlink type, one or two of the following expressions will be evaluated and
used to build the reference to which the hyperlink element will point:
The JasperReports Ultimate Guide
Page 62
>
What is important to know is that the first two should always return java.lang.String and the third
should return java.lang.Integer values.
There is a special sample called hyperlink, provided with the projects, which shows how this type of
report elements can be used.
8.4 Element Groups
Report elements placed in any report section can be arranged in multiple imbricate groups. The only
reason you might have for grouping your elements is to be able to customize the stretch behavior of the
graphic elements, as explained in the section 8.2 Graphic Elements.
The stretchType attribute, available for graphic elements, has among its possible values one called
"RelativeToTallestObject". When choosing this option, the engine will try to identify the object
from the same group with the current graphic element, which suffered the biggest amount of stretch. It
will then adapt the height of the current graphic element to the height of this tallest element of the
group.
But for this to work, you have to group your elements. This is done using the and
tags to mark the elements that are part of the same group.
XML Syntax
subreport | elementGroup)*>
Element groups can contain other nested element groups and there is no limit on the number of the
nested element groups.
Check the stretch sample, to see how element grouping works.
The JasperReports Ultimate Guide
Page 63
9 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 or when the structure of a single report is not sufficient to describe the complexity of the
desired output document.
A subreport is in fact a normal report that is been incorporated as apart of another report. You can
imbricate your subreports and make a subreport that contains itself other
subreports, the nesting level
not being limited.
On the other hand, a subreport is also a special kind of a report element that helps you introduce a
subreport into the parent report.
There's nothing more to say about subreports, seen as normal reports, because they are compiled and
filled just like normal reports are and we already have seen all that in previous chapters. In fact, any
report design can be used as a subreport when incorporated into another report design, without the need
to change anything inside it.
What we are going to see now, are the details concerning the element that you use when
introducing subreports into master reports.
XML Syntax
subreportParameter*, (connectionExpression | dataSourceExpression)?,
subreportExpression?)>
isUsingCache (true | false) "true"
>
name NMTOKEN #REQUIRED
>
class (java.lang.String | java.io.File | java.net.URL |
java.io.InputStream | dori.jasper.engine.JasperReport) "java.lang.String"
>
Subreport Expression
Just like normal report designs, subreport designs are in fact dori.jasper.engine.JasperReport
objects. Those are obtained after compiling a dori.jasper.engine.design.JasperDesign object
as seen in the 3.2 Compiling Report Designs section of this book.
The JasperReports Ultimate Guide
Page 64
We have seen that the text field elements have an expression that will be evaluated to obtain the text
content to display. The image elements have an expression representing the source of the image to
display. In the same way, subreport elements have an expression that is evaluated at runtime, in order
to obtain the source of the dori.jasper.engine.JasperReport object to load.
The so-called subreport expression is introduced by the element and can
return values from the following classes:
java.lang.String
java.io.File
java.net.URL
java.io.InputStream
dori.jasper.engine.JasperReport
When the subreport expression returns a java.lang.String value, the engine will try to
see whether the value represents an URL from which to load the subreport design object. If
it is not a valid URL representation, it will try to locate a file on disk and load the subreport
design from it, assuming that the value represents a file name. If no file is found, it will
finally assume that the string value represents the location of a classpath resource and will
try to load the subreport design from there. Only if all those fail, an exception will be
thrown.
If the image expression class is not specified using the class attribute, it is assumed to be
java.lang.String, by default.
Caching Subreports
A subreport element can load different subreport designs with every evaluation, giving you great
flexibility in shaping you documents.
However, most of the time, the subreport elements on a report are in fact static and their source do not
necessarily change with every new evaluation of the subreport expression. In the majority of cases, the
subreport designs are loaded from fixed locations: files on disk or static URLs.
If the same subreport design is filled multiple times on a report, there is no point on loading the
subreport design object from the source file every time we have to fill it with data.
We can instruct the reporting engine to cache this particular subreport design object. This way we are
making sure that the subreport design will be loaded from disk or from its particular location only once
and then it will only be reused every time it has to be filled.
By setting the isUsingCache attribute to "true", the reporting engine will try to recognize
previously loaded subreport design objects, using their specified source. For example, it will recognize
a subreport object if its source is a file name that it has already loaded, or if it is the same URL.
This caching functionality is available only for subreport elements that have expressions returning
java.lang.String objects as the subreport design source, representing file names, URLs or
classpath resources. That's because the engine uses the subreport source string as the key to recognize
that it is the same subreport design that it has already cached.
The JasperReports Ultimate Guide
Page 65
9.1 Subreport Parameters
Since subreports are normal reports themselves, they are compiled or filled in the same way. This
means that they also require a data source from which to get the data when they are filled and that can
also receive parameters, for the additional information they have to use when being filled.
There are two ways to supply the parameter values to a subreport and they can be used simultaneously,
if desired.
You can supply a map containing the parameter values, like we do when filling a normal report with
data, using one of the fillReportXXX() methods exposed by the
dori.jasper.engine.JasperFillManager class (see the 3.4 Filling Reports chapter to refresh
your memory).
This can be achieved if you use the element, which introduces the
expression that will be evaluated in order to obtain the specified parameter map. This expression should
always return a java.util.Map object in which the keys are the parameter names.
In addition to or instead of supplying the parameter values in a map, you can supply the parameter
values individually, one by one, using a element for each parameter you are
interested in. In such case, you have to specify the name of the corresponding parameter using the
mandatory name attribute and you have to provide an expression that will be evaluated at runtime to
obtain the value for that particular parameter, value that will be supplied to the subreport filling
routines.
Note that you can use both ways to provide subreport parameter values, simultaneously. When this
happens, the parameter values specified individually, using the element, will
override the parameters values present in the parameter map, that correspond to the same subreport
parameter. If the map does not contain corresponding parameter values already, the individually
specified parameter values will be added to the map.
Attention! When you supply the subreport parameter values, you have to be aware that the
reporting engine will affect the java.util.Map object it receives, adding the built-in
report parameter values that correspond to the subreport. This map is also affected by the
individually specified subreport parameter values, as already explained above.
In order to avoid altering the original java.util.Map object that you send, you can wrap it
in a different map, before supplying it to the subreport filling process like this:
new HashMap(myOriginalMap)
This way, your original map object remains unaffected and modifications are made to the
wrapping map object.
This is useful especially when you want to supply to your subreport the same set of
parameters that the master report has received and you use the built-in
REPORT_PARAMETERS_MAP report parameter of the master report. However, you don't want
to affect the value of this built-in parameter and you will wrap it like this:
new HashMap($P{REPORT_PARAMETERS_MAP})
The JasperReports Ultimate Guide
Page 66
9.2 Subreport Data Source
Subreports need a data source in order to generate their content, just like normal report do.
In the 3.4 Filling Reports chapter of this book we have seen that when filling a report you have to
supply either a data source object or a connection object, depending on that particular report type. That
is if it has an internal SQL query and you want to have it executed to obtain the report data or you
supply the report data yourself.
Subreports behave in the same way and expect to receive the same kind of input when they are being
filled.
You can supply to your subreport either a data source using the element
or a JDBC connection for the engine to execute the subreport's internal SQL query using the
element. These two XML elements cannot be both present at the same
time in a subreport element declaration. This is because you cannot supply both a data source and a
connection for your subreport. You have to decide on one of them and stick to it.
The report engine expects that the data source expression returns a
dori.jasper.engine.JRDataSource object and that the connection expression returns a
java.sql.Connnection object, whichever is present.
You can see how subreports work, if you check the subreport sample.
The JasperReports Ultimate Guide
Page 67
10 Advanced JasperReports
Previous chapters have presented the core functionality that most people will get to use when working
with the JasperReports library.
However, some complex requirements of your specific applications might force you to dig deeper into
the JasperReports functionality in order to adapt it to suit you needs.
In the following sections we are going to take a closer look at those aspects that are likely to interest
you if you'll want to make full benefit from the use of the JasperReports library.
10.1 XML Report Designs Loading and Writing
In the 3.2 Compiling Report Designs chapter we have explained how report designs pass from their
initial XML form into the compiled form, before being used to generate full-featured documents.
The engine first parses the XML report design and creates the in-memory representation of it by
instantiating and preparing a dori.jasper.engine.design.JasperDesign object. This object is
then subject to various validation checks and suffers the compilation process that produces a
corresponding dori.jasper.engine.JasperReport object.
But in certain cases, in your application, you might want to manually load the XML report design into a
dori.jasper.engine.design.JasperDesign object, without immediately compiling it. Such
scenarios might be common for applications that programmatically create report designs and use the
XML form to store them temporary or permanently.
Loading dori.jasper.engine.design.JasperDesign objects from XML report design can be
easily by calling one of the public static load() methods exposed by the
dori.jasper.engine.xml.JRXmlLoader class. This way you can load report design object from
XML content store in filed or that is been read from input streams.
The process opposed to the XML report design loading process is the generation of the XML form for a
given report design object.
As seen above, sometimes report designs are created programmatically, using the JasperReports API.
The report design objects obtained this way can be serialized, for disk storage or transfer over the
network, but they also can be stored in XML format.
You can obtain the XML representation of a given report design object by using one of the public static
writeReport() methods exposed by the dori.jasper.engine.xml.JRXmlWriter utility class.
10.2 Implementing Data Sources
JasperReports library comes with several default implementations of the
dori.jasper.engine.JRDataSource interface. This interface is used to supply the report data
when invoking the report filling process, as explained in the previous chapters of this book.
These default implementations let you generate reports using data from relational databases retrieved
through JDBC, from Java Swing tables or from collections and arrays of JavaBeans objects.
But maybe your application data that your are trying to display in your reports has a special structure or
is organized in a very particular way preventing you from using any of the default implementations of
the data source interface that come with the library.
In such situations, you will have to create custom implementations for the
dori.jasper.engine.JRDataSource interface, in order to wrap your special report data, so that
the reporting engine can understand and use it when generating the reports for you.
The JasperReports Ultimate Guide
Page 68
Creating a custom implementation for the dori.jasper.engine.JRDataSource interface is not
very difficult since you have to implement only two methods.
The first one, the next() method, is called by the reporting engine every time it wants the current
pointer to advance to the next virtual record in the data source.
The other, the getFieldValue() method, is called by the reporting engine with every iteration in the
data source to retrieve the value for each report field.
10.3 Customizing Viewers
The JasperReports library comes with built-in viewers that allow you to display the reports stored in the
library's proprietary format or to preview your report designs when you create them.
These viewers are represented by the following two classes:
_ dori.jasper.view.JasperViewer : You use this class to view generated reports, either as
in-memory objects or serialized objects on disk or even stored in XML format.
_ dori.jasper.view.JasperDesignViewer : This class can be used to preview report
designs, either in XML form or compiled form.
But these default viewers might not suit everybody's needs and therefore you might consider
customizing them so they adapt to certain application requirements.
In order to do that, you should be aware that these viewers use in fact other, more basic visual
components that come with the JasperReports library.
The report viewer mentioned above use the visual component represented by the
dori.jasper.view.JRViewer class and its companions. It is in fact a special
javax.swing.JPanel component that is capable of displaying generated reports and that can be
easily incorporated in other Java Swing based applications or applets.
If the functionality of this basic visual component is not sufficient for what you need, you can adapt it
by subclassing it. If for example you would want to have an extra button on the toolbar of this viewer,
you might consider extending the component and add that button yourself in the new visual component
you obtain by subclassing.
This can be seen in the webapp sample, where the "Printer Applet" displays a customized version of the
report viewer with an extra button in the toolbar.
Another very important issue is that the default report viewer that comes with the library does not know
how to deal with document hyperlinks that point to external resources. It only deals with local
references and can redirect the viewer to corresponding local anchor.
However, JasperReports offers you the possibility to handle yourself the clicks made on document
hyperlinks that point to external documents and not local anchors.
The only thing you have to do in order to achieve this, is to implement the
dori.jasper.view.JRHyperlinkListener interface and to add to register with the viewer
component an instance of this listener class, using the addHyperlinkListener() method exposed
by the dori.jasper.view.JRViewer class.
By doing this, you make sure the viewer will also call your implementation of the gotoHyperlink()
method in which you handle yourself the external references.
10.4 Exporting to New Output Formats
The JasperReports library continually evolves and improves. Among the features that are likely to be
introduced with time is the ability to export to new documents formats, besides PDF, HTML and XML.
In order to extend diversify in this direction, without affecting the existing functionality, JasperReports
provides those interested in this subject an interface for them to implement, in case they want to create
exporter classes that transform the generated documents into new output formats.
This way, if you need to export your reports into a special output format that is not yet available in the
core library, you might decide to implement yourself the dori.jasper.engine.JRExporter
interface.
The JasperReports Ultimate Guide
Page 69
Before deciding to implement this interface, it is important for you to understand how the
implementation is expected to function.
All the input data the exporter might need should be supplied to it using the so-called exporter
parameters, before the exporting process is started.
This is because the exporting process will be always invoked by calling the exportReport() method
of the dori.jasper.engine.JRExporter interface, and this method does not receive any
parameters itself, when called. The exporter parameters have to be already set using the
setParameter() method on the exporter instance you are working with, before launching the export
task.
You might choose to bulk set all your exporter parameters using the setParameters() method which
receives a java.util.Map object containing the parameter values. The keys in this map should be
instances of the dori.jasper.engine.JRExporterParameter class, as you would supply when
individually calling the setParameter() method for each of your exporter parameters.
Note that no matter what the type of output your exporter produces, you will be using parameters to
indicate to the exporter where to place or send this output.
Such parameter might be called OUT parameters.
For example, if you want your exporter to send the output it produces to an output stream, you will
supply the java.io.OutputStream object reference to the exporter using a parameter, probably
identified by the dori.jasper.engine.JRExporterParameter.OUTPUT_STREAM constant.
It is recommended to use the public constants of the
dori.jasper.engine.JRExporterParameter class to identify the parameters you set in your
exporters and only if you don't find one available for a particular setting you have to make in your
exporter, to extend this class to add new constants. This can be seen for the
dori.jasper.engine.export.JRXmlExporter, where special parameter identifier where created
by subclassing the dori.jasper.engine.JRExporterParameter class in the
dori.jasper.engine.export.JRXmlExporterParameter class.
You don't have to start from scratch when implementing the exporter interface, because there is a
convenience abstract class called dori.jasper.engine.JRAbstractExporter that at least deals
with parameter management for you.