找回密码
 立即注册

QQ登录

只需一步,快速开始

Winny

超级版主

130

主题

246

帖子

1528

积分

超级版主

Rank: 8Rank: 8

积分
1528
Winny
超级版主   /  发表于:2023-11-6 14:02  /   查看:676  /  回复:0
需求背景:部分业务场景中,公式函数的计算逻辑可能与当前xlsx文件计算逻辑不一致,需要根据业务规则重写SpreadJS内置的公式函数。

解决方法:
首选推荐的方法还是自定义公式函数,用自定义函数去完成与excel不一致的计算逻辑,而不是直接重写SpreadJS内置的公式函数。关于自定义公式函数,可自行参考学习指南或论坛其它自定义函数相关文章。
本文着重会介绍如何覆盖SpreadJS内置的一些公式函数。在这里提前需要说明的时,自定义函数如果逻辑处理的不完善,会出现影响其它函数计算结果准确性的问题。因此使用时需要慎重。并且在覆盖了内置函数之后,如果后续其它函数计算上出现问题,追踪问题时先注释掉对应覆盖内置函数相关的代码,排除是由于函数覆盖而带来的问题。
本文以IF函数为例,介绍覆盖IF函数的步骤:
1. 全局移除内置的IF函数。
  1. GC.Spread.CalcEngine.Functions.removeGlobalFunction("if")
复制代码
2. 自定义IF函数
  1. MyIf.prototype = new GC.Spread.CalcEngine.Functions.Function("if",3,3,{
  2.     description:"这是一个自定义的IF函数",
  3.     parameter:[
  4.         {
  5.             name:"逻辑判断",
  6.             optional: false,
  7.             repeatable: false
  8.         },{
  9.             name: "逻辑真值",
  10.             optional: false,
  11.             repeatable:false
  12.         },{
  13.             name:"逻辑假值",
  14.             optional: false,
  15.             repeatable: false
  16.         }
  17.     ]
  18. })
  19. MyIf.prototype.evaluate = function(){
  20.     // 可以打印出arguments信息,查看具体内容
  21.     let logicValue = arguments[1]
  22.     if(logicValue){
  23.        if(typeof arguments[2] == Object){
  24.         return arguments[2].getSource().getValue(arguments[2].getRow(),arguments[2].getColumn())
  25.        }else{
  26.         return arguments[2]
  27.        }
  28.     }else{
  29.         if(typeof arguments[3] == Object){
  30.         return arguments[3].getSource().getValue(arguments[3].getRow(),arguments[3].getColumn())
  31.        }else{
  32.         return arguments[3]
  33.        }
  34.     }
  35.     return "1"
  36. }

  37. MyIf.prototype.acceptsReference = function(){
  38.     // 自定义函数中,需要参数能包含引用单元格位置等上下文信息,添加该参数
  39.     return true
  40. }
  41. MyIf.prototype.isContextSensitive  = function(){
  42.     // 如果自定义函数时,需要参数返回当前自定义公式所在单元格位置等信息,添加该代码
  43.     return true
  44. }
复制代码

自定义函数中,evaluate方法中传递的参数与acceptsReferenceisContextSensitive 方法的返回值相关,其中isContextSensitive 返回值为true时,evaluate方法中第一个参数表示当前的spread对象。acceptsReference 返回值为true时,表示传递参数为单元格引用,而不是单元格实际值。
3. 注册自定义的IF函数
  1. GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("if",new MyIf)
复制代码


0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部