Right Outer Join

17 April 2011

Useful Chart Customizers in JasperReports, iReport, and JasperReports Server

Useful Chart Customizers in JasperReports, iReport, and JasperReports Server

In a previous article I described some reasons that chart customizers are useful and gave some links to useful resources. (I’ll call that article “Chart Customizers 1″.) If you are not already familiar with chart customizers, then please read Chart Customizers 1 before reading this one. If you are already familiar with them, then please skim Chart Customizers 1 before reading this one.

Overview

“Chart Customizers 1″ explained what chart customizers are and provided some code. It was useful for Java developers. It made all changes as hard-coded settings, so the samples were not immediately useful for anyone without further coding.

“Chart Customizers 2″ (this article) provides a useful chart customizer and describes why it’s useful. You can immediately use it to solve some common problems (no coding required!).

If you just want to grab the chart customizer (binary and source) scroll all the way to the bottom.

Using Additional Properties

The concept of “properties” is a key idea that was missing in “Chart Customizers 1″. Using properties lets you set values in the report (in the .jrxml file) rather than hard-coding them as I did in my earlier sample. As one would hope (expect?) it’s simple. The chart customizer extends JRAbstractChartCustomizer. Therefore we can get the chart properties like this:

JRPropertiesMap pm = jasperChart.getPropertiesMap();

Then we can get a particular property like this:

double upperMargin = (pm.getProperty("UpperMargin") == null) ? -1 : Double.parseDouble(pm.getProperty("UpperMargin"));

This is the addition that made it possible for me to extend my chart customizers from being purely proof of concept samples to being useful chart customizers.

Bar Chart Improvements

Integer Tick Marks

UPDATE: JasperReports added this option! There is a property called “net.sf.jasperreports.chart.range.axis.integer.unit” available now. There’s no need for a chart customizer to force the chart to use only integers. In the screenshot below where I use “IntegerTickUnits” you can instead use “net.sf.jasperreports.chart.range.axis.integer.unit” set to a value of “true” (both without quotes). It was added to JasperReports 4.6 (2012-05-21), we can hope it will make it into iReport or Jaspersoft Studio soon.

Let’s start with some common requests for bar charts. Perhaps the most common request that I have seen is to prevent charts from showing non-integer values on value axis. Here’s an example. The number of times that a person shopped on a particular day is necessarily an integer. I don’t want to see “2.5” on the chart axis.

The bars are completely accurate. Yet it’s annoying to have the non-decimal value displayed.

How easy is it to tell JFreeChart to only use integers? Really easy! Hooray! It has a method called “createIntegerTickUnits()”. By the way, if you’re doing any significant work with JFreeChart then you should buy their Developer Guide. It’s well done.

How easy is it tell iReport and JasperReports to use only this method? Impossible. That’s a big bummer.

Fortunately, we can amend that somewhat pessimistic answer like this:

How easy is it tell iReport and JasperReports to use only integers? Really easy if we use a chart customizer! Hooray! It’s a single line. Since we might not always want this applied, we can surround it by an if statement:

if (useIntegerTickUnits) {
  valueAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}

Now if I add the property “IntegerTickUnits” with the value “true” to my bar chart I’ll only get integers.

On the chart “Shopping Days” I set this property

If I set the value to “false” (or to anything besides “true”) or if I don’t set the property at all, then I get the standard behavior. If you’re new to JasperReports Server then refer to the Detailed Steps at the end of this article to exactly exactly what you need to do to apply this chart customizer.

The bars look much better when aligned with tick marks (or exactly half way between them)


Category Labels on multiple lines

By default there is no way to tell the chart to use multiple lines to display a category label. Again it’s easy in JFreeChart, so it’s easy in a chart customizer. Now I just have to add the property “MaximumCategoryLabelLines” with the value “2” to my chart to get what I want.

Who is it that drank more ţuică?

Now its clear that I ate more hot dogs.


Using more space for category labels

JFreeChart is nice enough to truncate long labels for me. But it’s quite restrictive about how large it lets the labels be. A call to setMaximumCategoryLabelWidthRatio let’s me allot more space for the labels. Here’s an alternative solution to the previous problem where labels are cut off.

Who is it that ate more hot dogs?

Alternative solution increases the width allowed for the labels


Space between bars

The default amount of space put between the bars within each category is pretty generous. That can be reduced as a percentage of the available space. I added this to the .jrxml (well, iReport adds this to the .jrxml) to completely eliminate the space between bars:

<property name="ItemMargin" value="0.0f"/>

In some charts its more effective to remove the space between bars


Upper Margin

I will not bother showing this property since it’s covered in “Chart Customizers 1″. The only difference now is that in that case I hard-coded the margin to .40. Now I can set that percentage as a property in the chart.

Pie Chart Improvements

My most common annoyance with pie charts was when I put several pie charts onto the same page to show a trend. There is no easy way to specify a color for a named section. It’s easy to specify a color for the first section and a color for the second section. This is often sufficient. But this has the potential to be extremely confusing when two different charts have different items or when they have the same items returned in a different order. The following sample report shows the idea clearly.

Passing in the colors for the sections in a pie chart is the most complex piece in all of my chart customizers. I give a special thank you to Teodor Danciu for the idea and to Luke Shannon for help with some implementation details.

You must create a property on the chart called “Predefined Colors”. The property value is a String containing key:value pairs separated from each other by semi-colons. For example, for a report that I run which shows the databases that JasperReports Server instances use for their repository database I pass this string:

MySQL:#015A84;Oracle:red;PostgreSQL:#0085B0;Microsoft SQL Server:#F8EB33

For most databases I choose a color using RGB values. For Oracle I use the shorthand syntax “red”. These values get converted into colors using a utility class that is built-in to JasperReports: http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/type/ColorEnum.html

To see exactly how it’s done, refer to the sample report (Pie_Specified_Series_Colors.jrxml) and to the comments in the chart customizer (PieLabels.java).

These are some of the most common chart tweaks that I have seen. Some are ones that I have needed myself, and others are ones that I have seen requested on JasperForge. Please let me know if you find the chart customer useful, and let me know what other properties you would find useful in a chart customizer.

Detailed Steps to update a report

Here are the steps I followed to apply my new chart customizer to an existing report. This is the report “Customer Overview” that ships with Jaspersoft BI evaluation version. So you can easily apply this chart customizer to that sample before trying it on your own charts.

  1. Upload ChartCustomizers2.jar into JasperReports Server. (Use either the web UI or iReport’s JasperReports Server plug-in.)
  2. Edit the report to add a link to the resource ChartCustomizers2.jar. (Use either the web UI or iReport’s JasperReports Server plug-in.)
  3. Edit the report in iReport to make two changes:
    1. Find the property “Customizer Class” and set it to “com.jaspersoft.bizdev.BetterBarLabels” (without the quotes).
    2. Find the property “Properties expressions” and add a new property called “IntegerTickUnits” with the value “true” (without the quotes in both cases).
  4. Save the report back to JasperReports Server. Run the report.

Sample reports and the Chart Customizer

WordPress seems to lose my attachments with some regularity. So instead of using that I’ll try GoogleDocs for sharing my samples.

  • Chart Customizer 2 – This is a .jar file. Just add it to your classpath and you can use it. The .jar also includes the source .java files.
  • Pie Chart sample report JRXML
  • Pie Chart sample report PDF
About these ads

26 Comments »

  1. Romanian by any chance ? :)
    “tuica” got my attention

    Comment by John — 4 May 2011 @ 03:39

  2. I’m glad you noticed the reference. I’m not Romanian, but I chose that example as a reference to the founder of JasperReports, Teodor Danciu, who is.

    Comment by mdahlman — 12 May 2011 @ 15:41

  3. Matt, your jar file attachment seems to have gone missing – I’m getting an IE error when I try to download it. The jrxml and pdf are ok.

    Comment by Christine — 19 May 2011 @ 22:29

    • Strange. It’s still working well for me using Chrome and Firefox. Try with this link to the .jar file:

      Comment by mdahlman — 20 May 2011 @ 10:41

  4. Im having a pie chart and a stacked 3d bar chart in the same page with values for same category. I used Pie_Specified_Series_Colors.jrxml) example to fix the issue in pie chart. how to fix the same in stacked 3d bar char. Can you help?

    Comment by Anand — 2 September 2011 @ 12:30

    • I’m relatively sure that it should be possible to the same thing for stacked bar charts. Sorry, I have never tried that, so I don’t have any specific advice. I would begin by taking a look at the JFreeCharts API to see how to control series colors in stacked bar charts.

      Comment by mdahlman — 2 September 2011 @ 13:55

      • Thanks dahlman

        I found the answer
        i did it this way
        categoryPlot.getRenderer().setSeriesPaint(i, (Paint)colorMap.get(rowKey));

        where the colorMap is something like your piesections in yor example.
        i runs through – dataset.getRowCount()

        Comment by Anand — 13 September 2011 @ 13:27

      • Would you mind sharing your jar file that includes the customization for your stacked bar chart color control?

        Comment by Christine — 23 November 2011 @ 15:01

  5. Thanks so much for this code! Definitely saved me some time.

    For anyone else that wants a pie chart with colors that stay the same:

    On the chart itself set the Customizer Class property to com.jaspersoft.bizdev.PieLabels

    Set the property named “PredefinedColors” without a space in the name.

    Comment by sjbotha — 12 September 2011 @ 11:20

  6. I have been trying to resolve this issue with my charting for months (where the pie chart color ties to the specific slice). I think this is exactly what I need, but I am not successful getting the ChartCustomizer2 to apply the property PreDefinedColors to my report. I added the report to the Jasper Report as a resource, then added the property to the chart.

    This is the first time I’ve tried applying a chart customizer, so is there something you think I am missing?

    Thanks in advance,
    Christine

    Comment by Christine — 23 November 2011 @ 11:01

  7. Will the integer tick units property work on a time series chart?

    Comment by kathy — 30 December 2011 @ 14:54

    • Never mind.. now it’s working. Thanks for the tool it’s awesome! Now, how do I go about building my own? I studied java a long time ago, I downloaded Eclipse, what would be my next step?

      Comment by kathy — 30 December 2011 @ 16:01

  8. Hello,

    I want to extend your great customizers. How is it possible to debug in the customizers?

    Thanks.

    Comment by stefansta — 12 January 2012 @ 10:35

    • I’m really glad you’re finding them useful. The source is all there, so you should be able to open it in the IDE of your choice and work with it.

      Comment by mdahlman — 12 January 2012 @ 11:04

  9. Hallo,

    I am not sure which debugger to use and how to configure that the ireport is startet out of my IDE. Which IDE do you use?

    Thanks.

    Comment by stefansta — 12 January 2012 @ 11:17

  10. Hi there,

    I am using ireport and have added the jar to my classpath. I think added “com.jaspersoft.bizdev.BetterBarLabels” to customizer class and added the property for “IntegerTickUnits” and set True however when I try to run my report I get a java.lang.NullPointerException  at com.jaspersoft.bizdev.BetterBarLabels.customize(BetterBarLabels.java:49

    Do you have ideas what I may be doing wrong?

    Thanks,

    Scott

    Comment by Scott Crawford — 9 February 2012 @ 03:27

    • This is line 49:
      double upperMargin = (pm.getProperty(“UpperMargin”) == null) ? -1 : Double.parseDouble(pm.getProperty(“UpperMargin”));

      It’s not supposed to be possible to get a Null Pointer Exception there. I guess that you have not set the property “UpperMargin”. That should be OK. Try adding the property UpperMargin and setting it to .05 (which is 5%), and see what happens. If that solves it… then my chart customizer seems to have a bug, but at least you have a simple workaround.

      If you still have a problem, please open a thread on the JasperReports forum on jasperforge.org. Include the full stack trace. Post here to let me know that the thread is started, and I’ll take a look.

      Comment by mdahlman — 9 February 2012 @ 09:14

      • I found a way that my chart customizer throws a Null Pointer Exception. If you have not set any properties at all on the chart, then the JRPropertiesMap is not just empty but null. So subsequent attempts to retrieve properties yield NPEs rather than the intended result of retrieving the value or retrieving nothing for unset values. It’s a simple fix. I’ll post it someday.

        Comment by mdahlman — 21 February 2012 @ 22:39

  11. Hey, mdahlman, thanks for the effort. I’m studying your code now to try to create automatic (and consistent) color assignment between charts in a same report. I can’t use PredefinedColors property as there are hundreds of possible keys and I just can’t (or shouldn’t) assign a specific color to each one. If I don’t give up and indeed find a generic solution, would you add it to your .jar? One less curse directed to the people of report-developing kingdom.

    One more thing, the javadoc at MeterLabels is a copy of the one at PieLabels :P

    Anyway, thanks for your effort!

    Comment by Kim — 16 March 2012 @ 06:27

    • Kim,
      Yes, I would be very happy to include your additional code into my sample .jar! A good way to achieve this might be to put my code into a public repository like github, but I have never gotten around to that. I have made a few improvements to the chart customizer since posting the article, but nothing has changed regarding colors. I’ll try to post all updates someday soon.

      Comment by mdahlman — 16 March 2012 @ 08:53

  12. Hi Matt,

    I have a doubt on the Category Labels on multiple lines. How do you or we should define the name of the property. How to take care of name of the property so that chart takes care of that. Like property , MaximumCategoryLabelLines (self explaining name), defines the Maximum lines to be defined for label but I want to understand how to choose this name for the property.

    Please advise.

    Comment by manish646manish — 3 December 2012 @ 22:02

    • Manish, you’ll have to look at the Java code for the chart customizer for complete details. The key idea is that the code looks for a property called “MaximumCategoryLabelLines” and does something with it. You can add lots of other properties with other names… but my chart customizer will just ignore them. When you write a new chart customizer it’s up to you to decide what properties (if any) you’ll use.

      Comment by mdahlman — 10 December 2012 @ 21:01

  13. JasperReports Server is deployed here: /webapps/jasperserver-pro
    You need to put the jar file here: /webapps/jasperserver-pro/WEB-INF/lib

    Comment by mdahlman — 10 December 2012 @ 20:51

  14. Hi, although this blog entry is quite old, it was very, very helpful for me. I hope to get additional help here, as I got a problem with the chart customizer class I cannot solve. I made a pie chart with a legend and a customizer class. The pie chart has a legend. I managed to give the legend the correct positon, a different font, rectangles instead of circles within the legend. But the problem now is: These little squares within the legend have light gray borders around them. How can I get rid of them????

    Comment by Shibadoo — 11 December 2012 @ 09:11

  15. Super useful, thank you!

    Comment by sh0x — 19 December 2012 @ 16:55

  16. Thanks Matt,
    using your articles and a few others, I finally managed to get a StackedBarGraph to have set colours based upon Series names, It is not elegant but appears to work. Would be nice to shift the Colour to Series lookup into Properties expressions and add some error checking.

    public class FixedSeriesColor extends JRAbstractChartCustomizer{
    public void customize(JFreeChart freeChart, JRChart jrChart) {

    CategoryPlot plot = freeChart.getCategoryPlot();
    CategoryDataset ds = plot.getDataset();

    CategoryItemRenderer r = plot.getRenderer();

    Color seriesColor;
    // Set a default colour if unnamed series
    seriesColor = Color.yellow;

    for (int i = 0; i < ds.getRowCount(); i++) {
    if (ds.getRowKey(i).toString().equalsIgnoreCase("Series1")) {
    seriesColor = Color.green;
    } else if (ds.getRowKey(i).toString().equalsIgnoreCase("Series2")) {
    seriesColor = Color.blue;
    } else if (ds.getRowKey(i).toString().equalsIgnoreCase("Series3")) {
    seriesColor = Color.red;
    } else {
    }
    r.setSeriesPaint(ds.getRowIndex(ds.getRowKey(i)), seriesColor);
    }

    }
    }

    Comment by Fluffy — 25 February 2013 @ 20:55


RSS feed for comments on this post. TrackBack URI

Go on... leave a reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Silver is the New Black Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 39 other followers

%d bloggers like this: