Products

Custom Formulas

Custom formulas provide a powerful mechanism to extend Jspreadsheet functionality beyond standard built-in functions. With custom formulas, you can fetch data from external APIs, manipulate complex data structures, render custom UI elements, and execute JavaScript logic directly within spreadsheet cells.

Important: All custom formula method names must be declared in UPPERCASE letters.

Documentation

Methods

The following methods and properties are available when working with custom formulas.

Method Description
setTracking Adds a cell to the tracking system that automatically updates when worksheet structure changes (row/column insertion).
setTracking(scope: object)
getCellObject Retrieves the cell object at specified coordinates. Creates the object if it doesn't exist.
getCellObject(x: number, y: number)

Formula Scope Properties

Within a custom formula, you have access to the current cell's coordinates through this.x and this.y properties, as well as the worksheet instance via this.instance. This context enables the creation of sophisticated formulas that can interact with external APIs, access other cells, and perform complex operations within the spreadsheet environment.

let COORDS = function() {
    // Return the coordinates to the cell
    return this.x + ',' + this.y;
}

Declare New Methods

Register custom formulas in your spreadsheet using the formula.setFormula method as demonstrated below.

formula.setFormula({ COORDS });

Examples

Using DOM elements

This example demonstrates how to create a custom formula that returns a DOM element to be rendered within a cell.

<html>
<script src="https://jspreadsheet.com/v12/jspreadsheet.js"></script>
<script src="https://jsuites.net/v6/jsuites.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v12/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v6/jsuites.css" type="text/css" />

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/formula-pro/dist/index.min.js"></script>

<div id="spreadsheet"></div>

<script>
// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Set the formula pro extension
jspreadsheet.setExtensions({ formula });

// Create a custom JavaScript method (uppercase)
const COLORIZE = function(v) {
    let d = document.createElement('span');
    d.style.color = v;
    d.innerText = v.toUpperCase();
    return d;
}

// Send custom formula to the correct scope
formula.setFormula({ COLORIZE })

// Create spreadsheet
jspreadsheet(document.getElementById('spreadsheet'), {
    worksheets: [{
        data: [
            [ 'red', '=COLORIZE(A1)' ],
            [ 'green', '=COLORIZE(A2)' ],
            [ 'blue', '=COLORIZE(A3)' ],
        ],
        columns: [
            { type: 'text', width:'300' },
            { type: 'text', width:'200' },
        ]
    }]
});
</script>
</html>
import React, {useRef} from "react";
import {Spreadsheet, Worksheet, jspreadsheet} from "@jspreadsheet/react";
import formula from "@jspreadsheet/formula-pro";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Create a custom JavaScript method (uppercase)
const COLORIZE = function (v) {
    let d = document.createElement('span');
    d.style.color = v;
    d.innerText = v.toUpperCase();
    return d;
}

// Send custom formula to the correct scope
formula.setFormula({COLORIZE})

// Extensions
const extensions = {formula};

// Create the component
export default function App() {
    // Array with all the data grids
    const spreadsheet = useRef();
    // Data
    const data = [
        ['red', '=COLORIZE(A1)'],
        ['green', '=COLORIZE(A2)'],
        ['blue', '=COLORIZE(A3)'],
    ]
    const columns = [
        {type: 'text', width: '300px'},
        {type: 'text', width: '200px'},
    ]

    // Render data grid component
    return (
        <Spreadsheet ref={spreadsheet} extensions={extensions}>
            <Worksheet data={data} columns={columns}/>
        </Spreadsheet>
    );
}
<template>
    <Spreadsheet ref="spreadsheet" :extensions="extensions">
        <Worksheet :data="data" :columns="columns" />
    </Spreadsheet>
</template>

<script>
import { Spreadsheet, Worksheet } from "@jspreadsheet/vue";
import formula from "@jspreadsheet/formula-pro";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Create a custom JavaScript method (uppercase)
const COLORIZE = function(v) {
    let d = document.createElement('span');
    d.style.color = v;
    d.innerText = v.toUpperCase();
    return d;
}

// Send custom formula to the correct scope
formula.setFormula({ COLORIZE })

// Extensions
const extensions = { formula };

// Create data grid component
export default {
    components: {
        Spreadsheet,
        Worksheet,
    },
    data() {
        // Data
        const data = [
            [ 'red', '=COLORIZE(A1)' ],
            [ 'green', '=COLORIZE(A2)' ],
            [ 'blue', '=COLORIZE(A3)' ],
        ]
        const columns = [
            { type: 'text', width:'300px' },
            { type: 'text', width:'200px' },
        ]

        return {
            extensions,
            data,
            columns
        };
    }
}
</script>
import { Component, ViewChild, ElementRef, AfterViewInit } from "@angular/core";
import jspreadsheet from "jspreadsheet";
import formula from "@jspreadsheet/formula-pro";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

jspreadsheet.setExtensions({ formula })

// Create a custom JavaScript method (uppercase)
const COLORIZE = (v: string) => {
    let d = document.createElement('span');
    d.style.color = v;
    d.innerText = v.toUpperCase();
    return d;
}

// Send custom formula to the correct scope
formula.setFormula({ COLORIZE })

// Create the data grid component
@Component({
    standalone: true,
    selector: "app-root",
    template: `<div #spreadsheet></div>`,
})
export class AppComponent implements AfterViewInit {
    @ViewChild("spreadsheet") spreadsheet: ElementRef;
    // Worksheets
    worksheets: jspreadsheet.worksheetInstance[];
    // Create a new data grid
    ngAfterViewInit() {
        // Create spreadsheet
        this.worksheets = jspreadsheet(this.spreadsheet.nativeElement, {
            worksheets: [{
                data: [
                    [ 'red', '=COLORIZE(A1)' ],
                    [ 'green', '=COLORIZE(A2)' ],
                    [ 'blue', '=COLORIZE(A3)' ],
                ],
                columns: [
                    { type: 'text', width: 300  },
                    { type: 'text', width: 200  },
                ]
            }]
        });
    }
}

Formula Chain

This example demonstrates a custom formula that calculates the sum of all values in the same column above the current cell. Since the formula doesn't explicitly reference other cells, it manually creates a dependency chain to ensure automatic updates when column values change.

<html>
<script src="https://jspreadsheet.com/v12/jspreadsheet.js"></script>
<script src="https://jsuites.net/v6/jsuites.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v12/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v6/jsuites.css" type="text/css" />

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/formula-pro/dist/index.min.js"></script>

<div id="spreadsheet"></div>

<script>
// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Set the formula pro extension
jspreadsheet.setExtensions({ formula });

// Create a custom JavaScript method (uppercase)
const SUMCOL = function () {
    // Update a formula chain when worksheet structure changes
    this.instance.setTracking.call(this, true);
    // Parent
    let parent = this.instance.getCellObject(this.x, this.y);
    // Get the column data
    let data = this.instance.getColumnData(this.x);
    // Total
    let total = 0;
    // Sum all values in the column from zero to the row number
    for (let y = 0; y < this.y; y++) {
        // Get the cell object
        let cell = this.instance.getCellObject(this.x, y);
        // Total
        total += parseInt(data[y]);
        // Formula chain
        if (typeof(cell.chain) === 'undefined') {
            cell.chain = new Map;
        }
        // Keep reference in the formula
        cell.chain.set(parent, null);
    }

    return total;
}

// Send custom formula to the correct scope
formula.setFormula({ SUMCOL })

// Create the spreadsheet
jspreadsheet(document.getElementById('spreadsheet'), {
    worksheets: [{
        data: [
            [ 'Apple', 931 ],
            [ 'Google', 431 ],
            [ 'Amazon', 534 ],
            [ 'Total', '=SUMCOL()' ],
        ],
        minDimensions: [6,4],
    }]
});
</script>
</html>
import React, { useRef } from "react";
import { Spreadsheet, Worksheet, jspreadsheet } from "@jspreadsheet/react";
import formula from "@jspreadsheet/formula-pro";
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Extensions
jspreadsheet.setExtensions({ formula });

// Create a custom JavaScript method (uppercase)
const SUMCOL = function () {
    // Update formula chain when worksheet structure changes
    this.instance.setTracking.call(this, true);
    // Get the column data
    let data = this.instance.getColumnData(this.x);
    // Total
    let total = 0;
    // Sum all values in the column from zero to the row number
    for (let y = 0; y < this.y; y++) {
        // Get the cell object
        let cell = this.instance.getCellObject(this.x, y);
        // Total
        total += parseInt(data[y]);
        // Formula chain
        if (typeof(cell.chain) === 'undefined') {
            cell.chain = new Map;
        }
        // Keep reference in the formula
        cell.chain.set(this.instance.records[this.y][this.x], this.instance);
    }

    return total;
}

// Send custom formula to the correct scope
formula.setFormula({ SUMCOL })

// Create the component
export default function App() {
    // Array with all the data grids
    const spreadsheet = useRef();
    // Data
    const data = [
        [ 'Apple', 931 ],
        [ 'Google', 431 ],
        [ 'Amazon', 534 ],
        [ 'Total', '=SUMCOL()' ],
    ]

    // Render data grid component
    return (
        <Spreadsheet ref={spreadsheet} extensions={{ formula }}>
            <Worksheet data={data} />
        </Spreadsheet>
    );
}
<template>
  <Spreadsheet ref="spreadsheet">
    <Worksheet :data="data" />
  </Spreadsheet>
</template>

<script>
import { Spreadsheet, Worksheet, jspreadsheet } from '@jspreadsheet/vue';
import formula from '@jspreadsheet/formula-pro';
import 'jsuites/dist/jsuites.css';
import 'jspreadsheet/dist/jspreadsheet.css';

// Add here your data grid license
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Extensions
jspreadsheet.setExtensions({ formula });

// Create a custom JavaScript method (uppercase)
const SUMCOL = function () {
  // Update a formula chain when a new row is added
  this.instance.setTracking.call(this, true);
  // Get the column data
  let data = this.instance.getColumnData(this.x);
  // Total
  let total = 0;
  // Sum all values in the column from zero to the row number
  for (let y = 0; y < this.y; y++) {
    // Get the cell object
    let cell = this.instance.getCellObject(this.x, y);
    // Total
    total += parseInt(data[y]);
    // Formula chain
    if (typeof cell.chain === 'undefined') {
      cell.chain = new Map();
    }
    // Keep reference in the formula
    cell.chain.set(this.instance.records[this.y][this.x], this.instance);
  }

  return total;
};

// Send custom formula to the correct scope
formula.setFormula({ SUMCOL });

export default {
  components: {
    Spreadsheet,
    Worksheet,
  },
  data() {
    // Data
    const data = [
      ['Apple', 931],
      ['Google', 431],
      ['Amazon', 534],
      ['Total', '=SUMCOL()'],
    ];

    return {
      data,
    };
  },
};
</script>
import { Component, ViewChild, ElementRef, AfterViewInit } from "@angular/core";
import jspreadsheet from "jspreadsheet";
import formula from "@jspreadsheet/formula-pro";
import 'jsuites/dist/jsuites.css';
import 'jspreadsheet/dist/jspreadsheet.css';

// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('N2Y1NzJjMGUyOTI0YjY0MDVmNDQ3YjM4M2JjMzM3OTEyZmQ3YmVmYmM2YjczZGJmNWFmZmMzYjQwYzgwZDNlNzIxODI4NDM5MDY2MTg1N2RmYmFmYTgwYmExMDBlMTE0MmU1YWI1NjAxODMwNzc5NmQ2MGRjMGZhMmMxMmU2ODksZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azFPREl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

// Set extensions
jspreadsheet.setExtensions({ formula });

// Create a custom JavaScript method (uppercase)
const SUMCOL = function (this: any) {
    // Update formula chain when worksheet structure changes
    this.instance.setTracking.call(this, true);
    // Get the column data
    let data = this.instance.getColumnData(this.x);
    // Total
    let total = 0;
    // Sum all values in the column from zero to the row number
    for (let y = 0; y < this.y; y++) {
        // Get the cell object
        let cell = this.instance.getCellObject(this.x, y);
        // Total
        total += parseInt(data[y]);
        // Formula chain
        if (typeof(cell.chain) === 'undefined') {
            cell.chain = new Map;
        }
        // Keep reference in the formula
        cell.chain.set(this.instance.records[this.y][this.x], this.instance);
    }

    return total;
}

// Send custom formula to the correct scope
formula.setFormula({ SUMCOL })

@Component({
    standalone: true,
    selector: "app-root",
    template: `<div #spreadsheet></div>`,
})
export class AppComponent implements AfterViewInit {
    @ViewChild("spreadsheet") spreadsheet: ElementRef;
    // Worksheets
    worksheets: jspreadsheet.worksheetInstance[];
    // Create a new data grid
    ngAfterViewInit() {
        // Create spreadsheet
        this.worksheets = jspreadsheet(this.spreadsheet.nativeElement, {
            worksheets: [
                {
                    data: [
                        [ 'Apple', 931 ],
                        [ 'Google', 431 ],
                        [ 'Amazon', 534 ],
                        [ 'Total', '=SUMCOL()' ],
                    ],
                    minDimensions: [6,4],
                }
            ]
        });
    }
}

More resources