自定义函数

SpreadJS 支持创建自定义函数来扩展计算引擎的能力,满足特定的业务计算需求。自定义函数可以像内置函数一样在公式中使用,支持返回单个值或数组结果,并通过简单的 API 进行添加和移除。

概述 本 Demo 展示了如何创建和使用自定义函数。通过两个阶乘函数示例,演示了自定义函数的基本用法:一个返回单个计算结果,另一个返回数组结果。Demo 还展示了如何添加和移除自定义函数。 实现思路 创建自定义函数类,继承 GC.Spread.CalcEngine.Functions.Function 基类 在构造函数中设置函数名称和参数数量限制(minArgs、maxArgs) 实现 evaluate 方法定义计算逻辑 使用 addCustomFunction 方法将函数添加到工作表 在单元格中使用公式调用自定义函数 使用 removeCustomFunction 方法移除自定义函数 代码解析 创建返回单个值的自定义函数 这段代码创建了一个计算阶乘的自定义函数。name 属性定义函数名称,minArgs 和 maxArgs 限定参数数量为 1。evaluate 方法接收参数并返回计算结果,如果参数无效则返回错误值 #VALUE!。 创建返回数组的自定义函数 这个函数演示了如何返回数组结果。evaluate 方法返回一个 CalcArray 对象,包含从 1 到 n 的阶乘序列。SpreadJS 会自动将数组结果填充到相邻单元格中。需要先启用动态数组功能:spread.options.allowDynamicArray = true。 添加和使用自定义函数 使用 addCustomFunction 方法添加函数后,可以在公式中像内置函数一样使用。函数名不区分大小写。 移除自定义函数 使用 removeCustomFunction 方法移除函数,需要传入函数名称字符串。移除后调用 recalcAll 重新计算工作表,单元格会显示 #NAME? 错误。 运行效果 点击"添加自定义函数"按钮后,工作表中显示 =FACTORIAL(5) 的计算结果(120)和 =FACTORIAL.ARRAY(5) 的数组结果(1, 2, 6, 24, 120) 点击"移除自定义函数"按钮后,公式单元格显示 #NAME? 错误,表示函数已被移除 API 参考 addCustomFunction 方法 fn:自定义函数实例,需继承 GC.Spread.CalcEngine.Functions.Function removeCustomFunction 方法 name:要移除的自定义函数名称字符串 自定义函数属性 name:函数名称 minArgs:最小参数数量 maxArgs:最大参数数量 evaluate(args...):计算逻辑,返回计算结果或 CalcArray 对象
window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 2 }); initSpread(spread); }; function initSpread(spread) { spread.options.allowDynamicArray = true; var sheet = spread.getSheet(0); sheet.setValue(1, 1, '点击 \'添加自定义函数\' 按钮'); sheet.setColumnWidth(1, 225); sheet.setColumnWidth(2, 100); function FactorialFunction() { this.name = "FACTORIAL"; this.maxArgs = 1; this.minArgs = 1; } FactorialFunction.prototype = new GC.Spread.CalcEngine.Functions.Function(); FactorialFunction.prototype.evaluate = function (arg) { var result = 1; if (arguments.length === 1 && !isNaN(parseInt(arg))) { for (var i = 1; i <= arg; i++) { result = i * result; } return result; } return "#VALUE!"; }; var factorial = new FactorialFunction(); function FactorialArrayFunction() { this.name = "FACTORIAL.ARRAY"; this.maxArgs = 1; this.minArgs = 1; } FactorialArrayFunction.prototype = new GC.Spread.CalcEngine.Functions.Function(); FactorialArrayFunction.prototype.evaluate = function (arg) { var t = 1; var result = [[]]; if (arguments.length === 1 && !isNaN(parseInt(arg))) { for (var i = 1; i <= arg; i++) { t = i * t; result[0].push(t); } return new GC.Spread.CalcEngine.CalcArray(result); } return "#VALUE!"; }; var factorialArray = new FactorialArrayFunction(); document.getElementById("addCustomFunction").addEventListener('click',function() { sheet.setValue(3, 1, '公式'); sheet.setValue(3, 2, '=FACTORIAL(5)'); sheet.setValue(4, 1, '结果'); sheet.addCustomFunction(factorial); sheet.setFormula(4, 2, "=factorial(5)"); sheet.setValue(6, 1, '公式'); sheet.setValue(6, 2, '=FACTORIAL.ARRAY(5)'); sheet.setValue(7, 1, '结果'); sheet.addCustomFunction(factorialArray); sheet.setFormula(7, 2, "=FACTORIAL.ARRAY(5)"); }); document.getElementById("removeCustomFunction").addEventListener('click',function() { sheet.removeCustomFunction("FACTORIAL"); sheet.removeCustomFunction("FACTORIAL.ARRAY"); sheet.recalcAll(true); }); };
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta name="spreadjs culture" content="zh-cn" /> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" class="sample-spreadsheets"></div> <div class="options-container"> <div class="option-row"> <input type="button" value="添加自定义函数(阶乘)" id="addCustomFunction" /> <input type="button" value="移除自定义函数(阶乘)" id="removeCustomFunction" /> </div> </div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height:100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; overflow: auto; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; } .option-row { margin-bottom: 12px; } input[type=button] { padding: 4px 6px; margin-bottom: 6px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }