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.

Description
app.vue
index.html
Copy to CodeMine

You can create your own function by inheriting the GC.Spread.CalcEngine.Functions.Function, as shown in the following code:

    function FactorialFunction() {
       this.name = 'FACTORIAL';
       this.maxArgs = 1;
       this.minArgs = 1;
    }
    FactorialFunction.prototype = new GC.Spread.CalcEngine.Functions.Function();
    FactorialFunction.prototype.evaluate = function (arg) {
       // your own evaluate content
    }
    var factorial = new FactorialFunction();
    sheet.addCustomFunction(factorial);

The evaluate function can return a GC.Spread.CalcEngine.CalcArray object to represent the custom function returns an array as following code:

    MyCustomFunction.prototype.evaluate = function (context) {
        return new GC.Spread.CalcEngine.CalcArray([[1, 2, 3]]);
    } 

After you have added your own function, if you want to remove it or clear all custom functions, use the removeCustomFunction or clearCustomFunctions method.

    sheet.removeCustomFunction('FACTORIAL');
    sheet.clearCustomFunctions();
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);