Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create multiple charts of same type but with different dataseries using JRBeanCollectionDatasource in Jasperreports

I have to create multiple XY-line charts with different dataset using same chart report template and I also have to use JRBeanCollectionDatasource for it.

Requirements:

1) Should be done using JRBeanCollectionDatasource.

2) Have to use the same chart report template to create multiple charts.

3) Number of charts are not fixed (Here I have problem giving names to Report Parameter in java). Because in ReportParametersMap, they can only have unique key name .

Java:

Coordinates.java

private Number series;
private Number xCoordinate;
private Number yCoordinate;
//Getters & Setters

GenerateReport.java

I am working with Report Book and each report template of the report book is considered as a sub-report. So I am passing XYChartDataSource(java.util.List) to master report book and I would map this parameter with the subreport by using new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{XYChartDataSource}) as a Datasource Expression.

and in Subreport, I have created a parameter XYChartDataSource(java.util.List) and created fields (series,xCoordinate,yCoordinate) in MainDataset ( used in chart)

List<List<Coordinates>> allchartData = new ArrayList<>();
List<Coordinates> chartData = new ArrayList<>();

chartData.add(new Coordinates(2.08, xCoordinate, yCoordinate));
chartData.add(new Coordinates(2.08, xCoordinate, yCoordinate));
chartData.add(new Coordinates(2.08, xCoordinate, yCoordinate));
allchartData.add(chartData);
.
.
.
chartData.add(new Coordinates(2.12, xCoordinate, yCoordinate));
chartData.add(new Coordinates(2.12, xCoordinate, yCoordinate));
chartData.add(new Coordinates(2.12, xCoordinate, yCoordinate));
allchartData.add(chartData);
.
.
.


for (int i = 0; i < baselineChartData.size(); i++) {
            parameters.put("XYChartDataSource", allchartData.get(i));
    }

main_report_book.jrxml

<parameter name="XYChartDataSource" class="java.util.List"/>

        <part uuid="5e668430-9acd-4835-be21-f4e2902ce33d">
            <p:subreportPart xmlns:p="http://jasperreports.sourceforge.net/jasperreports/parts" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/parts http://jasperreports.sourceforge.net/xsd/parts.xsd">
                <subreportParameter name="REPORT_DATA_SOURCE">
                    <subreportParameterExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{XYChartDataSource})]]></subreportParameterExpression>
                </subreportParameter>
                <subreportExpression><![CDATA[$P{SUBREPORT_DIR}+"/sub_chart.jasper"]]></subreportExpression>
            </p:subreportPart>
        </part>

sub_chart.jrxml

<parameter name="XYChartDataSource" class="java.util.List"/>
<field name="xCoordinate" class="java.lang.Double"/>
<field name="yCoordinate" class="java.lang.Double"/>
<field name="series" class="java.lang.Double"/>
    <summary>
        <band height="405">
            <xyLineChart>
                <chart evaluationTime="Report" bookmarkLevel="1">
                    <reportElement x="30" y="98" width="525" height="230" uuid="627d87d6-b675-409c-accb-b2bb3ffb9c80">
                        <property name="net.sf.jasperreports.chart.domain.axis.tick.interval" value="1"/>
                    </reportElement>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend position="Right"/>
                </chart>
                <xyDataset>
                    <xySeries autoSort="true">
                        <seriesExpression><![CDATA[$F{series}]]></seriesExpression>
                        <xValueExpression><![CDATA[$F{xCoordinate}]]></xValueExpression>
                        <yValueExpression><![CDATA[$F{yCoordinate}]]></yValueExpression>

                    </xySeries>
                </xyDataset>
                <linePlot isShowShapes="false">
                    <plot/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </linePlot>
            </xyLineChart>






            </textField>
        </band>
    </summary>

Current Output: only one chart is being printed, using the regular method.

enter image description here

Expected Output:

Here I am showing two charts(could be more in actual output) , which needs to be generated from same report template in the SAME PDF REPORT:

chart1

enter image description here

chart2

enter image description here

like image 684
Dhruvil Thaker Avatar asked Sep 13 '16 08:09

Dhruvil Thaker


1 Answers

You problem is here:

for (int i = 0; i < baselineChartData.size(); i++) {
        parameters.put("XYChartDataSource", allchartData.get(i));
}

Your parameter "XYChartDataSource" will contain last entry in your List, you replace each time in loop see Map.put(K key,V value))

What we need instead is the whole list

parameters.put("XYChartDataSource", allchartData);

However now we can't access directly the List<Coordinates>

On solution to not change your current subreport is to insert another subreport in the middle which will iterate your List<List<Coordinates>> in detail band.

The structure will be

  1. Pass List<List<Coordinates>> allchartData as datasource to this new subreport (sub_charts.jrxml)

  2. Define the field _THIS which is List<Coordinates> in subreport (hence it's iterating your List<List<Coordinates>>)

  3. In detail band include current sub_chart.jrxml and pass $F{_THIS} as datasource

sub_charts.jrxml

<?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="sub_charts" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="bc8c76ba-0b85-4522-bf67-4c62ae87202b">
    <field name="_THIS" class="java.util.List">
        <fieldDescription>_THIS</fieldDescription>
    </field>
    <detail>
        <band height="63" splitType="Stretch">
            <subreport>
                <reportElement x="0" y="0" width="550" height="60" uuid="b0e761bf-fe02-4a0a-bafb-32d6831b7a13"/>
                 <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{_THIS})]]></dataSourceExpression>
                 <subreportExpression><![CDATA[$P{SUBREPORT_DIR}+"/sub_chart.jasper"]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

Remember to call this new subreport in your main_report_book.jrxml.

<subreportExpression><![CDATA[$P{SUBREPORT_DIR}+"/sub_charts.jasper"]]></subreportExpression>

The OP Dhruvil Thaker did this great graphical representation of this answer.

graphical representation

like image 59
Petter Friberg Avatar answered Nov 12 '22 01:11

Petter Friberg