前言 | 问题背景
在不同的应用场景中,数字格式千变万化,即便强大如Excel,也无法满足所有的数字格式的需求。有用户提出了这样的需求:小数超过两位时,只保留两位且不做进位(例如123.456显示123.45);小数不足两位时,无后缀0(例如123.4就显示123.4);没有小数时只显示整数(例如123就显示123);整数部分需要能够每三位添加一个分位符(例如1234显示1,234)。
那么如何解决此问题做到自定义数字格式呢,本文基于SpreadJS V12版本,如需学习请先更新您的控件版本;
问题分析与解决思路
针对这样的“非典型需求”,我们即无法直接用Excel实现,Spread JS也没有原生的数字格式的支持。原本用户想用条件格式来实现,但实际上Spread JS提供了更加简洁的思路——自定义格式接口,这样用户可以最大限度地实现自己想要的格式。
解决自定义格式的问题,可以分为以下几个步骤:
- 重写GC.Spread.Formatter.GeneralFormatter类的format方法,这个方法接收的第一个参数就是单元格的值,我们可以在format方法中随意拼接修改值的格式和内容,不会影响单元格的真实值,只会改变最终的展示格式(单元格的Text)。
- 为单元格设置自定义样式。
- 定义一个处理数字的方法,返回符合上述用户需求的数字字符串。示例中提供的方法比需求的更强大和灵活,不仅可以实现定制是否四舍五入,还可以自定义分位符与小数点。
示例代码分析
示例中主要做了两件事,一是通过继承GeneralFormatter类来实现自定义数字格式,二是在format方法中实现了自定义数字格式的业务逻辑。下面的代码部分就是第一步,如何通过继承GeneralFormatter来实现自定义数字格式。
var customFormatterTest = {}; customFormatterTest.prototype = GC.Spread.Formatter.GeneralFormatter; // format方法中,第一个参数obj就是当前单元格的值(带类型) 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:要格式化的数字 * 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; } // floor 实现了只舍去不进位的逻辑 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); }
关于葡萄城
赋能开发者!葡萄城公司成立于 1980 年,是全球领先的集开发工具、商业智能解决方案、管理系统设计工具于一身的软件和服务提供商。西安葡萄城是其在中国的分支机构,面向全球市场提供软件研发服务,并为中国企业的信息化提供国际先进的开发工具、软件和研发咨询服务。葡萄城的控件和软件产品在国内外屡获殊荣,在全球被数十万家企业、学校和政府机构广泛应用。