java 如何在 Jasper Reports 中为十进制数指定 RoundingMode

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16899298/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 00:19:12  来源:igfitidea点击:

How to specify RoundingMode for decimal numbers in Jasper Reports

javajasper-reportsrounding

提问by mauretto

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_EVENrounding mode and this is not correct in my case.

我将 Java 与 Jasper Reports 一起使用,并希望使用此格式掩码格式化十进制值"#,##0.00"。乍一看,一切都很好,但我发现我的十进制值是使用RoundingMode.HALF_EVEN舍入模式舍入的,这在我的情况下是不正确的。

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

是否可以指定其他舍入模式(我需要HALF_DOWN模式)?

回答by Alex K

You can use the scriptlets mechanism.

您可以使用scriptlets 机制

The sample

样品

  • Java class
  • Java类
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)
  • 结果将是(在iReport 中预览)

The report in iReport

iReport 中的报告

Another solution

另一种解决方案

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

另一种方法是使用BigDecimal.setScale(int, java.math.RoundingMode)方法(对于字段):

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

or just (for BigDecimalfield):

或只是(对于BigDecimal字段):

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


More info about the scriptletsin JR: Scriptlets

有关更多信息小脚本JR小脚本

回答by D.Shev

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.

您可以通过扩展默认 JR 格式工厂 (net.sf.jasperreports.engine.util.DefaultFormatFactory) 并通过 JRParameter.REPORT_FORMAT_FACTORY 参数发送扩展工厂的实例来更改数字格式化程序的默认舍入模式。

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

可以通过 setRoundingMode() 方法更改 java.text.DecimalFormat 实例的舍入模式。

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

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;
        }
    });`