Hot questions for Using JasperReports in charts

Question:

I have this ChartField class

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
public class ChartField {

    private int x;
    private int y;

}

and MyChart class have a List of ChartField

import java.util.List;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class MyChart {

    private List<ChartField> chartFields;

}

This is the code how i generate the report.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.view.JasperViewer;

public class TestReport {

    public static void main(String[] args) {

        String source = "reports/test_report.jasper";

        try {

            List<MyChart> listMyCharts = new ArrayList<>();
            {
                MyChart myChart = new MyChart();
                List<ChartField> chartFields = new ArrayList<>();
                myChart.setChartFields(chartFields);
                {
                    chartFields.add(new ChartField(2, 3));
                    chartFields.add(new ChartField(5, 6));
                    chartFields.add(new ChartField(7, 9));
                    chartFields.add(new ChartField(11, 12));
                    chartFields.add(new ChartField(12, 16));
                    chartFields.add(new ChartField(17, 22));
                }
                listMyCharts.add(myChart);
            }
            {
                MyChart myChart = new MyChart();
                List<ChartField> chartFields = new ArrayList<>();
                myChart.setChartFields(chartFields);
                {
                    chartFields.add(new ChartField(5, 4));
                    chartFields.add(new ChartField(7, 8));
                    chartFields.add(new ChartField(12, 5));
                    chartFields.add(new ChartField(15, 18));
                    chartFields.add(new ChartField(18, 21));
                    chartFields.add(new ChartField(34, 55));
                }
                listMyCharts.add(myChart);
            }

            JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(listMyCharts);

            Map<String, Object> map = new HashMap<>();
            JasperPrint jp = JasperFillManager.fillReport(source, map, dataSource);
            JasperViewer.viewReport(jp);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

This is the design of test_report.jrxml as you can see i put table and chart in detail band. My expectation is the detail band can repeat my listMyCharts object (see TestReport class)

JRDatasource expression of table is

new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{chartFields})

as you can see i use the same JRDatasource that tabel use in this chart.

This is the test_report.jrxml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.2.0.final using JasperReports Library version 6.2.0  -->
<!-- 2016-03-05T12:51:11 -->
<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="master_report_template" 
    pageWidth="595" pageHeight="842" columnWidth="555" 
    leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" 
    uuid="a488f074-1b9d-4cc7-95d4-51323412d4b2">

    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
    <style name="Table_TH" mode="Opaque" backcolor="#F0F8FF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
            <topPen lineWidth="0.5" lineColor="#000000"/>
            <leftPen lineWidth="0.5" lineColor="#000000"/>
            <bottomPen lineWidth="0.5" lineColor="#000000"/>
            <rightPen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="Table_CH" mode="Opaque" backcolor="#BFE1FF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
            <topPen lineWidth="0.5" lineColor="#000000"/>
            <leftPen lineWidth="0.5" lineColor="#000000"/>
            <bottomPen lineWidth="0.5" lineColor="#000000"/>
            <rightPen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="Table_TD" mode="Opaque" backcolor="#FFFFFF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
            <topPen lineWidth="0.5" lineColor="#000000"/>
            <leftPen lineWidth="0.5" lineColor="#000000"/>
            <bottomPen lineWidth="0.5" lineColor="#000000"/>
            <rightPen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <subDataset name="Dataset1" uuid="8c5a7d5e-8685-4dae-b33b-b816e12907c4">
        <queryString>
            <![CDATA[]]>
        </queryString>
        <field name="x" class="java.lang.Integer"/>
        <field name="y" class="java.lang.Integer"/>
    </subDataset>
    <queryString>
        <![CDATA[]]>
    </queryString>
    <field name="chartFields" class="java.util.List"/>
    <background>
        <band splitType="Stretch"/>
    </background>
    <detail>
        <band height="202" splitType="Stretch">
            <property name="com.jaspersoft.studio.unit.height" value="pixel"/>
            <componentElement>
                <reportElement x="10" y="10" width="220" height="76" uuid="41604712-0359-4058-8a74-30677eb774df">
                    <property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.VerticalRowLayout"/>
                </reportElement>
                <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="Dataset1" uuid="6ad6bedb-dae4-4eb4-9f4e-57a0c04e73d5">
                        <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{chartFields})]]></dataSourceExpression>
                    </datasetRun>
                    <jr:column width="100" uuid="6a31d692-e928-497f-a168-a31c12620680">
                        <property name="com.jaspersoft.studio.components.table.model.column.name" value="Column1"/>
                        <jr:columnHeader style="Table_CH" height="30" rowSpan="1">
                            <staticText>
                                <reportElement x="0" y="0" width="100" height="30" uuid="897b63dd-e6ee-4329-9382-495c9b9a4286"/>
                                <textElement>
                                    <font size="14"/>
                                </textElement>
                                <text><![CDATA[x]]></text>
                            </staticText>
                        </jr:columnHeader>
                        <jr:detailCell style="Table_TD" height="30">
                            <textField>
                                <reportElement x="0" y="0" width="100" height="30" uuid="f6b7583f-e131-4ce4-bc8c-fdc83f4515dc"/>
                                <textElement>
                                    <font size="14"/>
                                </textElement>
                                <textFieldExpression><![CDATA[$F{x}]]></textFieldExpression>
                            </textField>
                        </jr:detailCell>
                    </jr:column>
                    <jr:column width="100" uuid="19cfc888-0988-42a7-a729-dd673a6c078d">
                        <property name="com.jaspersoft.studio.components.table.model.column.name" value="Column2"/>
                        <jr:columnHeader style="Table_CH" height="30" rowSpan="1">
                            <staticText>
                                <reportElement x="0" y="0" width="100" height="30" uuid="08a3e523-4c8b-4374-ab60-16c3cc577060"/>
                                <textElement>
                                    <font size="14"/>
                                </textElement>
                                <text><![CDATA[y]]></text>
                            </staticText>
                        </jr:columnHeader>
                        <jr:detailCell style="Table_TD" height="30">
                            <textField>
                                <reportElement x="0" y="0" width="100" height="30" uuid="99c2e10d-1cf3-4975-99b9-b1f1f6c55571"/>
                                <textElement>
                                    <font size="14"/>
                                </textElement>
                                <textFieldExpression><![CDATA[$F{y}]]></textFieldExpression>
                            </textField>
                        </jr:detailCell>
                    </jr:column>
                </jr:table>
            </componentElement>
            <xyLineChart>
                <chart evaluationTime="Report">
                    <reportElement x="260" y="0" width="294" height="200" uuid="19cc8a02-7aa3-4518-96f8-71a636b626cf"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <xyDataset>
                    <dataset>
                        <datasetRun subDataset="Dataset1" uuid="32ba4e38-1819-47f9-bbd6-4a4381e367a5">
                            <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{chartFields})]]></dataSourceExpression>
                        </datasetRun>
                    </dataset>
                    <xySeries autoSort="true">
                        <seriesExpression><![CDATA["SERIES 1"]]></seriesExpression>
                        <xValueExpression><![CDATA[$F{x}]]></xValueExpression>
                        <yValueExpression><![CDATA[$F{y}]]></yValueExpression>
                    </xySeries>
                </xyDataset>
                <linePlot>
                    <plot/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </linePlot>
            </xyLineChart>
        </band>
    </detail>
</jasperReport>

This is the result of the report that i successfully generated. You can see the table is repeated as i want.

My question is

But why the heck the chart does not follow the table instead used the last data?


Answer:

On the chart tag you are using evaluationTime="Report" this means

Report: A constant specifying that an expression should be evaluated at the end of the filling process.

At the end of filling process the $F{chartFields} is the last record.

Solution

Replace it with evaluationTime="Now" or remove it (this is default)

Now A constant specifying that an expression should be evaluated at the exact moment in the filling process when it is encountered.

Question:

Following the answer from here : How to create multiple charts of same type but with different dataseries using JRBeanCollectionDatasource in Jasperreports

I managed to at least create charts with my nested list. My java object :

public class PoolUserLoginsVO {
    private int userLogins;
    private String poolId;
    private Date date;

    //constructor + getter/setters

userLogins is the y coordinate value, the chart is a timeseries chart so the x coordinate is the date. poolId is the series in which the coordinates belong to.

I get the list of values I need for each series, and since there are multiple series, I have a list of a list that I pass to the parameter map to Jasper Reports.

My Jasper Reports :

Main jasper (the whole document is quite long so only the relevant part) :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.10.0.final using JasperReports Library version 6.10.0-unknown  -->
<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="test" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="fbaeab5e-6793-456e-9567-e0c5af982904">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
    <parameter name="poolLogins" class="java.util.List"/>
    <queryString>
        <![CDATA[]]>
    </queryString>
    <background>
        <band splitType="Stretch"/>
    </background>
    <detail>
        <band height="223">
            <subreport>
                <reportElement x="0" y="0" width="550" height="200" uuid="9f8a2d4a-1d90-4f88-a08c-1ea2604360c5"/>
                <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{poolLogins})]]></dataSourceExpression>
                <subreportExpression><![CDATA["sub_charts.jasper"]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

$P{poolLogins} is a List<List<PoolUserLoginsVO>.

sub_charts.jasper :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.10.0.final using JasperReports Library version 6.10.0-unknown  -->
<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><![CDATA[_THIS]]></fieldDescription>
    </field>
    <detail>
        <band height="237" splitType="Stretch">
            <subreport>
                <reportElement x="0" y="20" width="540" height="200" uuid="1ec1f733-ffee-46f3-859c-f774e5277d19"/>
                <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{_THIS})]]></dataSourceExpression>
                <subreportExpression><![CDATA["sub_chart.jasper"]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

sub_chart.jasper :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.10.0.final using JasperReports Library version 6.10.0-unknown  -->
<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_chart" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="4ce41625-c60b-4759-acbe-5fe12a013fb2">
    <queryString>
        <![CDATA[]]>
    </queryString>
    <field name="userLogins" class="java.lang.Integer"/>
    <field name="poolId" class="java.lang.String"/>
    <field name="date" class="java.util.Date"/>
    <background>
        <band splitType="Stretch"/>
    </background>
    <detail>
        <band height="210" splitType="Stretch">
            <timeSeriesChart>
                <chart evaluationTime="Report">
                    <reportElement x="0" y="20" width="540" height="180" uuid="874eee5e-1e71-4870-906b-ef71ef91d274"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <timeSeriesDataset>
                    <timeSeries>
                        <seriesExpression><![CDATA[$F{poolId}]]></seriesExpression>
                        <timePeriodExpression><![CDATA[$F{date}]]></timePeriodExpression>
                        <valueExpression><![CDATA[$F{userLogins}.intValue()]]></valueExpression>
                    </timeSeries>
                </timeSeriesDataset>
                <timeSeriesPlot>
                    <plot/>
                    <timeAxisFormat>
                        <axisFormat labelColor="#000000" tickLabelColor="#000000" axisLineColor="#000000"/>
                    </timeAxisFormat>
                    <valueAxisFormat>
                        <axisFormat labelColor="#000000" tickLabelColor="#000000" axisLineColor="#000000"/>
                    </valueAxisFormat>
                </timeSeriesPlot>
            </timeSeriesChart>
        </band>
    </detail>
</jasperReport>

The PDF and the charts successfully generate. But there are two problems :

1) I get like 30 pages of charts, even though there is only 4 series. Each series is duplicated exactly 30 times (the number of coordinates in each series). The generated charts are all correct though.

2) I don't want separate charts. I want all the series to be in one single chart, with different colors.

What am I doing wrong here?

Edit :

Main :

public class testmain {
    public static void main(String[] args) {
        int threshold = 30;
        List<List<PoolUserLoginsVO>> poolLogins = new ArrayList<>();
        List<PoolUserLoginsVO> userLogins = new ArrayList<>();
        for (int i = 0; i < threshold; ++i) {
            LocalDate localDate = LocalDate.now().minusDays(threshold - i - 1);
            Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
            PoolUserLoginsVO logins = new PoolUserLoginsVO(i, "pool1", date);
            userLogins.add(logins);
        }
        poolLogins.add(userLogins);

        List<PoolUserLoginsVO> userLogins2 = new ArrayList<>();

        for (int i = 0; i < threshold; ++i) {
            LocalDate localDate = LocalDate.now().minusDays(threshold - i - 1);
            Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
            PoolUserLoginsVO logins = new PoolUserLoginsVO(1, "pool2", date);
            userLogins2.add(logins);
        }
        poolLogins.add(userLogins2);

        List<PoolUserLoginsVO> userLogins3 = new ArrayList<>();
        for (int i = threshold; i > 0; --i) {
            LocalDate localDate = LocalDate.now().minusDays(threshold - i - 1);
            Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
            PoolUserLoginsVO logins = new PoolUserLoginsVO(i, "pool3", date);
            userLogins3.add(logins);
        }
        poolLogins.add(userLogins3);

        JRBeanCollectionDataSource vmsJRBean = new JRBeanCollectionDataSource(poolLogins);
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("poolLogins", poolLogins);

        File file = new File("report.pdf");
        try {
            FileOutputStream fop = new FileOutputStream(file);
            JasperPrint jasperPrint = JasperFillManager.fillReport("test.jasper", parameters, new JREmptyDataSource());
            JasperExportManager.exportReportToPdfStream(jasperPrint, fop);
            fop.flush();
            fop.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JRException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Answer:

You are ignoring what the detail band actually do in the sub_chart.jasper

The detail band will iterate over your datasource (record after record), creating a chart for every record and you don't want this; you need the datasource for your chart.

I have hard time testing your actual setup to check that everything else is ok, but a good guess is that it's enough that you move the chart to the summary band and then completely delete the detail band.

The code change in your sub_chart.jasper is:

<detail> --> <summary>

</detail> --> </summary>

Question:

We're evaluating the pro version of JasperReports. For a POC, we need to generate dynamically (with the Java API) a report template based on columns selected by a user on the UI, including a total at the bottom of the report. We are using the net.sf.jasperreports.* library to generate a report template, compile it and run it. That works fine.

However we want to add, next to the total, a chart with each of the values that comprise the total. We found the jaspersoft/highcharts jar and that seems to be the one to use, but need a code snippet to know how to add a chart (JRDesign chart element) to a report band (JRBand).

Any insights will be greatly appreciated.

UPDATE Reference on Jaspersoft Pro support of Highcharts here


Answer:

Adding a chart element via the Java API consists of creating a JRDesignComponentElement object which wraps a com.jaspersoft.jasperreports.highcharts.charts.StandardChartComponent instance, which contains all the chart configuration.

Here's some sample code that creates a report that contains a chart in the summary section. The report can be run using an empty data source with one or more data records.

You'll of course need to adapt the code to populate the chart with the data that you want to display. You'd mainly need to change the level bucket expression and the measure value expression.

To compile the code you'll need to a jasperreports-highcharts jar in the classpath (plus dependencies - jasperreports-pro, jasperreports-license and others).

JasperDesign report = new JasperDesign();
report.setName("chart");

JRDesignBand summary = new JRDesignBand();
summary.setHeight(300);
report.setSummary(summary);

JRDesignComponentElement chartElement = new JRDesignComponentElement();
chartElement.setX(0);
chartElement.setY(0);
chartElement.setWidth(500);
chartElement.setHeight(300);
chartElement.setComponentKey(HighchartsConstants.DEFAULT_COMPONENT_KEY);

StandardChartComponent chart = new StandardChartComponent();
chart.setType(ChartType.COLUMN_CHART);

StandardChartSetting defaultSetting = new StandardChartSetting();
defaultSetting.setName(HighchartsConstants.SETTING_NAME_DEFAULT);
//set a static String property
defaultSetting.addChartProperty(new StandardChartProperty("title.text", 
        "My chart title", null));
//set an expression based boolean property
defaultSetting.addChartProperty(new StandardChartProperty("plotOptions.series.dataLabels.enabled", 
        null, new JRDesignExpression("true")));
chart.addChartSetting(defaultSetting);

DesignMultiAxisData data = new DesignMultiAxisData();
DesignMultiAxisDataset dataset = new DesignMultiAxisDataset();
//this actually means feeding data to the chart on each record
dataset.setIncrementType(IncrementTypeEnum.NONE);
data.setDataset(dataset);

DesignDataAxis rowAxis = new DesignDataAxis();
rowAxis.setAxis(Axis.ROWS);
DesignDataAxisLevel level = new DesignDataAxisLevel();
level.setName("rows");
level.setLabelExpression(new JRDesignExpression("\"Rows\""));
DesignDataLevelBucket levelBucket = new DesignDataLevelBucket();
//expression that produces category values
levelBucket.setExpression(new JRDesignExpression("\"Row \" + $V{REPORT_COUNT}"));
level.setBucket(levelBucket);
rowAxis.addLevel(level);
data.addDataAxis(rowAxis);

DesignDataMeasure measure = new DesignDataMeasure();
measure.setName("measure");
measure.setLabelExpression(new JRDesignExpression("\"Data\""));
measure.setCalculation(CalculationEnum.NOTHING);
measure.setValueClassName("java.lang.Integer");
//expression that produces series values
measure.setValueExpression(new JRDesignExpression("$V{REPORT_COUNT}"));
data.addMeasure(measure);

chart.setMultiAxisData(data);

chartElement.setComponent(chart);
summary.addElement(chartElement);

Question:

i tried to make pie chart with jasper report... I already write the customizer class for the chart...Anyone can give me suggestion about how to make item label color same with series color?

PiePlot piePlot = (PiePlot)chart.getPlot();
PieDataset pieDataset = piePlot.getDataset();
piePlot.setOutlineVisible(false);
chart.setBackgroundPaint(Color.white);              
piePlot.setLabelFont(new Font("Arial", Font.CENTER_BASELINE, 7));                              piePlot.setShadowPaint(null);        
piePlot.setLabelOutlinePaint(null);
piePlot.setLabelShadowPaint(null);
piePlot.setLabelBackgroundPaint(null);      
piePlot.setSectionOutlinesVisible(false);

I add picture...In picture, "0.07%, 6.18%, 93.74%" have black color...Can we change that color with series color? So "93.74%" have brown color, "6.18%" have magenta color...

Thanks


Answer:

Finally i found the solution based on @PetterFriberg suggestion...

in PiePlot method drawLeftLabels and drawRigtLabels change

TextBlock block = TextUtilities.createTextBlock(label,
                        this.labelFont, this.labelPaint, maxLabelWidth,
                        new G2TextMeasurer(g2));

to

TextBlock block = TextUtilities.createTextBlock(label,
                        this.labelFont, lookupSectionPaint(leftKeys.getKey(i)), maxLabelWidth,
                        new G2TextMeasurer(g2));

Result

Question:

I want to make a jasper report with vertical separation on series in line chart.

I checked all report elements but I didn't find any matching element. I attach sample image what I want


Answer:

The chart is generated by the jfreechart library and AFIK there is no setting that will allow you to achieve this automatically.

The solution would be generating multiple charts (one on top of the other) on each series and applying a customizer to the chart so that each chart can be adapted in base of its position.

csv data example

+----------+--------+--------+
| Category | Serie1 | Serie2 |
+----------+--------+--------+
| A        | 1      | 0.3    |
| B        | 0.5    | 0.2    |
| C        | 0.7    | 0.6    |
+----------+--------+--------+

jrxml example with two charts (1 for series1 and the other for series2)

<?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="chartTest" pageWidth="595" pageHeight="842" whenNoDataType="BlankPage" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="597c0716-df6b-42ec-a7c8-863eb1b7174a">
    <queryString>
        <![CDATA[]]>
    </queryString>
    <field name="Category" class="java.lang.String"/>
    <field name="Serie1" class="java.lang.Double"/>
    <field name="Serie2" class="java.lang.Double"/>
    <summary>
        <band height="205" splitType="Stretch">
            <lineChart>
                <chart customizerClass="ChartCustomizer">
                    <reportElement x="171" y="0" width="200" height="100" uuid="245c4678-0cad-4342-8e54-6355c23a3c72"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend position="Right"/>
                </chart>
                <categoryDataset>
                    <categorySeries>
                        <seriesExpression><![CDATA["Serie 1"]]></seriesExpression>
                        <categoryExpression><![CDATA[$F{Category}]]></categoryExpression>
                        <valueExpression><![CDATA[$F{Serie1}]]></valueExpression>
                    </categorySeries>
                </categoryDataset>
                <linePlot isShowShapes="false">
                    <plot/>
                    <categoryAxisFormat>
                        <axisFormat verticalTickLabels="false"/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat tickLabelColor="#FF0033"/>
                    </valueAxisFormat>
                </linePlot>
            </lineChart>
            <lineChart>
                <chart>
                    <reportElement x="171" y="93" width="200" height="111" uuid="b53cb5dc-09cd-448d-93ea-0719c239eafe"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend position="Right"/>
                </chart>
                <categoryDataset>
                    <categorySeries>
                        <seriesExpression><![CDATA["Serie 2"]]></seriesExpression>
                        <categoryExpression><![CDATA[$F{Category}]]></categoryExpression>
                        <valueExpression><![CDATA[$F{Serie2}]]></valueExpression>
                    </categorySeries>
                </categoryDataset>
                <linePlot isShowShapes="false">
                    <plot>
                        <seriesColor seriesOrder="0" color="#000000"/>
                    </plot>
                    <categoryAxisFormat>
                        <axisFormat verticalTickLabels="true"/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                    <rangeAxisMinValueExpression><![CDATA[0]]></rangeAxisMinValueExpression>
                    <rangeAxisMaxValueExpression><![CDATA[2]]></rangeAxisMaxValueExpression>
                </linePlot>
            </lineChart>
        </band>
    </summary>
</jasperReport>

java class including the ChartCustomizer for chart 1 and main method to run report

public class ChartCustomizer implements JRChartCustomizer {

    @Override
    public void customize(JFreeChart jfchart, JRChart jrchart) {
        CategoryPlot plot = (CategoryPlot) jfchart.getPlot();
        CategoryAxis range = plot.getDomainAxis();
        //Don't show the range axis
        range.setVisible(false);

        //Lets remove the 0, in your case you can do a customizer to remove the 2 on the other chart
        NumberAxis rangeAxis = new NumberAxis() {

            private static final long serialVersionUID = 3744076016723532336L;

            @SuppressWarnings({ "rawtypes", "unchecked" })
            @Override
            public List refreshTicks(Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {

                List allTicks = super.refreshTicks(g2, state, dataArea, edge);
                NumberTick t0 = new NumberTick(TickType.MAJOR, 0, "", TextAnchor.CENTER_RIGHT, TextAnchor.CENTER_RIGHT, 0);
                allTicks.set(0, t0);
                return allTicks;
            }
        };

        //Set range and paint, since we replace the rangeAxis
        rangeAxis.setRange(0, 2);
        rangeAxis.setTickLabelPaint(Color.RED); 
        plot.setRangeAxis(rangeAxis);

    }

    public static void main(String[] args) throws Exception {
        JasperReport report = JasperCompileManager.compileReport("ChartTest.jrxml");

        JRCsvDataSource ds = new JRCsvDataSource(new File("ChartData.csv"));
        ds.setNumberFormat(NumberFormat.getInstance(Locale.US)); //. as decimal separator
        ds.setFieldDelimiter(';');
        ds.setUseFirstRowAsHeader(true);

        Map<String, Object> paramMap = new HashMap<String, Object>();
        JasperPrint jasperPrint = JasperFillManager.fillReport(report, paramMap, ds);
        JRPdfExporter exporter = new JRPdfExporter();
        exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput("ChartTest.pdf"));
        SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
        configuration.setCreatingBatchModeBookmarks(true);
        configuration.setMetadataAuthor("Petter");
        exporter.setConfiguration(configuration);
        exporter.exportReport();
    }
}

Result

As you can see it not yet perfect, for the legend you can remove it from the chart and create it directly in jasper report, furthermore you can remove the 2.0 on second chart instead of the 0 in first chart, but further implementation I will leave to you.

Question:

I am looking for Bubble Chart tutorials/example of JasperReports. I did get my expected resource yet, sample program and jrxml template. I already looking for online and Jasper Ultimate Guide. Why I ask this question is to keep the answer of this question here. Not other(eg: JavaFX Chart), I have to use JasperReports.

Any body help me provide simple program as below data(not theme).

Data

Chart


Answer:

Here I got my example program for JasperReport Bubble Chart Example.

Data.java

public class Data {
    private String name;
    private double x;
    private double y;
    private double z;

    public Data(String name, double x, double y, double z) {
        this.name = name;
        this.x = x;
        this.y = y;
        this.z = z;
    }
    // getter, setter
}

BubbleChartTest.java

public class BubbleChartTest {
    public static void main(String[] args) throws Exception {
        List<Data> dataList = new ArrayList<Data>();
        dataList.add(new Data("A", 1d, 3d, 0.3));
        dataList.add(new Data("A", 2d, 3d, 0.2));
        dataList.add(new Data("B", 5d, 6d, 0.4));
        dataList.add(new Data("B", 4d, 3d, 0.2));
        dataList.add(new Data("B", 2d, 5d, 0.1));
        dataList.add(new Data("C", 5d, 6d, 0.2));
        dataList.add(new Data("C", 2d, 3d, 0.3));
        dataList.add(new Data("C", 4d, 5d, 0.4));
        String templateFile = "resources/bubble.jrxml";
        JasperDesign design = JRXmlLoader.load(templateFile);
        JasperReport report = JasperCompileManager.compileReport(design);
        Map parameter = new HashMap();
        JasperPrint print = JasperFillManager.fillReport(report, parameter, new JRBeanCollectionDataSource(dataList));
        JasperExportManager.exportReportToPdfFile(print, "D:/temp/bubble_chart.pdf");
    }
}

bubble.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="BubbleChartReport" columnCount="2" pageWidth="595" pageHeight="842" columnWidth="270" columnSpacing="15" leftMargin="20" rightMargin="20" topMargin="30">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="0"/>
    <field name="name" class="java.lang.String"/>
    <field name="x" class="java.lang.Double"/>
    <field name="y" class="java.lang.Double"/>
    <field name="z" class="java.lang.Double"/>
    <pageHeader>
        <band height="203">
            <bubbleChart>
                <chart evaluationTime="Report" theme="aegean">
                    <reportElement positionType="Float" x="0" y="2" width="555" height="197"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <xyzDataset>
                    <xyzSeries>
                        <seriesExpression><![CDATA[$F{name}]]></seriesExpression>
                        <xValueExpression><![CDATA[$F{x}]]></xValueExpression>
                        <yValueExpression><![CDATA[$F{y}]]></yValueExpression>
                        <zValueExpression><![CDATA[$F{z}]]></zValueExpression>
                    </xyzSeries>
                </xyzDataset>
                <bubblePlot scaleType="RangeAxis">
                    <plot/>
                    <xAxisFormat>
                        <axisFormat/>
                    </xAxisFormat>
                    <yAxisFormat>
                        <axisFormat/>
                    </yAxisFormat>
                </bubblePlot>
            </bubbleChart>
        </band>
    </pageHeader>
</jasperReport>

Output

Question:

I'm currently using Jaspersoft Studio 6.3.0 and jasperreports-6.2.0.jar for generating JasperReports's reports from Java application.

I have to create multiple xy-line chart(not just a single line) that too using JRBeanCollectionDataSource.

If I work with just a single xy-data list List<Coordinates>, which contains data for only one line, Then I will have the correct XY-line chart but with only one line. but I need multiple lines plotted on a chart, And the number of lines to be drawn are dynamic.

I hope someone with good experience in JasperReports can easily solve it.I have tried searching for multiple xy-line chart with JRBeanCollectionDataSource, but they all have the same example using database query.

Can anyone suggest some good reading material for jasper, because this is just beginning for me ,and on later stage I have to generate document, using jasper reports and I believe, I will have to use most of the functionalities provided by jasper(charts, tables, static data,Table of Content, etc.).

Bean Class:

public class Coordinates {

    public Coordinates(Number xCoordinate, Number yCoordinate) {
        super();
        this.xCoordinate = xCoordinate;
        this.yCoordinate = yCoordinate;
    }

    public Coordinates() {
    }

    private Number xCoordinate;
    private Number yCoordinate;

    public Number getxCoordinate() {
        return xCoordinate;
    }

    public void setxCoordinate(Number xCoordinate) {
        this.xCoordinate = xCoordinate;
    }

    public Number getyCoordinate() {
        return yCoordinate;
    }

    public void setyCoordinate(Number yCoordinate) {
        this.yCoordinate = yCoordinate;
    }

this is how I create report: I have created

List<List<Coordinates>> coordinatesList = new ArrayList<>();

so that I can hold multiple line data in it.

 JRBeanCollectionDataSource coordiantesListBean = new JRBeanCollectionDataSource(coordinatesList); 

            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            InputStream projectInputStream = classloader.getResourceAsStream("jasper/xyLineChart.jasper");

            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("XYChartDataSource", coordiantesListBean);

            try {
                JasperPrint jasperPrint = JasperFillManager.fillReport(projectInputStream, parameters,
                        new JREmptyDataSource());
                JasperExportManager.exportReportToPdfFile(jasperPrint,FILE_LOCATION);
            } catch (JRException e) {
                e.printStackTrace();
            }

Here is my xyLineChart.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="test" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="f5d035d9-630a-476c-b3d1-32985d774cb3">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
    <subDataset name="XYdataset" uuid="276f43e3-9d6c-4df1-85cb-5ea8bef1c28c">
        <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
        <parameter name="XYChartDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource">
            <parameterDescription><![CDATA[]]></parameterDescription>
        </parameter>
        <queryString>
            <![CDATA[]]>
        </queryString>
        <field name="xCoordinate" class="java.lang.Number"/>
        <field name="yCoordinate" class="java.lang.Number"/>
    </subDataset>
    <parameter name="XYChartDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
    <queryString>
        <![CDATA[]]>
    </queryString>
    <summary>
        <band height="283" splitType="Stretch">
            <xyLineChart>
                <chart evaluationTime="Report">
                    <reportElement x="0" y="0" width="555" height="283" uuid="9c9ff114-81b4-433f-bf71-17e21ea1fd3e"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <xyDataset>
                    <dataset>
                        <datasetRun subDataset="XYdataset" uuid="a8b4a706-dfaf-4347-9410-3c7018fce5f2">
                            <dataSourceExpression><![CDATA[$P{XYChartDataSource}]]></dataSourceExpression>
                        </datasetRun>
                    </dataset>
                    <xySeries autoSort="true">
                        <seriesExpression><![CDATA["SERIES 1"]]></seriesExpression>
                        <xValueExpression><![CDATA[$F{xCoordinate}]]></xValueExpression>
                        <yValueExpression><![CDATA[$F{yCoordinate}]]></yValueExpression>
                    </xySeries>
                </xyDataset>
                <linePlot>
                    <plot/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </linePlot>
            </xyLineChart>
        </band>
    </summary>
</jasperReport>

Answer:

Actually, multiple lines mean multiple series in JasperReports.

And to solve it I created a separate bean for each series.I am not sure if this is the best solution, but kind of worked for me.

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        InputStream projectInputStream = classloader.getResourceAsStream("jasper/xyLineChart.jasper");


        Map<String, Object> parameters = new HashMap<String, Object>();

        for(int i = 0 ; i< coordinatesList.size() ; i++){
            coordiantesListBean = new JRBeanCollectionDataSource(coordinatesList.get(i));
            parameters.put("XYChartDataSource", coordiantesListBean);
        }

        try {
            JasperPrint jasperPrint = JasperFillManager.fillReport(projectInputStream, parameters,
                    new JREmptyDataSource());
            JasperExportManager.exportReportToPdfFile(jasperPrint,FILE_LOCATION);
        } catch (JRException e) {
            e.printStackTrace();
        }

I even created an extra series variable in BEAN class

public class Coordinates {



    public Coordinates() {
    }

    public Coordinates(Number series, Number xCoordinate, Number yCoordinate) {
        super();
        this.series = series;
        this.xCoordinate = xCoordinate;
        this.yCoordinate = yCoordinate;
    }

    private Number series;
    private Number xCoordinate;
    private Number yCoordinate;

    /** getters & setters **/

}

xyLineChart.jrxml

Here Also, I have added new Series variable <![CDATA[$F{series}.doubleValue()]]>

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.0.final using JasperReports Library version 6.3.0  -->
<!-- 2016-07-22T09:37:19 -->
<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="test" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="f5d035d9-630a-476c-b3d1-32985d774cb3">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
    <subDataset name="XYdataset" uuid="276f43e3-9d6c-4df1-85cb-5ea8bef1c28c">
        <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
        <parameter name="XYChartDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource">
            <parameterDescription><![CDATA[]]></parameterDescription>
        </parameter>
        <queryString>
            <![CDATA[]]>
        </queryString>
        <field name="xCoordinate" class="java.lang.Double"/>
        <field name="yCoordinate" class="java.lang.Double"/>
        <field name="series" class="java.lang.Double"/>
    </subDataset>
    <parameter name="XYChartDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
    <queryString>
        <![CDATA[]]>
    </queryString>
    <background>
        <band splitType="Stretch"/>
    </background>
    <summary>
        <band height="283" splitType="Stretch">
            <xyLineChart>
                <chart evaluationTime="Report">
                    <reportElement x="0" y="0" width="555" height="283" uuid="78aa19cc-8293-4bdd-b9af-5c429db047d2"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <xyDataset>
                    <dataset>
                        <datasetRun subDataset="XYdataset" uuid="d121d53d-5698-4914-953e-03df6bf2af6e">
                            <dataSourceExpression><![CDATA[$P{XYChartDataSource}]]></dataSourceExpression>
                        </datasetRun>
                    </dataset>
                    <xySeries autoSort="true">
                        <seriesExpression><![CDATA[$F{series}.doubleValue()]]></seriesExpression>
                        <xValueExpression><![CDATA[$F{xCoordinate}.doubleValue()]]></xValueExpression>
                        <yValueExpression><![CDATA[$F{yCoordinate}.doubleValue()]]></yValueExpression>
                    </xySeries>
                </xyDataset>
                <linePlot>
                    <plot/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </linePlot>
            </xyLineChart>
        </band>
    </summary>
</jasperReport>

output: