Custom Functions

In SpreadJS, you can create your own function and add it to sheet. In addition to all the 500+ built-in functions, the SpreadJS Calculation Engine also allows you to create your own custom functions for specific business use cases. They can be defined and called as you would any of the built-in functions.

You can create your own function by inheriting the GC.Spread.CalcEngine.Functions.Function, as shown in the following code: The evaluate function can return a GC.Spread.CalcEngine.CalcArray object to represent the custom function returns an array as following code: After you have added your own function, if you want to remove it or clear all custom functions, use the removeCustomFunction or clearCustomFunctions method.
<template> <div class="sample-tutorial"> <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread"> <gc-worksheet> </gc-worksheet> <gc-worksheet> </gc-worksheet> </gc-spread-sheets> <div class="options-container"> <div class="option-row"> <input type="button" value="Add a Custom Function(factorial)" @click="addCustomFunction($event)" /> <input type="button" value="Remove the Custom Function(factorial)" @click="removeCustomFunction($event)" /> </div> </div> </div> </template> <script setup> import '@mescius/spread-sheets-vue'; import GC from "@mescius/spread-sheets"; let mySpread; let factorial; let factorialArray; let initSpread = function (spread) { mySpread = spread; spread.options.allowDynamicArray = true; let sheet = spread.getSheet(0); sheet.setValue(1, 1, 'Press \'Add a Custom Function\' button'); 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) { let result = 1; if (arguments.length === 1 && !isNaN(parseInt(arg))) { for (let i = 1; i <= arg; i++) { result = i * result; } return result; } return "#VALUE!"; }; 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) { let t = 1; let result = [[]]; if (arguments.length === 1 && !isNaN(parseInt(arg))) { for (let i = 1; i <= arg; i++) { t = i * t; result[0].push(t); } return new GC.Spread.CalcEngine.CalcArray(result); } return "#VALUE!"; }; factorialArray = new FactorialArrayFunction(); } let addCustomFunction = function(e) { let sheet = mySpread.sheets[0]; sheet.addCustomFunction(factorial); sheet.setValue(3, 1, 'Formula'); sheet.setValue(3, 2, '=FACTORIAL(5)'); sheet.setValue(4, 1, 'Result'); sheet.setFormula(4, 2, "=factorial(5)"); sheet.addCustomFunction(factorialArray); sheet.setValue(6, 1, 'Formula'); sheet.setValue(6, 2, '=FACTORIAL.ARRAY(5)'); sheet.setValue(7, 1, 'Result'); sheet.setFormula(7, 2, "=FACTORIAL.ARRAY(5)"); } let removeCustomFunction = function(e) { let sheet = mySpread.sheets[0]; sheet.removeCustomFunction("FACTORIAL"); sheet.removeCustomFunction("FACTORIAL.ARRAY"); sheet.recalcAll(true); } </script> <style scoped> #app { height: 100%; } .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; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .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; } </style>
<!DOCTYPE html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>SpreadJS VUE</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/en/vue3/node_modules/systemjs/dist/system.src.js"></script> <script src="./systemjs.config.js"></script> <script src="./compiler.js" type="module"></script> <script> var System = SystemJS; System.import("./src/app.js"); System.import('$DEMOROOT$/en/lib/vue3/license.js'); </script> </head> <body> <div id="app"></div> </body> </html>
(function (global) { SystemJS.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, packageConfigPaths: [ './node_modules/*/package.json', "./node_modules/@mescius/*/package.json", "./node_modules/@babel/*/package.json", "./node_modules/@vue/*/package.json" ], map: { 'vue': "npm:vue/dist/vue.esm-browser.js", 'tiny-emitter': 'npm:tiny-emitter/index.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', "systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js", '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-resources-en': 'npm:@mescius/spread-sheets-resources-en/index.js', '@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js' }, meta: { '*.css': { loader: 'systemjs-plugin-css' }, '*.vue': { loader: "../plugin-vue/index.js" } } }); })(this);