Winny 发表于 2023-11-6 14:02:51

重写SpreadJS内置公式函数

需求背景:部分业务场景中,公式函数的计算逻辑可能与当前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
    if(logicValue){
       if(typeof arguments == Object){
      return arguments.getSource().getValue(arguments.getRow(),arguments.getColumn())
       }else{
      return arguments
       }
    }else{
      if(typeof arguments == Object){
      return arguments.getSource().getValue(arguments.getRow(),arguments.getColumn())
       }else{
      return arguments
       }
    }
    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)

页: [1]
查看完整版本: 重写SpreadJS内置公式函数