How to specify RoundingMode for decimal numbers in Jasper Reports

前端 未结 2 971
天命终不由人
天命终不由人 2020-12-07 03:41

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

相关标签:
2条回答
  • 2020-12-07 03:46

    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 (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

    0 讨论(0)
  • 2020-12-07 04:08

    Here is another solution.

    You can change the default rounding mode of the number formatter by extending the default JR format factory (net.sf.jasperreports.engine.util.DefaultFormatFactory) and sending an instance of the extended factory via the JRParameter.REPORT_FORMAT_FACTORY parameter.

    The rounding mode of a java.text.DecimalFormat instance can be changed via the setRoundingMode() method.

    https://community.jaspersoft.com/questions/528989/decimal-formatting-rounding-mode-problem

    I've created inner class:

        getParameters().put(REPORT_FORMAT_FACTORY, new DefaultFormatFactory() {
    
            @Override
            public NumberFormat createNumberFormat(String pattern, Locale locale) {
                NumberFormat format = null;
                if (pattern != null && pattern.trim().length() > 0) {
                    if (STANDARD_NUMBER_FORMAT_DURATION.equals(pattern)) {
                        format = new DurationNumberFormat();
                    } else {
                        format = locale == null ?
                                NumberFormat.getNumberInstance() :
                                NumberFormat.getNumberInstance(locale);
                        if (format instanceof DecimalFormat) {
                            format.setRoundingMode(HALF_UP);
                            ((DecimalFormat) format).applyPattern(pattern);
                        }
                    }
                }
                return format;
            }
        });`
    
    0 讨论(0)
提交回复
热议问题