Search code examples
javajasper-reportsbar-chartjfreechart

How to set color of bar in barChart in JasperStudio based on value in dataset?


I'm creating a barChart in a subReport. I pass the dataset completely constructed via code (nodeJS) and it works pretty fine.

Now I have to give always the same color (of the bar in the barChart) to same element. The number of elements in the barChart is dynamic, so I can't do it static (I did it like that previously).

For example:

  • Item 1 would always have the color black;
  • Item 2 always blue;
  • Item 3 always pink.

And so on. Of course there will be occasion when there is only Item 3, so normally a standard series "0" color would be assigned to it. But I need that Item to be always pink, regardless if it is the first item, the third, etc.

I've come here, but I don't know how to go further. I've found some answers but they don't achieve what I want

package com.efarmgroup.sina.sios4.jasper;


import java.awt.Color;
import net.sf.jasperreports.engine.JRChart;
import net.sf.jasperreports.engine.JRChartCustomizer;
import org.jfree.chart.JFreeChart;
import org.jfree.data.category.*;
import org.jfree.chart.renderer.category.*;
import java.util.HashMap;



public class customColorSeries implements JRChartCustomizer {


    @Override
    public void customize(JFreeChart chart, JRChart jasperChart) {

        //This is the list of the object. Each of them should have a standard color
        Object[] objectList = {"BULLONERIA", "FONDAZIONE o BASAMENTO", "SPALLE", "PILE", "PULVINI", "TRAVI",
                            "TRAVERSI", "IMPALCATI", "CORDOLI", "ARCHI", "APPARECCHI SPECIALI", "SISTEMAZIONE IDRAULICA",
                            "MURO", "APPOGGI", "BARRIERA", "GIUNTI", "Portale", "Piedritto sinistro", "Paramento sinistro",
                            "Volta", "Paramento destro", "Piedritto destro", "Sovrastruttura stradale",
                            "By Pass / Nicchia", "Elementi accessori"};



        // Category Plot: most commonly used to display bar chart
        // BarRenderer: create bar charts from data in a category dataset

        BarRenderer renderer = (BarRenderer) chart.getCategoryPlot().getRenderer();

        // Method required for reading the dataset.
        // Table of values that can be accessed using row and column keys.
        CategoryDataset cd = chart.getCategoryPlot().getDataset();

        // Row gives the series expression
        int rc = cd.getRowCount();
        for (int i = 0; i < rc; i++) {

            //Here I should retrieve the the value of the dataset to perform a simple if
        }
    }

}


This is a simple example of the sub data set

evolution_data: 
  [

     { Building_ID: 1,
       Building_Code: 'F010',
       Building_Name: 'Quiliano',
       Evaluation: 50,
       Object_Name: 'APPOGGI',
       Span_Code: 1,
       seriesOrder: 0,
       color: '#FC6D79' },
     { Building_ID: 1,
       Building_Code: 'F010',
       Building_Name: 'Quiliano',
       Evaluation: 8,
       Object_Name: 'BARRIERA',
       Span_Code: 1,
       seriesOrder: 0,
       color: '#FC6D79' },
     { Building_ID: 1,
       Building_Code: 'F010',
       Building_Name: 'Quiliano',
       Evaluation: 5,
       Object_Name: 'APPOGGI',
       Span_Code: 2,
       seriesOrder: 1,
       color: '#A64186' },
     { Building_ID: 1,
       Building_Code: 'F010',
       Building_Name: 'Quiliano',
       Evaluation: 3,
       Object_Name: 'BARRIERA',
       Span_Code: 2,
       seriesOrder: 1,
       color: '#A64186' },
     { Building_ID: 1,
       Building_Code: 'F010',
       Building_Name: 'Quiliano',
       Evaluation: 0,
       Object_Name: 'APPOGGI',
       Span_Code: 3,
       seriesOrder: 2,
       color: '#9758C4' },
     { Building_ID: 1,
       Building_Code: 'F010',
       Building_Name: 'Quiliano',
       Evaluation: 0,
       Object_Name: 'BARRIERA',
       Span_Code: 3,
       seriesOrder: 2,
       color: '#9758C4' }]

The color should be based on the "Object_Name" field in the dataset.


Solution

  • My problem is solved, here's my solution:

    public class customColorSeries  extends JRAbstractChartCustomizer  {
    
        @Override
        public void customize(JFreeChart chart, JRChart jasperChart) {
    
            BarRenderer renderer = (BarRenderer) chart.getCategoryPlot().getRenderer();
            CategoryDataset catDS = chart.getCategoryPlot().getDataset();
            com.fasterxml.jackson.databind.node.ArrayNode seriesColor = (ArrayNode) getParameterValue("seriesColor_P");
            HashMap<String, String> customMap = new HashMap<>();
    
            for (int z = 0; z < seriesColor.size(); z++) {  
                customMap.put(seriesColor.get(z).get("Object_Name").textValue(), seriesColor.get(z).get("Color").textValue());
            }
    
            for (int i = 0; i < catDS.getRowCount(); i++) {
                if(customMap.containsKey(catDS.getRowKey(i).toString())) {
                    renderer.setSeriesPaint(i, Color.decode(customMap.get(catDS.getRowKey(i).toString())));
                }
            }
        }        
    }
    

    I send an array of object, where every object is built like this

    {Object_Name: 'APPOGGI', Color: '#ff0000'} 
    {Object_Name: 'SPALLE', Color: '#f2ca79'}
    

    and so on....

    as a parameter to the sub report. I then use the databind and the HashMap to treat it and render it at the end.