Creating a table with JasperReports library

In this tutorial, we show how to display a table in a report created with JasperReports library.

JasperReports is a open-source reporting library. It can create reports in various formats including PDF, HTML, XLS, or CSV. JasperReports creates page-oriented, ready-to-print documents in a simple and flexible manner.

The following application loads data from a bean collection data source and creates a report from it with JasperReports library. The report is a PDF file. The data is shown in a table format.

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── bean
    │   │           │   └── Order.java
    │   │           └── main
    │   │               ├── CommandLineRunner.java
    │   │               └── JasperTable2.java
    │   └── resources
    │       └── table.xml
    └── test
        └── java

This is the project structure.

Order.java
package com.zetcode.bean;

import java.math.BigDecimal;

public class Order {
    
    private String item;
    private BigDecimal unitPrice;
    private int quantity;

    public Order(String item, BigDecimal unitPrice, int quantity) {
        this.item = item;
        this.unitPrice = unitPrice;
        this.quantity = quantity;
    }
    
    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public BigDecimal getUnitPrice() {
        return unitPrice;
    }

    public void setUnitPrice(BigDecimal unitPrice) {
        this.unitPrice = unitPrice;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
}

This is Order bean class. It contains item name, unit price, and item quantity.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zetcode</groupId>
    <artifactId>JasperTable2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>
        
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>6.4.0</version>
        </dependency>
        
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports-fonts</artifactId>
            <version>6.0.0</version>
        </dependency>
               
    </dependencies>    
    
</project>

The Maven pom.xml file contains these dependencies: jasperreports and jasperreports-fonts. The jasperreports dependency is the JasperReports library; the jasperreports-fonts is needed for displaying bold fonts in PDF report.

table.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
   
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports
                                    http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
              name="report6" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail"
              columnWidth="555" leftMargin="20" rightMargin="20"
              topMargin="20" bottomMargin="20">
    
<style name="TableHeader" vAlign="Middle" hAlign="Center" isBold="true"/>
<style name="TableCell"  hAlign="Center" vAlign="Middle" /> 
<style name="TableFooter" hAlign="Right" vAlign="Middle" />   

<style name="Table">
    <box>
        <pen lineWidth="0.5"/>
    </box>
</style>         

<subDataset name="dataset1">
    <field name="item" class="java.lang.String"/>
    <field name="unitPrice" class="java.math.BigDecimal"/>
    <field name="quantity" class="java.lang.Integer"/> 
    
    <variable name="UnitTotalPrice" class="java.math.BigDecimal">
        <variableExpression><![CDATA[$F{unitPrice}.multiply(new BigDecimal($F{quantity}))]]></variableExpression>
    </variable>           
    
    <variable name="TotalPrice" resetType="Report" class="java.math.BigDecimal" calculation="Sum">
        <variableExpression><![CDATA[$V{UnitTotalPrice}]]></variableExpression>
    </variable>          
    
</subDataset>  

<parameter name="datasource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>

<detail>

<band height="250">
    
<componentElement>
<reportElement style="Table" x="0" y="10" width="555" height="150">
    <property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.HorizontalRowLayout"/>
</reportElement>
<c:table xmlns:c="http://jasperreports.sourceforge.net/jasperreports/components" 
            xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">

    <datasetRun subDataset="dataset1">
        <dataSourceExpression><![CDATA[$P{datasource}]]></dataSourceExpression>
    </datasetRun>
                            
    <c:column width="60">
        <c:columnHeader height="30">
            <box>
                <pen lineColor="#000000"/>
                <bottomPen lineWidth="0.5"/>
            </box>
            <staticText>
                <reportElement x="0" y="0" width="60" height="30" style="TableHeader"/>
                <text><![CDATA[Item]]></text>
            </staticText>
        </c:columnHeader>
        <c:detailCell height="15">
            <box>
                <bottomPen lineWidth="0.5"/>
            </box>
            <textField isStretchWithOverflow="true">
                <reportElement x="0" y="0" width="60" height="15" style="TableCell"/>
                <textFieldExpression><![CDATA[$F{item}]]></textFieldExpression>
            </textField>
        </c:detailCell>
    </c:column>
    
    <c:column width="100">
        <c:columnHeader height="30">
            <box>
                <pen lineColor="#000000"/>
                <leftPen lineWidth="0.5"/>
                <bottomPen lineWidth="0.5"/>
            </box>
            <staticText>
                <reportElement x="0" y="0" width="90" height="30" style="TableHeader"/>
                <text><![CDATA[UnitPrice]]></text>
            </staticText>
        </c:columnHeader>
        <c:detailCell height="15">
            <box>
                <leftPen lineWidth="0.5"/>
                <bottomPen lineWidth="0.5"/>
            </box>
            <textField>
                <reportElement x="0" y="0" width="90" height="15" style="TableCell"/>
                <textFieldExpression><![CDATA[$F{unitPrice}]]></textFieldExpression>
            </textField>
        </c:detailCell>
    </c:column>
    
    <c:column width="100" >
        <c:columnHeader height="30">
            <box>
                <pen lineColor="#000000"/>
                <leftPen lineWidth="0.5"/>
                <bottomPen lineWidth="0.5"/>
            </box>
            <staticText>
                <reportElement x="0" y="0" width="90" height="30" style="TableHeader"/>
                <text><![CDATA[Quantity]]></text>
            </staticText>
        </c:columnHeader>
        <c:detailCell height="15">
            <box rightPadding="5">
                <leftPen lineWidth="0.5"/>
                <bottomPen lineWidth="0.5"/>
            </box>
            <textField>
                <reportElement x="0" y="0" width="90" height="15"/>
                <textElement textAlignment="Right" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{quantity}]]></textFieldExpression>
            </textField>
        </c:detailCell>
    </c:column>
    
    <c:column width="100" >
        <c:columnHeader height="30">
            <box>
                <pen lineColor="#000000"/>
                <leftPen lineWidth="0.5"/>
                <bottomPen lineWidth="0.5"/>
            </box>
            <staticText>
                <reportElement x="0" y="0" width="90" height="30" style="TableHeader"/>
                <text><![CDATA[Total price]]></text>
            </staticText>
        </c:columnHeader>
        <c:detailCell height="15">
            <box rightPadding="5">
                <leftPen lineWidth="0.5"/>
                <bottomPen lineWidth="0.5"/>
            </box>
            <textField>
                <reportElement x="0" y="0" width="90" height="15"/>
                <textElement textAlignment="Right" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$V{UnitTotalPrice}]]></textFieldExpression>
            </textField>
        </c:detailCell>
        <c:columnFooter style="TableFooter" height="15">
            <box>
                <pen lineColor="#000000"/>
                <topPen lineWidth="0.5"/>
            </box>
            <textField evaluationTime="Report">
                <reportElement x="0" y="0" width="90" height="15" style="TableFooter"/>
                <textFieldExpression><![CDATA[$V{TotalPrice}]]></textFieldExpression>
            </textField>
        </c:columnFooter>                        
    </c:column>                    

</c:table>
</componentElement>
</band>
</detail>
</jasperReport>

This is the report template file. The template contains only the detail band. In a detail band, each element is repeated for every record provided by the data source.

<style name="TableHeader" vAlign="Middle" hAlign="Center" isBold="true"/>
<style name="TableCell"  hAlign="Center" vAlign="Middle" /> 
<style name="TableFooter" hAlign="Right" vAlign="Middle" />  

These three styles are used for table header, table footer, and table cell.

<style name="Table">
    <box>
        <pen lineWidth="0.5"/>
    </box>
</style>  

This style creates a border around the table.

<subDataset name="dataset1">
    <field name="item" class="java.lang.String"/>
    <field name="unitPrice" class="java.math.BigDecimal"/>
    <field name="quantity" class="java.lang.Integer"/> 
    
    <variable name="UnitTotalPrice" class="java.math.BigDecimal">
        <variableExpression><![CDATA[$F{unitPrice}.multiply(new BigDecimal($F{quantity}))]]></variableExpression>
    </variable>           
    
    <variable name="TotalPrice" resetType="Report" class="java.math.BigDecimal" calculation="Sum">
        <variableExpression><![CDATA[$V{UnitTotalPrice}]]></variableExpression>
    </variable>          
    
</subDataset> 

A table will read data from the subDataset element. Inside the element, we have three fields and two variables. The fields are mapped to the elements of the data source. In our case, fields are mapped to the attributes of the beans. (We are using JRBeanCollectionDataSource.) The variables perform calculations on the fields. They calculate the unit price and the total price in the table.

<parameter name="datasource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/> 

The parameter defines a datasource. JRBeanCollectionDataSource is a collection of Java class beans. The parameter is passed to the report during the filling phase.

<c:table xmlns:c="http://jasperreports.sourceforge.net/jasperreports/components" 
            xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">

Table is a component that is specified in the JasperReports components schema.

<datasetRun subDataset="dataset1">
    <dataSourceExpression><![CDATA[$P{datasource}]]></dataSourceExpression>
</datasetRun>

The datasetRun creates an instance of the dataset. In the dataSourceExpression, we pass the datasource parameter.

<c:column width="100">
    <c:columnHeader height="30">
        <box>
            <pen lineColor="#000000"/>
            <leftPen lineWidth="0.5"/>
            <bottomPen lineWidth="0.5"/>
        </box>
        <staticText>
            <reportElement x="0" y="0" width="90" height="30" style="TableHeader"/>
            <text><![CDATA[UnitPrice]]></text>
        </staticText>
    </c:columnHeader>
    <c:detailCell height="15">
        <box>
            <leftPen lineWidth="0.5"/>
            <bottomPen lineWidth="0.5"/>
        </box>
        <textField>
            <reportElement x="0" y="0" width="90" height="15" style="TableCell"/>
            <textFieldExpression><![CDATA[$F{unitPrice}]]></textFieldExpression>
        </textField>
    </c:detailCell>
</c:column>

There are four columns in the table. Each column is defined separately. In this column, we have a column header and a column cell. The header contains the column label and the cell contains the unit price, retrieved from the unitPrice field. The field is referenced with the $F{} syntax. The box elements are used to create lines.

<c:columnFooter style="TableFooter" height="15">
    <box>
        <pen lineColor="#000000"/>
        <topPen lineWidth="0.5"/>
    </box>
    <textField evaluationTime="Report">
        <reportElement x="0" y="0" width="90" height="15" style="TableFooter"/>
        <textFieldExpression><![CDATA[$V{TotalPrice}]]></textFieldExpression>
    </textField>
</c:columnFooter>

In the last fourth column, we have a column footer. It contains the total price of all items of the order. We refer to the variable with the $V{} syntax.

JasperTable2.java
package com.zetcode.main;

import com.zetcode.bean.Order;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperTable2 {

    public void start() throws JRException {

        String xmlFile = "src/main/resources/table.xml";
        JasperReport jreport = JasperCompileManager.compileReport(xmlFile);

        ArrayList<Order> orders = new ArrayList<>();
        
        orders.add(new Order("Item 1", new BigDecimal("5.4"), 4));
        orders.add(new Order("Item 2", new BigDecimal("2.3"), 3));
        orders.add(new Order("Item 3", new BigDecimal("1.5"), 8));
        orders.add(new Order("Item 4", new BigDecimal("4.0"), 2));

        JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(orders);

        Map params = new HashMap();
        params.put("datasource", ds);

        JasperPrint jprint = JasperFillManager.fillReport(jreport,
                params, new JREmptyDataSource());
        
        JasperExportManager.exportReportToPdfFile(jprint,
                "src/main/resources/table.pdf");        
    }
}

The JasperTable2 creates a JasperPrint file from the data source. JasperPrint represents a page-oriented document that can be viewed, printed, or exported to other formats. In our case, it is going to be viewed with JRViewer.

String xmlFile = "src/main/resources/table.xml";
JasperReport jreport = JasperCompileManager.compileReport(xmlFile);

We compile the XML template file into a JasperReport. JasperReport is a compiled template ready to be filled with data.

ArrayList<Order> orders = new ArrayList<>();

orders.add(new Order("Item 1", new BigDecimal("5.4"), 4));
orders.add(new Order("Item 2", new BigDecimal("2.3"), 3));
orders.add(new Order("Item 3", new BigDecimal("1.5"), 8));
orders.add(new Order("Item 4", new BigDecimal("4.0"), 2));

An ArrayList of orders is our data.

JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(orders);

JRBeanCollectionDataSource is a data source implementation that wraps a collection of Java bean objects. We put four Order beans into the data source.

Map params = new HashMap();
params.put("datasource", ds);

We place the data source into the parameters map and pass the map into the JasperFillManager.fillReport() method.

JasperPrint jprint = JasperFillManager.fillReport(jreport,
        params, new JREmptyDataSource());

A JasperPrint object is created; an object that can be viewed, printed, or exported to other formats.

JasperExportManager.exportReportToPdfFile(jprint,
        "src/main/resources/table.pdf");    

The JasperExportManager.exportReportToPdfFile() method exports the JasperPrint into a PDF file.

CommandLineRunner.java
package com.zetcode.main;

public class CommandLineRunner {

    public static void main(String[] args) throws Exception {

        JasperTable2 app = new JasperTable2();
        app.start();
    }
}

The CommandLineRunner sets up the application.

Table
Figure: Table

This is the table object displaying data in a PDF file.

In this tutorial, we have created a data table in a report with JasperReports. The report was in a PDF format. You might also be interested in these related tutorials: JasperReports scriptlets, Creating a report with JasperReports API, Creating a report from CSV with JasperReports, and Java tutorial.