javajasper-reportsrounding

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)?


Solution

  • You can use the scriptlets mechanism.

    The sample

    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);
        }
    }
    
    <?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 report in iReport

    Another solution

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

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

    or just (for BigDecimal field):

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

    More info about the scriptlets in JR: Scriptlets