Search code examples
javajasper-reports

Why do jasper reports generate multiple tables instead of one?


I want to use jasperreport to generate pdf file with table in it, my java code is as follows:

JasperReport report = JasperCompileManager.compileReport("src/main/resources/report1.jrxml");
Map<String,Object> params = new HashMap<String,Object>();
List<Info> infos = new ArrayList<Info>();
for(int i=0;i<10;i++) {
    Info info = new Info();
    info.setAccountCode("abc");
    info.setAccountName("test");
    infos.add(info);                
}

JRBeanCollectionDataSource beans = new JRBeanCollectionDataSource(infos);
params.put("tableSource", infos);

JasperPrint print = JasperFillManager.fillReport(report , params, beans);
JasperExportManager.exportReportToPdfFile(print,"jasper.pdf");

in jrxml file, I created a parameter tableSource (its type is List), added two fields accountName and accountCode, added a 'Table' report element, also created

new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{tableSource})

in table properties, the full jrxml file is :

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report1" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="6fa4b189-7e18-456b-9307-710a8d6972c1">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="20"/>
    <style name="table">
        <box>
            <pen lineWidth="1.0" lineColor="#000000"/>
        </box>
    </style>
    <style name="table_TH" mode="Opaque" backcolor="#F0F8FF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="table_CH" mode="Opaque" backcolor="#BFE1FF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="table_TD" mode="Opaque" backcolor="#FFFFFF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="table 1">
        <box>
            <pen lineWidth="1.0" lineColor="#000000"/>
        </box>
    </style>
    <style name="table 1_TH" mode="Opaque" backcolor="#F0F8FF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="table 1_CH" mode="Opaque" backcolor="#BFE1FF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="table 1_TD" mode="Opaque" backcolor="#FFFFFF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <subDataset name="Table Dataset 1" uuid="6d5cf195-8b52-4dfe-9f53-9e3eb5be5db3">
        <field name="accountCode" class="java.lang.String"/>
        <field name="accountName" class="java.lang.String"/>
    </subDataset>
    <parameter name="tableSource" class="java.util.List"/>
    <field name="accountCode" class="java.lang.String"/>
    <background>
        <band splitType="Stretch"/>
    </background>
    <title>
        <band height="79" splitType="Stretch"/>
    </title>
    <pageHeader>
        <band height="35" splitType="Stretch"/>
    </pageHeader>
    <columnHeader>
        <band height="61" splitType="Stretch"/>
    </columnHeader>
    <detail>
        <band height="125" splitType="Stretch">
            <componentElement>
                <reportElement key="table 1" style="table 1" x="108" y="30" width="450" height="50" uuid="c7628262-8e54-4c62-b977-175f6aea984e"/>
                <jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
                    <datasetRun subDataset="Table Dataset 1" uuid="8beea930-93ae-4fa8-826b-cebfebef3a86">
                        <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{tableSource})]]></dataSourceExpression>
                    </datasetRun>
                    <jr:column width="90" uuid="0155325f-f82b-4b89-849c-dff724c771a9">
                        <jr:tableHeader style="table 1_TH" height="30" rowSpan="1">
                            <staticText>
                                <reportElement x="0" y="0" width="90" height="30" uuid="ea43a2ac-624e-4c44-a53c-60f79a2a4cd3"/>
                                <text><![CDATA[Account Code]]></text>
                            </staticText>
                        </jr:tableHeader>
                        <jr:detailCell style="table 1_TD" height="30" rowSpan="1">
                            <textField isStretchWithOverflow="true">
                                <reportElement x="0" y="0" width="90" height="20" uuid="28ac521c-37bf-4cfc-80ad-35a380e32d9a"/>
                                <textElement>
                                    <font fontName="Arial" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
                                </textElement>
                                <textFieldExpression><![CDATA[$F{accountCode}]]></textFieldExpression>
                            </textField>
                        </jr:detailCell>
                    </jr:column>
                    <jr:column width="90" uuid="9249d41a-f7af-4abf-9163-0a15d0a621a8">
                        <jr:tableHeader style="table 1_TH" height="30" rowSpan="1">
                            <staticText>
                                <reportElement x="0" y="0" width="90" height="30" uuid="81274afc-cb28-4251-8e9d-8ffe2466d2dc"/>
                                <text><![CDATA[Account Name]]></text>
                            </staticText>
                        </jr:tableHeader>
                        <jr:detailCell style="table 1_TD" height="30" rowSpan="1">
                            <textField isStretchWithOverflow="true">
                                <reportElement x="0" y="0" width="90" height="20" uuid="5876bb0e-cc9d-4d34-a2ba-483016846752"/>
                                <textElement>
                                    <font fontName="Arial" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
                                </textElement>
                                <textFieldExpression><![CDATA[$F{accountName}]]></textFieldExpression>
                            </textField>
                        </jr:detailCell>
                    </jr:column>
                </jr:table>
            </componentElement>
        </band>
    </detail>
    <columnFooter>
        <band height="45" splitType="Stretch"/>
    </columnFooter>
    <pageFooter>
        <band height="54" splitType="Stretch"/>
    </pageFooter>
    <summary>
        <band height="42" splitType="Stretch"/>
    </summary>
</jasperReport>

I expect it generate one table like next :

Account Code  Account Name
abc           test
abc           test

However, the real result is there are 2 tables generated like following :

Account Code  Account Name
abc           test
abc           test

Account Code  Account Name
abc           test
abc           test

why there are two same table generated?

I'm using iReport 5.6.0, jasperreport 6.2.2


Solution

  • You should pass a JREmptyDataSource with 1 record to the JasperFillManager

    JasperPrint print = JasperFillManager.fillReport(report , params, new JREmptyDataSource(1));
    

    why?

    Jasper Reports iterate's the detail band on the datasource you pass to the JasperFillManager, hence it will create as many detail bands as records in your JRBeanCollectionDataSource beans. In your case you do not want this since you are passing this datasource as a parameter to be used by the <jr:table> component. Your setup is to display detail band once (1 record) with a jr:table that iterates on a datasource passed as parameter and the easiest way to get 1 record is a new JREmptyDataSource(1)