函数是将重复且复杂的逻辑封装为一个独立的单元,从而实现重复利用,在日常开发场景,我们经常会借助函数完成相关逻辑的实现。
苍穹平台已预置了大量技术类和业务类的函数,但由于平台的通用性,无法完全满足所有场景的需求。因此,需要ISV伙伴和客户进行自定义扩展,尽管苍穹平台提供函数的扩展能力,但其操作相对复杂,用户体验有待提升。
基于以上背景,苍穹推出表达式函数自定义功能,以简化函数的扩展过程,实现配置化操作,从而降低使用者的扩展难度,提升便利性。通过集中管理列表,用户可以更方便地管理和维护自定义函数。
适用版本
该功能适用版本为苍穹V6.0.1以上。
功能介绍
本功能主要是为了实现函数的配置化的扩展能力,三步即可完成配置步骤:执行类编写→新建自定义函数→自定义函数使用。
函数根据传入参数的不同,可以分为两个类型:
1、有参函数:需要传递参数的函数,函数运算时,仅需要当前参数进行运算。
2、无参函数:依赖当前运行上下文,函数运算时,需要获取上下文中的对象进行运算。
接下来以有参数函数为例,编写一个获取四舍五入值的函数,即开发一个公共函数,对传入数值进行四舍五入运算,返回四舍五入后的值。此公共函数是一个有参函数,参数需要传入数值字段,指定四舍五入的小数精度。
第一步:编写“获取四舍五入值的函数”的核心执行类。
编写小贴士
实现函数执行类函数的执行类,必须实现接口 BOSUDFunction,接口方法介绍如下:
1. package kd.bos.newdevportal.domaindefine.sample.function;
2. import kd.bos.entity.formula.ExpressionContext;
3. import kd.bos.entity.function.BOSUDFunction;
4. import kd.bos.formula.excel.FormulaException;
5. import java.math.BigDecimal;
6. import java.math.BigInteger;
7. /**
8. * 自定义函数示例:四设五入(通用函数):kdtest_MyRound(numberic, precision)
9. */
10. public class MyRound implements BOSUDFunction {
11.
12. /**
13. * 返回函数名称:可以和类名不同,但须和函数编码保持一致(增加开发商前缀),表达式中以此为函数名
14. *
15. * @return
16. */
17. @Override
18. public String getName() {
19. return "kdtest_MyRound";
20. }
21.
22. /**
23. * 传入函数上下文,创建函数执行实例
24. * 如果函数执行需要依赖上下文对象,可在构造函数执行实例时,传入上下文对象,然后在call方法内就可以调用上下文对象
25. * @param expContext 函数执行上下文对象,基于此获取函数隐含的参数值
26. * @return 返回本对象的实例
27. */
28. @Override
29. public BOSUDFunction getInstance(ExpressionContext expContext) {
30. return new MyRound();
31. }
32. /**
33. * 不带参数的构造函数:必须提供
34. */
35. public MyRound() {
36. }
37. /**
38. * 传入执行参数,执行函数
39. * @param objects 参数
40. * @return 返回执行结果
41. */
42. @Override
43. public Object call(Object... objects) {
44. if(objects.length!=2) {
45. throw new FormulaException(this.getName() + " has two params, format: (<numeric>,<precision>)");
46. }
47.
48. Object obj = objects[0];
49. Object v2 = objects[1];
50. if(obj==null) {
51. return 0;
52. }
53. else if(!(obj instanceof Number) || !(v2 instanceof Number)) {
54. throw new FormulaException(this.getName() + " params must be numeric");
55. }
56.
57. int scale = ((Number)v2).intValue();
58.
59. if (obj instanceof Integer || obj instanceof Long || obj instanceof BigInteger) {
60. // 整数不需要四设五入,直接返回原值
61. return obj;
62. }
63. else if (obj instanceof BigDecimal) {
64. // BigDecimal,保持原始类型返回
65. BigDecimal r = ((BigDecimal)obj).setScale(scale, BigDecimal.ROUND_UP);
66. if (scale > 0) {
67. return r;
68. }
69. else {
70. return r.intValue();
71. }
72. }
73. else {
74. BigDecimal bd = new BigDecimal(obj.toString());
75. BigDecimal r = bd.setScale(scale, BigDecimal.ROUND_UP);
76.
77. if(scale>0) {
78. return r.doubleValue();
79. } else {
80. return r.intValue();
81. }
82. }
83. }
84. }
第二步,执行类编写完成后,在表达式函数自定义功能中定义函数。
功能路径:【开发服务云】→【新版开发平台】→【模型扩展】→【规则】→【函数定义】。
进入“函数定义”菜单新增函数,维护相关字段信息,具体字段信息请参考文中的相关推荐。
以上已经完成了最关键两步,此时函数已是可用状态。
第三,使用自定义函数。
进入开发平台设计器进行测试运用。
点击业务规则,进行函数配置,可以看到自定义函数会统一放置在扩展函数节点下。
选择函数,配置参数点击确认后,这时在调用表达式中出现该函数。
注意事项
1、 不同函数有不同适用场景,在选择适用场景一定要注意,比如在单据上适用的函数、不一定在BOTP场景中适用,请认真评估。
2、因为函数暂未支持批量处理,编写函数时,应该对函数性能有所考量。
相关链接
表达式函数自定义功能详细说明:
https://developer.kingdee.com/article/494172099104366592?productLineId=29&isKnowledge=2
划重点
1、简单配置式的函数扩展能力,降低函数扩展难度,提升使用者体验。
2、对扩展函数实现列表集中管理,提升扩展函数管理的统一管理能力。