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
styles.css
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-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> import Vue from 'vue'; import '@mescius/spread-sheets-vue' import GC from '@mescius/spread-sheets'; import './styles.css'; let App = Vue.extend({ name: "app", methods:{ initSpread: function (spread) { this.spread = spread; spread.options.allowDynamicArray = true; var 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) { var result = 1; if (arguments.length === 1 && !isNaN(parseInt(arg))) { for (var i = 1; i <= arg; i++) { result = i * result; } return result; } return "#VALUE!"; }; this.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!"; }; this.factorialArray = new FactorialArrayFunction(); }, addCustomFunction: function(e) { var sheet = this.spread.sheets[0]; sheet.addCustomFunction(this.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(this.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)"); }, removeCustomFunction: function(e) { var sheet = this.spread.sheets[0]; sheet.removeCustomFunction("FACTORIAL"); sheet.removeCustomFunction("FACTORIAL.ARRAY"); sheet.recalcAll(true); } } }); new Vue({ render: h => h(App) }).$mount('#app'); </script>
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/vue/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- SystemJS --> <script src="$DEMOROOT$/en/vue/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); System.import('$DEMOROOT$/en/lib/vue/license.js'); </script> </head> <body> <div id="app"></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; 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; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' }, '*.vue': { loader: 'vue-loader' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'css': 'npm:systemjs-plugin-css/css.js', 'vue': 'npm:vue/dist/vue.min.js', 'vue-loader': 'npm:systemjs-vue-browser/index.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' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'js' }, rxjs: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' } } }); })(this);