最近在用FineReport这个工具进行系统的报表开发,发现在导出报表时要求按币别和精度要求动态的格式化金额显示,工具本身不支持这项功能,最后经过研究发现了通过条件属性加上自定义函数的方式可以完美解决该问题,代码如下:
package com.xxx.report.function;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.fr.base.FRContext;
import com.fr.report.script.NormalFunction;
/**
* 格式化货币, 为货币加上前缀并且保留合适的小数位,并对末位进行四舍五入处理
*/
public class CcyRender extends NormalFunction {
private static final long serialVersionUID = 1L;
/**
* params[0]: 需要格式化的货币值
* params[1]: 货币前缀
* params[2]: 货币精度
* @see com.fr.report.script.Function#run(java.lang.Object[])
*/
public Object run(Object[] params) {
String target = "0.00d"; // 目标值
String prefix = "¥"; // 前缀
int scale = 2; // 精度
try {
target = String.valueOf(params[0]);
prefix = String.valueOf("" + params[1]);
scale = Integer.valueOf("" + params[2]);
} catch (Exception ex) {
// ignore the exception, return;
FRContext.getLogger().log(Level.WARNING, ex.getMessage(), ex);
}
// 对小数位进行四舍五入
try {
BigDecimal d = new BigDecimal(target).setScale(scale, RoundingMode.HALF_UP);
target = String.valueOf(d);
} catch (Exception ex) {
// ignore
FRContext.getLogger().log(Level.WARNING, ex.getMessage(), ex);
}
FRContext.getLogger().log(Level.INFO, " --> " + target);
final String regex = "^([^\\.]*\\d+)(\\d{3}.*)$"; // 每3位数字用逗号分隔
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(target);
while (m.find()) {
target = m.group(1) + "," + m.group(2);
m = p.matcher(target);
}
String res;
if (target.charAt(0) == '-') {
res = '-' + prefix + target.substring(1);
} else {
res = prefix + target;
}
return res;
}
public static void main(String[] args) {
Object res = new CcyRender().run(new Object[]{"11232213213216789.1235", "$", 3});
System.out.println(res);
}
}