How to populate chart data with JavaBeans collection dataSet?
Asked Answered
S

1

6

I have already created a working jrxml report presenting a table populated by a dataset of a collection (List) of Java beans.

Now I would like to use that same dataset to create Chart (basic bar chart for starters). Each bean contains 4 values that I would like to show on bar chart: month, normal hours, travel hours, and overtime hours. I was hoping that each bean would generate a group of 3-bars for each month so in the end the chart would contain 12x3 bars growing from bottom to up and the name of the month would act as a label under the 3-bar groups, each group positioned next to another starting from left to right.

Unfortunately creating this chart seems much harder than I thought. At least it seems to be totally different compared to creating the table. I'm not sure if the Jasper Studio's Chart wizard is even working. At least it doesn't allow me to add any series in the chart data series dialog: if I press Add absolutely nothing happens - no dialog opens, no error message, nothing, nothing to hint me what is wrong.

Main problem is that I don't see a way to connect the dataset data to the Chart.

After trying embedding chart to my main report, I tried to add it also to a new subreport created only for to act as chart container. I passed the main report dataset as a datasource to subreport and tried to use it as main data set in subreport's chart. Still no luck with the dataset/chart connection, f.e. Still nothing happens if I press the Add-button.

Below you can see the simple beans I'm using. First one, the WorkingHoursReport is the bean I'm passing to report as JRBeanCollectionDataSource. I believe the most interesting field of that bean is the list of WorkingHours-beans. There will be always 12 items on that list: one for each month. That is the list I'm currently passing to my table element using datasource expression: new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{workingHours}).

WorkingHoursReport.java:

public class WorkingHoursReport extends CommonReport {
    private int year;
    private List<WorkingHours> workingHours;
}

WorkingHours.java:

public class WorkingHours {

    private int month = 0;
    private double hoursNormal = 0;
    private double hoursTravel = 0;
    private double hoursOvertime = 0;
    private double hoursTotal = 0;
    private double hoursTotalCumulative = 0;
 }

While trying to create my first chart ever, I was naturally trying to populate the data to chart using the very same command for defining the datasource as I was already using successfully with my table:

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

Unfortunately it seemed that at least the jasper studio chart creation wizard did not get any connection to the data (no dialog was opening where, according to the docs, I should have been able to select data fields to chart ).

Seersucker answered 4/3, 2016 at 15:49 Comment(6)
Show the bean you are using, so we have something to work from.Neutrality
I extended my inital post to contain clips from the beans as well.Seersucker
Ok, thanks, you like 1 barchart for each WorkingHours or one barchart with the sum of all of them?Neutrality
Just one chart, where basically each WorkingHours-bean on the list would present one month in x-axis. Each month would show a group of 3 bars (one bar for normal, travel and overtime hours) "growing" on y-axis.Seersucker
Ok, tonight I will try to answer you...Neutrality
Sounds great! Because of my failures to get this done I started to worry if it's even possible to create charts based on bean collections (all/most examples seem to be concentrating on database query solutions), but I guess now that there is a way...Seersucker
N
12

This is how I would solve your problem considering that you are using java beans, need to sum up data and then have both series (hours) and categories (months). Don't connect it to your table datasource but create a specific datasource for it.

Create a specific chart bean

public class ChartData {
    private String serie;
    private String category;
    private double value;

    public ChartData(String serie, String category, double value) {
        super();
        this.serie = serie;
        this.category = category;
        this.value = value;
    }
    .... getter and setters         
}

Fill the chart bean's with data

Loop your dataset (List) and fill the ChartData list, you will probably need a map to find same month and add to the hours. I will not show you this but create them statically to show an example

List<ChartData> cList = new ArrayList<ChartData>();
cList.add(new ChartData("hoursNormal","month1", 12.3)); //The use of resources or static text is beyond this example
cList.add(new ChartData("hoursTravel","month1", 3.2));
cList.add(new ChartData("hoursOvertime","month1", 1.3));
cList.add(new ChartData("hoursNormal","month2", 16.4));
cList.add(new ChartData("hoursTravel","month2", 5.2));
cList.add(new ChartData("hoursOvertime","month2", 4.1));

Pass the List as a datasource through the parameter map

Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("CHART_DATASET", new JRBeanCollectionDataSource(cList));

Display the chart

Now we can display the chart in the title or summary band using a subDataset passed on the parameter $P{CHART_DATASET}

<?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="working_hours" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="1a12c021-57e2-4482-a273-56cbd3f78a17">
    <subDataset name="chartDataSet" uuid="119b7f0e-01ef-4e2b-b628-d76f51e83768">
        <field name="serie" class="java.lang.String"/>
        <field name="category" class="java.lang.String"/>
        <field name="value" class="java.lang.Double"/>
    </subDataset>
    <parameter name="CHART_DATASET" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource" isForPrompting="false"/>
    <summary>
        <band height="142" splitType="Stretch">
            <barChart>
                <chart>
                    <reportElement x="80" y="0" width="337" height="142" uuid="c8f4dc5d-47e7-489b-b27e-09976d90994a"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <categoryDataset>
                    <dataset>
                        <datasetRun subDataset="chartDataSet" uuid="abec2dce-b670-4e84-b71f-469d954dbcb5">
                            <dataSourceExpression><![CDATA[$P{CHART_DATASET}]]></dataSourceExpression>
                        </datasetRun>
                    </dataset>
                    <categorySeries>
                        <seriesExpression><![CDATA[$F{serie}]]></seriesExpression>
                        <categoryExpression><![CDATA[$F{category}]]></categoryExpression>
                        <valueExpression><![CDATA[$F{value}]]></valueExpression>
                    </categorySeries>
                </categoryDataset>
                <barPlot>
                    <plot/>
                    <itemLabel/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </barPlot>
            </barChart>
        </band>
    </summary>
</jasperReport>

Settings in JasperSoft Studio

Studio

Enjoy the result

Result

Neutrality answered 7/3, 2016 at 21:16 Comment(8)
Thanks a lot! I got my first chart created. I still have issues with the Jasper soft studi though. Even after creating the datasources and datastructures like you instructed, the Jasper soft studio's chart creation wizard is not able to read any data from those datasets and the wizard remains unresponsive: f.e. most of buttons that should open dialog to define data, are still not doing absolutely anything and wizard remains mostly silent and unresponsive. So only thing I could do was to copy paste your jrxml code defined in <barChart>-tag.Seersucker
@Seersucker I added the view I have in Studio view when defining chart... I do not have your issues..Neutrality
Yep, that view looks identical to my screen. But, if I f.e. try to press those "..."-buttons, nothing happens. Only "..."-button next to series opens a Series-dialog, but if I try to press "add"-button there, nothing happens. Not even after deleting the existing one from there, the add-button doesn't get any more responsive. Because of this I would not have been able to create the chart compltely by this wizard: can't even add a series-variable there...Seersucker
Just in case you are intersted, I added here a new sort of a follow-up question: #35866774Seersucker
@vka, for me it opens the expression editor... I guess you have a problem with the installation..Neutrality
Hi @PetterFriberg I have tried using the above example. Im getting this following exception. java.lang.ClassCastException: org.jfree.chart.axis.NumberTickUnitSource cannot be cast to org.jfree.chart.axis.TickUnits on <valueExpression><![CDATA[$F{value}]]></valueExpression>, Please help. Thanks.Goggles
@Ellie the exact same code as in example? or just something similar?Neutrality
Yes very similar, the only difference is that it is inside a subreport, When i change the value of <valueExpression><![CDATA[0]]></valueExpression , the chart gets printed but no values just the series. I have tried now using Customizer class for the report and luckily I am able to print the chart without error. So I guess I am going to stick with this since I have a lot of customization also. Thank you for replying.Goggles

© 2022 - 2024 — McMap. All rights reserved.