Search code examples
javajasper-reportsjfreechart

How to set stacked bar chart series color dynamically?


I have a stacked bar chart in JasperSoft 6.3.1 in eclipse and I am trying to display the colors based on the series. The chart displays random colors instead of assigning a single color for a specific series.

jrxml

<categorySeries>
    <seriesExpression><![CDATA[$F{name}]]></seriesExpression>
    <categoryExpression><![CDATA[$F{time}]]></categoryExpression>
    <valueExpression><![CDATA[$F{value}]]></valueExpression>
</categorySeries>
</categoryDataset>
    <barPlot>
        <plot>
            <seriesColor $F{name}.equals("JANUARY")?color="#756D72":color="" seriesOrder="0" />
            <seriesColor $F{name}.equals("MARCH")?color="#4B5154":color="" seriesOrder="1" />
            <seriesColor $F{name}.equals("JUNE")?color="#090A09":color="" seriesOrder="2"/>
        </plot>
    <itemLabel/>
    <categoryAxisFormat>
    ....

I am trying to assign the chart series color to a specific series name using the if statement. How do I achieve this in jasper reports?.

If the series name is JANUARY the color should be black, and if there is no data for JANUARY the black color should not be used.


Solution

  • As I guess that you have noticed, you can not do if statements in the xml tags, the jrxml will simple not compile since it's not valid xml anymore.

    The solution is to implement your own JRChartCustomizer

    Example

    java

    Find the different series name and set Paint to the renderer on basis of the name

    public class BarColorCustomizer implements JRChartCustomizer {
    
        @Override
        public void customize(JFreeChart jfchart, JRChart jrchart) {
            //Get the plot
            CategoryPlot  plot = jfchart.getCategoryPlot();
            //Get the dataset
            CategoryDataset dataSet = plot.getDataset();
            //Loop the row count (our series)
            int rowCount = dataSet.getRowCount();
            for (int i = 0; i < rowCount; i++) {
                Comparable<?> rowKey = dataSet.getRowKey(i);
                //Get a custom paint for our series key
                Paint p = getCustomPaint(rowKey);
                if (p!=null){
                    //set the new paint to the renderer
                    plot.getRenderer().setSeriesPaint(i, p);
                }
            }
    
        }
    
        //Example of simple implementation returning Color on basis of value
        private Paint getCustomPaint(Comparable<?> rowKey) {
            if ("JANUARY".equals(rowKey)){
                return Color.BLACK;
            }
            return null;
        }
    }
    

    jrxml

    Set the customizerClass attribute with full package name on the chart tag

    <barChart>
        <chart evaluationTime="Report" customizerClass="my.custom.BarColorCustomizer">
        ....
    </barChart>