前言 | 问题背景
在不同的应用场景中,数字格式千变万化,即便强大如Excel,也无法满足所有的数字格式的需求。有用户提出了这样的需求:小数超过两位时,只保留两位且不做进位(例如123.456显示123.45);小数不足两位时,无后缀0(例如123.4就显示123.4);没有小数时只显示整数(例如123就显示123);整数部分需要能够每三位添加一个分位符(例如1234显示1,234)。
本文基于SpreadJS
V12版本,下载请点击。
问题分析与解决思路
针对这样的“非典型需求”,我们即无法直接用Excel实现,Spread
JS也没有原生的数字格式的支持。原本用户想用条件格式来实现,但实际上Spread
JS提供了更加简洁的思路——自定义格式接口,这样用户可以最大限度地实现自己想要的格式。
在官网的学习指南上,有一个简单的示例,感兴趣的可以先移步参考:
https://demo.grapecity.com.cn/SpreadJS/TutorialSample/#/demos/customFormatter
解决自定义格式的问题,可以分为以下几个步骤:
- 重写GC.Spread.Formatter.GeneralFormatter类的format方法,这个方法接收的第一个参数就是单元格的值,我们可以在format方法中随意拼接修改值的格式和内容,不会影响单元格的真实值,只会改变最终的展示格式(单元格的Text)。
- 为单元格设置自定义样式。
- 定义一个处理数字的方法,返回符合上述用户需求的数字字符串。示例中提供的方法比需求的更强大和灵活,不仅可以实现定制是否四舍五入,还可以自定义分位符与小数点。
示例代码分析
示例中主要做了两件事,一是通过继承GeneralFormatter类来实现自定义数字格式,二是在format方法中实现了自定义数字格式的业务逻辑。下面的代码部分就是第一步,如何通过继承GeneralFormatter来实现自定义数字格式。
var customFormatterTest = {};
customFormatterTest.prototype = GC.Spread.Formatter.GeneralFormatter;
customFormatterTest.format = function (obj, conditionalForeColor) {
return number_format(obj, 2, ".", ",");
};
上述代码通过继承GeneralFormatter类,并重写format方法实现了自定义数字格式,在format方法中,第一个参数obj就是当前单元格的值,拿到单元格的值后,可以根据业务需求进行自定义显示格式,方法返回值是一个字符串。
第二部,实现自定义数字格式,注意最后返回值是字符串就行了。
function number_format(number, decimals, dec_point, thousands_sep, isRoundUp) {
number = (number + '').replace(/[^0-9+-Ee.]/g, '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function (n, prec) {
var k = Math.pow(10, prec);
if(isRoundUp){
return '' + Math.round(n * k) / k;
}
return '' + Math.floor(n * k) / k;
};
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
var re = /(-?\d+)(\d{3})/;
while (re.test(s[0])) {
s[0] = s[0].replace(re, "$1" + sep + "$2");
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
}
if(s[1] === ""){
return s.join("");
}
return s.join(dec);
}
完整版的Demo,请点击此处下载。 |