mauretto mauretto - 4 months ago 40
Java Question

How to specify RoundingMode for decimal numbers in Jasper Reports

I'm using Java with Jasper Reports and would like to format a decimal value using this format mask

"#,##0.00"
. At the first sight all looks fine, but I found that my decimal values are rounded using
RoundingMode.HALF_EVEN
rounding mode and this is not correct in my case.

Is this possible to specify an other rounding mode (I need
HALF_DOWN
mode)?

Answer

You can use the scriptlets mechanism.

The sample

  • Java class
package utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

public class RoundingHelper {

    public static String round(BigDecimal value, RoundingMode mode, String pattern) {
        DecimalFormat format = new DecimalFormat(pattern);
        format.setRoundingMode(mode);
        return format.format(value);
    }
}
  • The report's template:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="format_decimal" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
    <import value="utils.RoundingHelper"/>
    <queryString>
        <![CDATA[SELECT id, (cost/10) as cost from product]]>
    </queryString>
    <field name="ID" class="java.lang.Integer"/>
    <field name="COST" class="java.math.BigDecimal"/>
    <columnHeader>
        <band height="50">
            <staticText>
                <reportElement x="0" y="0" width="154" height="50"/>
                <box leftPadding="10">
                    <topPen lineWidth="1.0"/>
                    <leftPen lineWidth="1.0"/>
                    <bottomPen lineWidth="1.0"/>
                    <rightPen lineWidth="1.0"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle">
                    <font isBold="true"/>
                </textElement>
                <text><![CDATA[Original value]]></text>
            </staticText>
            <staticText>
                <reportElement x="154" y="0" width="191" height="50"/>
                <box leftPadding="10">
                    <topPen lineWidth="1.0"/>
                    <leftPen lineWidth="1.0"/>
                    <bottomPen lineWidth="1.0"/>
                    <rightPen lineWidth="1.0"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle">
                    <font isBold="true"/>
                </textElement>
                <text><![CDATA[Using RoundingMode.HALF_DOWN]]></text>
            </staticText>
            <staticText>
                <reportElement x="345" y="0" width="191" height="50"/>
                <box leftPadding="10">
                    <topPen lineWidth="1.0"/>
                    <leftPen lineWidth="1.0"/>
                    <bottomPen lineWidth="1.0"/>
                    <rightPen lineWidth="1.0"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle">
                    <font isBold="true"/>
                </textElement>
                <text><![CDATA[Using RoundingMode.HALF_DOWN]]></text>
            </staticText>
        </band>
    </columnHeader>
    <detail>
        <band height="20" splitType="Stretch">
            <textField pattern="#,##0.000000000000">
                <reportElement x="0" y="0" width="154" height="20"/>
                <box leftPadding="10">
                    <topPen lineWidth="1.0"/>
                    <leftPen lineWidth="1.0"/>
                    <bottomPen lineWidth="1.0"/>
                    <rightPen lineWidth="1.0"/>
                </box>
                <textElement/>
                <textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{COST}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="154" y="0" width="191" height="20"/>
                <box leftPadding="10">
                    <topPen lineWidth="1.0"/>
                    <leftPen lineWidth="1.0"/>
                    <bottomPen lineWidth="1.0"/>
                    <rightPen lineWidth="1.0"/>
                </box>
                <textElement/>
                <textFieldExpression class="java.lang.String"><![CDATA[RoundingHelper.round($F{COST}, RoundingMode.HALF_DOWN, "#,##0.")]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="345" y="0" width="191" height="20"/>
                <box leftPadding="10">
                    <topPen lineWidth="1.0"/>
                    <leftPen lineWidth="1.0"/>
                    <bottomPen lineWidth="1.0"/>
                    <rightPen lineWidth="1.0"/>
                </box>
                <textElement/>
                <textFieldExpression class="java.lang.String"><![CDATA[RoundingHelper.round($F{COST}, RoundingMode.HALF_UP, "#,##0.")]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>
  • The result will be (preview in iReport)

The report in iReport

Another solution

Another way is to use BigDecimal.setScale(int, java.math.RoundingMode) method:

<textFieldExpression class="java.lang.String"><![CDATA[new BigDecimal($F{COST}).setScale(2, BigDecimal.ROUND_HALF_DOWN).toString()]]></textFieldExpression> 

or just (for BigDecimal field):

<textFieldExpression class="java.lang.String"><![CDATA[$F{COST}.setScale(2, BigDecimal.ROUND_HALF_DOWN).toString()]]></textFieldExpression> 

More info about the scriptlets in JR: Scriptlets

Comments