Products

Getting Started with Jspreadsheet CE v5

Overview

Jspreadsheet CE, formerly jExcel, is a free, lightweight JavaScript spreadsheet library to help developers bring Excel-like data grids and spreadsheet features to their applications. The library enables developers to build robust data management interfaces using React, Angular or pure JavaScript.

Why Choose Jspreadsheet CE?

  • Create rich, interactive data grid interfaces
  • Handle complex data inputs with Excel-like functionality
  • Direct Excel compatibility: Copy and paste using standard shortcuts
  • Proven success across thousands of implementations
  • Lightweight, fast, and intuitive
  • Easy integration with third-party plugins
  • Built for collaboration and sharing

Installation

Choose one of the following installation options:

NPM

Install jspreadsheet using NPM:

npm install jspreadsheet-ce@5

CDN

Include jspreadsheet directly from JSDelivr CDN:

<script src="https://cdn.jsdelivr.net/npm/jspreadsheet-ce@5/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jspreadsheet-ce@5/dist/jspreadsheet.min.css" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/jsuites@5/dist/jsuites.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jsuites@5/dist/jsuites.min.css" type="text/css" />

Download

Download and run jspreadsheet on your server or local machine:

https://bossanova.uk/jspreadsheet/v5/jspreadsheet.zip

License

This software is distributed under the MIT license.

Documentation

Global methods and properties

Method Description
Create a new spreadsheet.
jspreadsheet(element: HTMLDivElement | HTMLTableElement, options: SpreadsheetOptions): WorksheetInstance[];
Destroy a given spreadsheet.
jspreadsheet.destroy(element: JspreadsheetInstanceElement, destroyEventHandlers?: boolean): void;
Destroy all spreadsheets in all namespaces.
jspreadsheet.destroyAll(): void;
Translate Jspreadsheet components and extensions.
jspreadsheet.setDictionary(translations: Record<string, string>): void;
Get a worksheet instance by name and namespace.
jspreadsheet.getWorksheetInstanceByName(worksheetName: string | null | undefined, namespace: string): WorksheetInstance | Record<string, WorksheetInstance>;

Examples

Create a new data grid

You can create a new data grid with spreadsheet-like controls from an HTML table element, a JS array, a CSV, a JSON file or an Excel XLSX file.

<html>
<script src="https://bossanova.uk/jspreadsheet/v5/jspreadsheet.js"></script>
<script src="https://jsuites.net/v5/jsuites.js"></script>
<link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v5/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v5/jsuites.css" type="text/css" />

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />

<div id='spreadsheet'></div>

<script>
// Create a new spreadsheet
jspreadsheet(document.getElementById('spreadsheet'), {
    worksheets: [{
        minDimensions: [6,6],
    }]
});
</script>
</html>
import React, { useRef } from "react";
import { Spreadsheet, Worksheet } from "@jspreadsheet-ce/react";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/style.css";

export default function App() {
    // Spreadsheet array of worksheets
    const spreadsheet = useRef();

    // Render component
    return (
        <>
            <Spreadsheet ref={spreadsheet}>
                <Worksheet minDimensions={[6,6]} />
            </Spreadsheet>
        </>
    );
}
<template>
    <Spreadsheet ref="spreadsheet">
        <Worksheet :minDimensions="[6,6]" />
    </Spreadsheet>
</template>

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

export default {
    components: {
        Spreadsheet,
        Worksheet,
    }
};
</script>

import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet-ce";

import "jspreadsheet-ce/dist/jspreadsheet.css";
import "jsuites/dist/jsuites.css";

@Component({
    standalone: true,
    selector: "app-root",
    template: `<div #spreadsheet></div>`
})
export class AppComponent {
    @ViewChild("spreadsheet") spreadsheet: ElementRef;
    // Worksheets
    worksheets: jspreadsheet.worksheetInstance[];
    // Create a new data grid
    ngAfterViewInit() {
        // Create spreadsheet
        this.worksheets = jspreadsheet(this.spreadsheet.nativeElement, {
            worksheets: [
                minDimensions: [6,6]
            }]
        });
    }
}

Destroying The Data Grid

The following example shows how to dynamically destroy and recreate a new data grid.

<html>
<script src="https://bossanova.uk/jspreadsheet/v5/jspreadsheet.js"></script>
<script src="https://jsuites.net/v5/jsuites.js"></script>
<link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v5/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v5/jsuites.css" type="text/css" />

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />

<div id='jspreadsheet'></div>

<p><input type='button' value='Destroy' id="btn1" /> <input type='button' value='Create' id="btn2" /></p>

<script>
// Create a new spreadsheet
let create = function() {
    if (document.getElementById('jspreadsheet').spreadsheet) {
        destroy();
    }

    jspreadsheet(document.getElementById('jspreadsheet'), {
    	worksheets: [ { minDimensions:[5,5] } ]
    });
}

// Destroy the spreadsheet
let destroy = function() {
    jspreadsheet.destroy(document.getElementById('jspreadsheet'));
}

// Create the spreadsheet
jspreadsheet(document.getElementById('jspreadsheet'), {
    worksheets: [{
        minDimensions: [5,5],
    }]
});

document.getElementById("btn1").onclick = () => destroy()
document.getElementById("btn2").onclick = () => create()
</script>
</html>
import React, { useRef, useEffect } from "react";
import { jspreadsheet } from "@jspreadsheet-ce/react";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/dist/jspreadsheet.css";

export default function App() {
    // Spreadsheet array of worksheets
    const spreadsheet = useRef();
    const instance = useRef();

		const destroy = function() {
  	      jspreadsheet.destroy(spreadsheet.current);
		}

		const create = function() {
  	      if (instance.current) {
  	          destroy();
  	      }
	
  	      jspreadsheet(spreadsheet.current, {
  	          worksheets: [ { minDimensions:[5,5] } ]
  	      });
		}

    useEffect(() => {
        if (!instance.current && spreadsheet.current) {
            instance.current = jspreadsheet(spreadsheet.current, {
                worksheets: [ { minDimensions:[5,5] } ]
            })
        }
    }, [])

    // Render component
    return (
        <>
            <div ref={spreadsheet}></div>
						<button onClick={destroy}>Destroy</button>
						<button onClick={create}>Create</button>
        </>
    );
}
<template>
  <div>
    <div ref="spreadsheet"></div>
    <button @click="destroy">Destroy</button>
    <button @click="create">Create</button>
  </div>
</template>

<script>
import { ref, onMounted } from "vue";
import { jspreadsheet } from "@jspreadsheet-ce/vue";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/dist/jspreadsheet.css";

export default {
  name: "App",
  setup() {
    const spreadsheet = ref(null);
    let instance = null;

    const destroy = () => {
      if (instance) {
        jspreadsheet.destroy(spreadsheet.value);
        instance = null;
      }
    };

    const create = () => {
      if (instance) {
        destroy();
      }
      instance = jspreadsheet(spreadsheet.value, {
        worksheets: [{ minDimensions: [5, 5] }],
      });
    };

    onMounted(() => {
      if (!instance && spreadsheet.value) {
        instance = jspreadsheet(spreadsheet.value, {
          worksheets: [{ minDimensions: [5, 5] }],
        });
      }
    });

    return {
      spreadsheet,
      destroy,
      create,
    };
  },
};
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet-ce";

import "jspreadsheet-ce/dist/jspreadsheet.css";
import "jsuites/dist/jsuites.css";

@Component({
    standalone: true,
    selector: "app-spreadsheet",
    template: `
        <div #spreadsheet id="jspreadsheet"></div>
        <p>
            <button (click)="destroy()">Destroy</button>
            <button (click)="create()">Create</button>
        </p>
    `,
})
export class SpreadsheetComponent {
    @ViewChild("spreadsheet") spreadsheetRef: ElementRef;
    worksheets: jspreadsheet.worksheetInstance[];

    ngAfterViewInit() {
        this.initialCreate();
    }

    initialCreate() {
        this.worksheets = jspreadsheet(this.spreadsheetRef.nativeElement, {
            worksheets: [{
                minDimensions: [5, 5]
            }]
        });
    }

    create() {
        if (this.spreadsheetRef.nativeElement.spreadsheet) {
            this.destroy();
        }

        this.worksheets = jspreadsheet(this.spreadsheetRef.nativeElement, {
            worksheets: [{
                minDimensions: [5, 5]
            }]
        });
    }

    destroy() {
        jspreadsheet.destroy(this.spreadsheetRef.nativeElement);
    }
}

Importing Spreadsheet Files

Using TabularJS for File Import

TabularJS imports spreadsheet files into Jspreadsheet. It supports 16+ file formats including Excel, OpenDocument, CSV, and converts them to JSON format compatible with Jspreadsheet.

Features

  • Supports .xlsx, .xls, .ods, .csv, .tsv, HTML tables, and legacy formats
  • Extracts data, formulas, styles, and merged cells
  • Pure JavaScript implementation with no external dependencies
  • Compatible with Vanilla JS, React, Vue, and Angular

Installation

npm install tabularjs

Basic Usage

The library provides an async function that accepts a file and returns Jspreadsheet-compatible data:

<html>
<script src="https://bossanova.uk/jspreadsheet/v5/jspreadsheet.js"></script>
<link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v5/jspreadsheet.css" type="text/css" />
<script src="https://jsuites.net/v5/jsuites.js"></script>
<link rel="stylesheet" href="https://jsuites.net/v5/jsuites.css" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/tabularjs/dist/tabularjs.min.js"></script>

<div id="spreadsheet"></div>
<input type="file" id="fileInput" accept=".xlsx,.xls,.ods,.csv" />

<script>
let root = document.getElementById('spreadsheet');

document.getElementById('fileInput').addEventListener('change', async (e) => {
    const file = e.target.files[0];
    if (file) {
        const result = await tabularjs(file);
        // Destroy
        jspreadsheet.destroy(root);
        // Create
        jspreadsheet(root, result);
    }
});
</script>
</html>
import React, { useRef } from "react";
import jspreadsheet from "jspreadsheet-ce";
import tabularjs from "tabularjs";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/dist/jspreadsheet.css";

export default function App() {
    const spreadsheet = useRef(null);
    const inputRef = useRef(null);

    const handleFileLoad = async (e) => {
        const file = e.target.files[0];
        if (file) {
            const result = await tabularjs(file);
            jspreadsheet(spreadsheet.current, result);
        }
    };

    return (
        <div>
            <div ref={spreadsheet}></div>
            <input
                ref={inputRef}
                type="file"
                onChange={handleFileLoad}
                accept=".xlsx,.xls,.ods,.csv"
                style={{ display: 'none' }}
            />
            <button onClick={() => inputRef.current.click()}>
                Import Spreadsheet
            </button>
        </div>
    );
}
<template>
    <div>
        <div ref="spreadsheet"></div>
        <input
            ref="fileInput"
            type="file"
            @change="handleFileLoad"
            accept=".xlsx,.xls,.ods,.csv"
            style="display: none"
        />
        <button @click="$refs.fileInput.click()">Import Spreadsheet</button>
    </div>
</template>

<script>
import jspreadsheet from "jspreadsheet-ce";
import tabularjs from "tabularjs";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/dist/jspreadsheet.css";

export default {
    methods: {
        async handleFileLoad(e) {
            const file = e.target.files[0];
            if (file) {
                const result = await tabularjs(file);
                jspreadsheet(this.$refs.spreadsheet, result);
            }
        }
    }
}
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet-ce";
import tabularjs from "tabularjs";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/dist/jspreadsheet.css";

@Component({
    selector: "app-root",
    template: `
        <div>
            <div #spreadsheet></div>
            <input
                #fileInput
                type="file"
                (change)="handleFileLoad($event)"
                accept=".xlsx,.xls,.ods,.csv"
                style="display: none"
            />
            <button (click)="fileInput.click()">Import Spreadsheet</button>
        </div>
    `
})
export class AppComponent {
    @ViewChild("spreadsheet") spreadsheet: ElementRef;

    async handleFileLoad(event: Event) {
        const input = event.target as HTMLInputElement;
        const file = input.files?.[0];
        if (file) {
            const result = await tabularjs(file);
            jspreadsheet(this.spreadsheet.nativeElement, result);
        }
    }
}