Thursday, February 28, 2013

More Jasper iReport Tips and Tricks

I've been working with iReport for about a month now and will share a few more tricks I have found. Today I will cover:

  • Alternating row color or style
  • Date calculation - such as adding days
  • Title case
  • Setting the maximum number of rows - useful for html report as they can crash the browser
  • Html output - breaking words and cell padding

Alternating Row Style


I came across a few posts which talk about drawing rectangles to do this, however I found the best way is with Conditional Styles. This also work with html reports, unlike some other proposed solutions I tried.

In iReport simply right click on Style > Add > Style. Name the style AltBackgrd. Now right click on the new style and select Add Conditional Style. Under Condition Expression enter:
$V{REPORT_COUNT}.intValue() % 2 == 0


Now check Opaque and set the Backcolor color as needed, I'm using [234,234,234].

The xml definition of the style will look like this:

 <style name="AltBackgrd" fontName="DejaVu Sans" fontSize="10">
  <conditionalStyle>
   <conditionExpression><![CDATA[$V{REPORT_COUNT}.intValue() % 2 == 0]]></conditionExpression>
   <style mode="Opaque" backcolor="#EAEAEA"/>
  </conditionalStyle>
 </style>
Next under the Detail Band, select all the fields and set the Style to AltBackgrd. Your report should look something like this:


Date Calculation


I've also had to do some date calculation. The sql returned a set of dates indicating the start/end date of a financial week, I was then required to calculate the month end date from todays date. There is a nice post out there suggesting this can be done with a single statement which involved initializing a Calendar object, setting the date and then adding to it. In practice I was unable to get this to work. I then went down the simple route of adding hours as follows:
"Month End " + new SimpleDateFormat("MM/dd/yyyy").format(new Date($F{WEEK_END_DATE}.getTime() + ($V{oneDay} * 7 * ($F{ACCT_WEEKS_IN_MONTH}.intValue() - $V{AcctMonth_COUNT}))))

Where does oneDay come from you ask? Well that is just a Variable I defined, with the following Variable Expression:
24L*60*60*1000

Now I can easily do date calculations. This is sufficient for my purposes however do be careful around daylight saving times with this technique.

Title Case


Although this is a fairly obvious solution I though it would be worth mentioning to get fields in Title Case you can simply do this:
org.apache.commons.lang.WordUtils.capitalizeFully($F{MANAGER_NAME})
This of course relies on the fact that you have Apache WordUtils on your classpath ... don't you, of course you do.

Maximum Number of Rows


This was a very important feature. I was constantly getting bug requests because the screen would lock up or Chrome would crash, controls were sluggish and unresponsive, and why? Well because you're trying to view 50k rows in your browser. Now this solution was only needed for html as we did not want to limit the rows for pdf or csv. To do this I used the REPORT_MAX_COUNT parameter.

This is configured inside my controller as follows:
 if (format == null || "HTML".equalsIgnoreCase(format)) {
  mav.addObject("format", "html");
  mav.addObject(JRParameter.REPORT_MAX_COUNT, report.getMaxRowsHtml()); //Row limit only needed for Html
 } else {
  mav.addObject("format", format);
  if ("PDF".equalsIgnoreCase(format)) {
   mav.addObject(JRParameter.IS_IGNORE_PAGINATION, Boolean.FALSE); //Paging is only needed for pdf
  }
 }
The report object you see is simply the model representation of a Report table we use which lists all the reports and maxRowsHtml is one of the columns in the table which contains the per report html row limit. Another thing about our application is that the jrxml files are directly uploaded into the database as a clob. They are parsed, and the maxRowsHtml property is read from the jrxml. It is simply defined in the jrxml as a report property like this:
<property name="maxRowsHtml" value="2000"/>

The other piece of this was indicating to the user that there is a row limit enforced on the report, this would only be displayed on html. You can see it as (Max 2000). This can be achieved with a Text Field in iReport. Give it the following Text Field Expression:
"Rows: " + $V{REPORT_COUNT} + ($P{REPORT_MAX_COUNT} == null ? "" : " (Max " + $P{REPORT_MAX_COUNT} + ")")

Html Output


Finally I'll touch on how I prettied up the html output. When I first ran my reports they looked like this:



The lines were too tall and there was no gap between the right aligned Request Amt and the left aligned Reason. With one line of jquery, I was able to reduce the line height and put some padding between cells, this is called after the html is set on the report container through an ajax call:
$("#reportContainer table tr p").css({ 'margin' : '5px 3px', 'overflow' : 'visible'});
The other problem I had was very long descriptions were not wrapping at all, I fixed that with css:
table td
{
    word-break: break-all;
    word-wrap: break-word;
}

The final report looks something like this:


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.