Custom cell coloring in the JasperReports crosstab cell

Custom cell coloring in the JasperReports crosstab cell

In our application we have a set of common colours which are used on the reports. These colours can be rather dynamic and are stored in the properties file. Once some chart is rendered – the colour is loaded from the file and the used to create chart.

It’s rather trivial to do this for the chart. Just specify JRChartCustomizer and do everything you want.
It’s not so trivial to change the background colour of the cells in the JasperReports crosstab. So let me describe how it was done in the version 3.0.1 of JasperReports.

Unfortunately conditional styles could not be used in our case. We are not going to specify the smae scope of colours across multiple report templates, it will become a huge pain in case of changes.

May be you know that generating JasperReports report includes three steps:
1. Compilation of the JRXML file into binary JASPER file.
2. Filling compiled JASPER file with some data for example DB data. As result you get JasperPrint object.
3. Exporting JasperPrint into some format like PDF/RTF/HTML/etc…

So the main idea here is to update JasperPrint object generated on step 2. JasperPrint contains all of the report contents and you can work with it.
Lets get deeper into the code

private void customizeFirstPage(final JasperPrint reportPrint) {
  // Get the page.
  JRPrintPage firstPage = (JRPrintPage) reportPrint.getPages().get(1);

  // Passing through page items.
  for(Object element : firstPage.getElements()) {

    // Selecting objects which are probably table cells.
    if(element instanceof JRTemplatePrintFrame) {
      JRTemplatePrintFrame printElement = (JRTemplatePrintFrame)element;

      // Getting elements inside cell
      List elements = printElement.getElements();

      // Filtering out items which can’t be cells
      if(elements.isEmpty() || !(elements.get(0) instanceof JRPrintText)) {
        continue;
      }

      // Getting the text item. We’ll select the color based on the its contents.
      final JRPrintText object = (JRPrintText)elements.get(0);

      // Getting template which defines the look like of the cell
      JRTemplateElement template = printElement.getTemplate();

      // Using commons-lang library to copy template object. We’re not going to spoil the old one.
      JRTemplateElement newTemplate
        = (JRTemplateElement) SerializationUtils.clone(template);

      // “DynamicTableHeader” was specified as a style marker in JRXML file.
      if(“DynamicTableHeader”.equals(template.getStyle().getName())) {

        // This method invokes protected method named setBackcolor via reflection
        // and passes a color selected based on the cell contents as a parameter.
        invokePrivateMethod(JRTemplateElement.class, “setBackcolor”, newTemplate,
buildColor(object.getText()));

        // Applying a new style to the cell.
        printElement.setTemplate(newTemplate);
      }
    }
  }
}

I guess that code has enough comments, so let see how the result looks like in the reality.

Of course this grid looks like a bit weird and I’ll continue making more beautiful, but it works. 🙂