需求背景:部分业务场景中,公式函数的计算逻辑可能与当前xlsx文件计算逻辑不一致,需要根据业务规则重写SpreadJS内置的公式函数。
解决方法:
首选推荐的方法还是自定义公式函数,用自定义函数去完成与excel不一致的计算逻辑,而不是直接重写SpreadJS内置的公式函数。关于自定义公式函数,可自行参考学习指南或论坛其它自定义函数相关文章。
本文着重会介绍如何覆盖SpreadJS内置的一些公式函数。在这里提前需要说明的时,自定义函数如果逻辑处理的不完善,会出现影响其它函数计算结果准确性的问题。因此使用时需要慎重。并且在覆盖了内置函数之后,如果后续其它函数计算上出现问题,追踪问题时先注释掉对应覆盖内置函数相关的代码,排除是由于函数覆盖而带来的问题。
本文以IF函数为例,介绍覆盖IF函数的步骤:
1. 全局移除内置的IF函数。
- GC.Spread.CalcEngine.Functions.removeGlobalFunction("if")
复制代码 2. 自定义IF函数
- MyIf.prototype = new GC.Spread.CalcEngine.Functions.Function("if",3,3,{
- description:"这是一个自定义的IF函数",
- parameter:[
- {
- name:"逻辑判断",
- optional: false,
- repeatable: false
- },{
- name: "逻辑真值",
- optional: false,
- repeatable:false
- },{
- name:"逻辑假值",
- optional: false,
- repeatable: false
- }
- ]
- })
- MyIf.prototype.evaluate = function(){
- // 可以打印出arguments信息,查看具体内容
- let logicValue = arguments[1]
- if(logicValue){
- if(typeof arguments[2] == Object){
- return arguments[2].getSource().getValue(arguments[2].getRow(),arguments[2].getColumn())
- }else{
- return arguments[2]
- }
- }else{
- if(typeof arguments[3] == Object){
- return arguments[3].getSource().getValue(arguments[3].getRow(),arguments[3].getColumn())
- }else{
- return arguments[3]
- }
- }
- return "1"
- }
- MyIf.prototype.acceptsReference = function(){
- // 自定义函数中,需要参数能包含引用单元格位置等上下文信息,添加该参数
- return true
- }
- MyIf.prototype.isContextSensitive = function(){
- // 如果自定义函数时,需要参数返回当前自定义公式所在单元格位置等信息,添加该代码
- return true
- }
复制代码
自定义函数中,evaluate方法中传递的参数与acceptsReference 和isContextSensitive 方法的返回值相关,其中isContextSensitive 返回值为true时,evaluate方法中第一个参数表示当前的spread对象。acceptsReference 返回值为true时,表示传递参数为单元格引用,而不是单元格实际值。
3. 注册自定义的IF函数
- GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("if",new MyIf)
复制代码
|
|