Sample Reference - Schema Reference - Configuration Reference - API (Javadoc)
|
|
|
|
JasperReports - Jasper Sample (version 4.0.1) | ![]() |
|
|
|
Main Features in This Sample | |
| Data Grouping |
| Exporting to CSV Format Using Report Metadata |
| Conditional Styles |
![]() | ![]() | ![]() | ![]() |
|
|
|
top | ||||||
|
||||||
![]() | Data Grouping | Documented by Sanda Zaharia | ||||
|
||||||
| Description / Goal |
| How to group data at different levels and perform aggregate calculations using report groups. | |||
| Since |
| 0.1.0 | |||
| Other Samples |
|
|
|||
|
||||||
|
Grouping Data in JasperReports
A report's content can be better organized if the report data are grouped by meaningful criteria. For instance, a shipping report becomes more relevant when its data are grouped by product type, or by customer's country, etc. And as a bonus, grouped data allow statistic calculations to be performed and additional statistic information to be added to the report at runtime. As seen above, there are multiple reasons of grouping and aggregating data before they are represented. In JasperReports there are two ways to accomplish this:
Any group in a report can be customized through its attributes:
Report variables are special objects built on top of a report expression in order to apply the code reusability during the report design stage. Report templates are a lot simplified when expressions frequently used throughout the report template are declared in a single place as objects that can be referenced by their name as unique identifier. Another great advantage of declaring expressions as variables is the ability to perform various calculations based on their corresponding expression. A report variable is characterized by the following attributes:
For more about report variables one can consult also the tutorial. Being familiarized with variables, it's time to focus back on data grouping. Report variables are very useful objects in a report, that can operate on any collection of data. Since groups are aggregating data in meaningful collections, variables could be used to perform operations at group level too. As seen above, they can be reset or incremented any time a group breaks, and can be used to perform various built-in calculations over parameters, other variables and/or field values in a group. Related to groups, there is a special built-in counting variable, used to count the number of records in a group. This type of variables are always named with the related group's name followed by the _COUNT suffix. In this sample we'll find some usage examples
of this group counting variables.
The Jasper Sample This sample illustrates how groups can be used to produce documents with complex data grouping in a multicolumn layout. The reports/FirstJasper.jrxml file describes a shipping report presented
in a 2-column layout, with data organized according to several specific grouping criteria.
The 2-column layout is given by the columnCount="2" attribute setting in the
<jasperReport/> element.
Further, one can see the report query retrieving data ordered by the ShipCountry field:
<queryString><![CDATA[SELECT * FROM Orders WHERE OrderID <= $P{MaxOrderID} ORDER BY ShipCountry]] ></queryString>Next in the report are defined some variables related to groups: <variable name="FirstLetter" class="java.lang.String" resetType="None"> <variableExpression><![CDATA[$F{ShipCountry}.substring(0, 1).toUpperCase()]] ></variableExpression> </variable> <variable name="FreightSumFirstLetterGroup" class="java.lang.Double" resetType="Group" resetGroup="FirstLetterGroup" calculation="Sum"> <variableExpression><![CDATA[$F{Freight}]] ></variableExpression> </variable> <variable name="FreightSumCountryGroup" class="java.lang.Double" resetType="Group" resetGroup="CountryGroup" calculation="Sum"> <variableExpression><![CDATA[$F{Freight}]] ></variableExpression> </variable> <variable name="FreightSumColumn" class="java.lang.Double" resetType="Column" calculation="Sum"> <variableExpression><![CDATA[$F{Freight}]] ></variableExpression> </variable> <variable name="FreightSumPage" class="java.lang.Double" resetType="Page" calculation="Sum"> <variableExpression><![CDATA[$F{Freight}]] ></variableExpression> </variable> <variable name="FreightSumReport" class="java.lang.Double" calculation="Sum"> <variableExpression><![CDATA[$F{Freight}]] ></variableExpression> </variable> <variable name="DateHighestCountryGroup" class="java.sql.Timestamp" resetType="Group" resetGroup="CountryGroup" calculation="Highest"> <variableExpression><![CDATA[$F{OrderDate}]] ></variableExpression> </variable> <variable name="RegionCountCountryGroup" class="java.lang.Integer" resetType="Group" resetGroup="CountryGroup" calculation="Count"> <variableExpression><![CDATA[$F{ShipRegion}]] ></variableExpression> </variable>Now let's take a look at the groups themselves: <group name="FirstLetterGroup" isStartNewColumn="true" isReprintHeaderOnEachPage="true" minHeightToStartNewPage="200"> <groupExpression><![CDATA[$V{FirstLetter}]] ></groupExpression> <groupHeader> <band height="25"> ... <textField> <reportElement mode="Opaque" x="130" y="14" width="140" height="11" forecolor="#ff0000" backcolor="#ffdddd" style="Sans_Bold"/> <textFieldExpression class="java.lang.String"><![CDATA[$V{FirstLetter}]] ></textFieldExpression> </textField> </band> </groupHeader> <groupFooter> <band height="15"> ... <textField> <reportElement x="45" y="1" width="25" height="11" forecolor="#ff0000" style="Sans_Bold"/> <textElement textAlignment="Right"/> <textFieldExpression class="java.lang.Integer"><![CDATA[$V{FirstLetterGroup_COUNT}]] ></textFieldExpression> </textField> ... <textField pattern="0.00"> <reportElement x="170" y="1" width="60" height="11" forecolor="#ff0000" style="Sans_Bold"/> <textElement textAlignment="Right"/> <textFieldExpression class="java.lang.Double"><![CDATA[$V{FreightSumFirstLetterGroup}]] ></textFieldExpression> </textField> <textField evaluationTime="Auto"> <reportElement x="230" y="1" width="40" height="11" forecolor="#ff0000" style="Sans_Bold"/> <textElement textAlignment="Right"/> <textFieldExpression> <![CDATA[ msg("{0,number,0.00}%", new Double(100d * $V{FreightSumFirstLetterGroup}.doubleValue() / $V{FreightSumReport}.doubleValue())) ]] > </textFieldExpression> </textField> </band> </groupFooter> </group>According to the group expression above, the FirstLetterGroup groups data with the same
first letter of the ShipCountry field. All countries starting with the same letter
will be grouped together. When the first letter changes, the FirstLetterGroup group
will break.
One can see also, from attribute settings, that this group will start in a new column, each time printing its header too, and requires a minimum 200px amount of vertical space in order to prevent starting on a new page by its own. Another interesting element here is the built-in variable FirstLetterGroup_COUNT which
counts the number of records in the group. One could notice the variable's name consisting in the
related group's name followed by the _COUNT suffix.
Other report variables, such as FreightSumFirstLetterGroup and FreightSumReport
were used too, in order to perform statistic calculations.
Now let's jump to the next group in the report. The FirstLetterGroup group contains records
for all countries starting with the same letter. It means that for groups containing more than one country, records
for different countries are mixed together, and this might be not a very good idea. Obviously, a better data grouping
procedure is required. For instance, to create a child group inside the FirstLetterGroup for each distinct
country starting with that letter. So, the information will become more readable and significant than before.
This is what the second group in the report does, the CountryGroup :
<group name="CountryGroup" isReprintHeaderOnEachPage="true"> <groupExpression><![CDATA[$F{ShipCountry}]] ></groupExpression> <groupHeader> <band height="15"> ... <textField evaluationTime="Group" evaluationGroup="CountryGroup" pattern="EEE, MMM d, yyyy"> <reportElement x="170" y="2" width="100" height="11" style="Sans_Bold"/> <textElement textAlignment="Right"/> <textFieldExpression class="java.sql.Timestamp"><![CDATA[$V{DateHighestCountryGroup}]] ></textFieldExpression> </textField> </band> </groupHeader> <groupFooter> <band height="15"> ... <textField> <reportElement mode="Opaque" x="45" y="0" width="25" height="11" backcolor="#c0c0c0" style="Sans_Bold"/> <textElement textAlignment="Right"/> <textFieldExpression class="java.lang.Integer"><![CDATA[$V{CountryGroup_COUNT}]] ></textFieldExpression> </textField> ... <textField pattern="0.00"> <reportElement mode="Opaque" x="170" y="0" width="60" height="11" backcolor="#c0c0c0" style="Sans_Bold"/> <textElement textAlignment="Right"/> <textFieldExpression class="java.lang.Double"><![CDATA[$V{FreightSumCountryGroup}]] ></textFieldExpression> </textField> <textField evaluationTime="Auto"> <reportElement mode="Opaque" x="230" y="0" width="40" height="11" backcolor="#c0c0c0" style="Sans_Bold"/> <textElement textAlignment="Right"/> <textFieldExpression><![CDATA[msg("{0,number,0.00}%", new Double(100d * $V{FreightSumCountryGroup}.doubleValue() / $V{FreightSumFirstLetterGroup}.doubleValue()))]] ></textFieldExpression> </textField> </band> </groupFooter> </group>Here one can observe another built-in counting variable: CountryGroup_COUNT . Again some other report variables
are used to perform various calculations: DateHighestCountryGroup , FreightSumCountryGroup ,
FreightSumFirstLetterGroup . The group header will also be reprinted on each new page.
At this stage we can represent data in a user-friendly form, well separated by countries and country first letters, in a 2-columns layout. What else could be done to separate data better than that? Well, there is one more thing. What if for a given country there are thousands of records? One after one, after one, and so on. Thousands of records looking the same, with nothing special to separate them, increasing a lot the eye's effort... It doesn't sound very good, indeed. This is why the third group in the report is present. It is an empty dummy group that breaks after every 5 records, introducing a supplementary amount of vertical space between the resulting 5-records groups: <group name="BreakGroup"> <groupExpression><![CDATA[new Boolean($V{BreakGroup_COUNT}.intValue() > 5)]] ></groupExpression> <groupHeader> <band height="5"> </band> </groupHeader> <groupFooter> <band height="5"> </band> </groupFooter> </group>Once finished the data grouping work, the report template continues with its usual sections, such as title ,
title , pageHeader , columnHeader , detail , columnFooter ,
pageFooter and summary .
At this moment the sample is ready to be ran. Running the Sample Running the sample requires the Apache Ant library. Make sure that ant is already installed on your system (version 1.5 or later).
In a command prompt/terminal window set the current folder to demo/hsqldb within the JasperReports source project and run the > ant runServer command.
It will start the HSQLDB server shipped with the JasperReports distribution package. Let this terminal running the HSQLDB server.
Open a new command prompt/terminal window and set the current folder to demo/samples/jasper within the JasperReports source project and run the > ant test view command.
It will generate all supported document types containing the sample report in the demo/samples/jasper/build/reports directory.
Then the report will open in the JasperReports internal viewer. |
|||||
|
||||||
top | ||||||
|
||||||
![]() | Exporting to CSV Format Using Report Metadata | Documented by | ||||
|
||||||
| Description / Goal |
| Shows how to export the report to CSV format using metadata associated with report elements at design time, to mark data columns. | |||
| Since |
| 4.0.0 | |||
|
||||||
| [Under Construction] | |||||
|
||||||
top | ||||||
|
||||||
![]() | Conditional Styles | Documented by Sanda Zaharia | ||||
|
||||||
| Description / Goal |
| Shows how to define and use a conditional style in a report template. | |||
| Since |
| 1.2.0 | |||
| Other Samples |
|
|
|||
|
||||||
|
Conditional Styles
In JasperReports styles are the bricks used to generate the report elements appearance. Styles mean anything about fonts, but also mean borders, horizontal and vertical alignment, element transparency or opacity, background and foreground colors, format patterns, text markup information, text rotation, and so on... Almost anything needed to set up a complex, elegant and meaningful element look and feel. However, there are situations when the L&F depends on certain conditions determined only at runtime. The most common example is the necessity to use alternate row colors in a table with a large number of rows, in order to better distinguish between them. When the total number of rows is unknown at report design time, or if the row is used in the detail section, a tool for setting up different backgrounds for the same cell is definitely required. And here come conditional styles to get some help. Conditional styles consist in two elements: a Boolean condition expression and a style. When the
condition evaluates to true , the corresponding style is applied. In the
Jasper sample one can see a conditional style definition:
<style name="Sans_Normal" isDefault="true" fontName="DejaVu Sans" fontSize="8" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false"/> <style name="OrderIdStyle" style="Sans_Normal"> <conditionalStyle> <conditionExpression><![CDATA[new Boolean($F{OrderID}.intValue() % 10 == 0)]] ></conditionExpression> <style forecolor="#ff0000" isBold="true"/> </conditionalStyle> </style>The OrderIdStyle defined above derives from the Sans_Normal parent style.
Usually, elements with OrderIdStyle will have the default black forecolor and a normal
font weight. But when the condition expression evaluates to true (this happens each time
the OrderID field value is a multiple of 10) the element's style changes: the forecolor
becomes red and the font gets bold.
Therefore, when applied, a conditional style will override the properties of its parent style. A style definition may contain many conditional styles, any of them inheriting from the parent style. In this case, all conditions that evaluate to true will append their own style properties
to the existing style, in the same order they were defined in the report (the second style will be
appended to the first one, and so on). If more than one conditional style affect the same style property,
the property value will be done by the first conditional style in the styles sequence which evaluates its
condition to true .
Here is a more elaborate example: <style name="alternateStyle" fontName="Arial" forecolor="red"> <conditionalStyle> <conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue() % 2 == 0)]] ></conditionExpression> <style forecolor="blue"/> </conditionalStyle> <conditionalStyle> <conditionExpression><![CDATA[new Boolean($F{AMOUNT}.intValue() > 10000)]] ></conditionExpression> <style isBold="true"/> </conditionalStyle> <conditionalStyle> <conditionExpression><![CDATA[new Boolean($F{AMOUNT}.intValue() > 20000)]] ></conditionExpression> <style isBold="false" isItalic="true"/> </conditionalStyle> </style>One can see above that on each even row the element forecolor becomes blue. More than that, if the AMOUNT
field value is greater than 10,000, the second conditional style evaluates to true , and the element
displays in bold font (this doesn't affect the red color or blue color set by the first conditional style, because the
forecolor and font weight properties do not interfere). Further, if the AMOUNT field value is greater than
20,000, the font style becomes italic, without affecting the font color. But because any value greater than
20,000 is also greater than 10,000, then the isBold="false" font weight is no more applied, because
both conditions >10,000 and >20,000 evaluate to true and isBold="true"
style was appended first.
Note:
Conditional styles combined with some specific report built-in variables can be used to generate alternate row colors for the detail section. As known, the detail section is repetitive and contains common layout information for records in the dataset. For each record in the dataset, a detail section filling process is called at fill time. Being related to records, one of the most common layouts used for the detail section is the table row layout. And like in any other table, alternate row colors might be needed. To solve this problem, two things are necessary:
<style name="alternateStyle" fontName="Arial" backcolor="yellow"> <conditionalStyle> <conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue() % 2 == 0)]] ></conditionExpression> <style backcolor="blue"/> </conditionalStyle> </style>Here, the odd rows will be rendered with yellow background color, and the even ones will be rendered in blue. |
|||||
|
|
© 2001-2010 Jaspersoft Corporation www.jaspersoft.com |