Products

JavaScript component to create web applications with spreadsheet UI

Free and open-source JavaScript component to create web applications with spreadsheet UI.

Worksheet
NPM Logo

23k+

Weekly downloads
GitHub Logo

6700+

GitHub stars
MIT License Icon

MIT License

Free and open-source

Compatible with
React, Angular, and Vue.

Jspreadsheet CE provides compatibility across different environments, ensuring your spreadsheet solution fits perfectly into your chosen stack.



JavaScript Angular ReactJS VueJS LemonadeJS

A complete solution to make rich and user-friendly web applications

Fully customizable JavaScript spreadsheet library, offering various components to enhance web development projects.

Column Types

A variety of customisable column types

Nested Headers

Create multi-level column headers

Cell Comments

Add comments to your spreadsheet cells

Custom Toolbar

Personalize your spreadsheet toolbar

<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://jsuites.net/v5/jsuites.css" type="text/css" />
<link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v5/jspreadsheet.css" type="text/css" />


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

<script>
let table = jspreadsheet(document.getElementById('spreadsheet'), {
    worksheets: [{
        data: [
            ['Hello', 13123, '', 'Yes', true, '#AA4411'],
            ['World!', 8, '', 'No', false, '#99BE23']
        ],
        columns: [
            { type: 'text', title: 'Text' },
            { type: 'numeric', title: 'Numeric', mask:'$ #.##,00', decimal: ',' },
            { type: 'calendar', title: 'Calendar' },
            { type: 'dropdown', source: ['Yes', 'No', 'Maybe'] },
            { type: 'checkbox', title: 'Checkbox' },
            { type: 'color', title: 'Color', width: 50, render: 'square' }
        ]
    }]
});
</script>
</html>
import React, { useRef } from "react";
import { Spreadsheet, Worksheet } from "@jspreadsheet-ce/react";
import "jspreadsheet-ce/dist/jspreadsheet.css";

export default function App() {
    // Spreadsheet array of worksheets
    const spreadsheet = useRef();
    // Data
    const data = [
        ['Hello', 13123, '', 'Yes', true, '#AA4411'],
        ['World!', 8, '', 'No', false, '#99BE23']
    ];
    // Columns
    const columns = [
        { type: 'text', title: 'Text' },
        { type: 'numeric', title: 'Numeric', mask:'$ #.##,00', decimal: ',' },
        { type: 'calendar', title: 'Calendar' },
        { type: 'dropdown', source: ['Yes', 'No', 'Maybe'] },
        { type: 'checkbox', title: 'Checkbox' },
        { type: 'color', title: 'Color', width: 50, render: 'square' }
    ];

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

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

// Spreadsheet ref
const spreadsheetRef = ref(null);

// Data
const data = ref([
    ['Hello', 13123, '', 'Yes', true, '#AA4411'],
    ['World!', 8, '', 'No', false, '#99BE23']
]);

// Columns
const columns = ref([
    { type: 'text', title: 'Text' },
    { type: 'numeric', title: 'Numeric', mask:'$ #.##,00', decimal: ',' },
    { type: 'calendar', title: 'Calendar' },
    { type: 'dropdown', source: ['Yes', 'No', 'Maybe'] },
    { type: 'checkbox', title: 'Checkbox' },
    { type: 'color', title: 'Color', width: 50, render: 'square' }
]);
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet-ce";
import "jspreadsheet-ce/dist/jspreadsheet.css"

// Create component
@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: [{
                data: [
                    ['Hello', 13123, '', 'Yes', true, '#AA4411'],
                    ['World!', 8, '', 'No', false, '#99BE23']
                ],
                columns: [
                    { type: 'text', title: 'Text' },
                    { type: 'numeric', title: 'Numeric', mask:'$ #.##,00', decimal: ',' },
                    { type: 'calendar', title: 'Calendar' },
                    { type: 'dropdown', source: ['Yes', 'No', 'Maybe'] },
                    { type: 'checkbox', title: 'Checkbox' },
                    { type: 'color', title: 'Color', width: 50, render: 'square' }
                ]
            }],
        });
    }
}
<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" />


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

<script>
jspreadsheet(document.getElementById('spreadsheet'), {
    worksheets: [{
        data: [[]],
        minDimensions: [5, 2],
        nestedHeaders:[
            [
                {
                    title: 'Supermarket information',
                    colspan: '6',
                },
            ],
            [
                {
                    title: 'Location',
                    colspan: '1',
                },
                {
                    title: ' Other Information',
                    colspan: '2'
                },
                {
                    title: ' Costs',
                    colspan: '3'
                }
            ],
        ]
    }]
});
</script>
</html>
import React, { useRef } from "react";
import { Spreadsheet, Worksheet } 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();
    // Nested headers
    const nestedHeaders = [
        [
            {
                title: 'Supermarket information',
                colspan: '6',
            },
        ],
        [
            {
                title: 'Location',
                colspan: '1',
            },
            {
                title: ' Other Information',
                colspan: '2'
            },
            {
                title: ' Costs',
                colspan: '3'
            }
        ],
    ];
    // Render component
    return (
        <>
            <Spreadsheet ref={spreadsheet}>
                <Worksheet nestedHeaders={nestedHeaders} minDimensions={[5,2]} />
            </Spreadsheet>
        </>
    );
}
<template>
  <Spreadsheet ref="spreadsheet">
      <Worksheet 
          :nestedHeaders="nestedHeaders" 
          :minDimensions="[5,2]" 
      />
  </Spreadsheet>
</template>

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

// Nested headers
const nestedHeaders = ref([
  [
      {
          title: 'Supermarket information',
          colspan: '6',
      },
  ],
  [
      {
          title: 'Location',
          colspan: '1',
      },
      {
          title: ' Other Information',
          colspan: '2'
      },
      {
          title: ' Costs',
          colspan: '3'
      }
  ],
]);

const spreadsheet = ref(null);
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet-ce";
import "jspreadsheet-ce/dist/jspreadsheet.css"
import "jsuites/dist/jsuites.css"

// Create component
@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: [{
                data: [[]],
                minDimensions: [5, 2],
                nestedHeaders:[
                    [
                        {
                            title: 'Supermarket information',
                            colspan: '6',
                        },
                    ],
                    [
                        {
                            title: 'Location',
                            colspan: '1',
                        },
                        {
                            title: ' Other Information',
                            colspan: '2'
                        },
                        {
                            title: ' Costs',
                            colspan: '3'
                        }
                    ],
                ]
            }]
        });
    }
}
<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" />


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

<script>
jspreadsheet(document.getElementById('spreadsheet'), {
    worksheets: [{
        data: [
            ['US', 'Cheese', '2019-02-12'],
            ['CA', 'Apples', '2019-03-01'],
        ],
        columns: [
            {width: '170px'},
            {width: '170px'},
            {width: '170px'},
        ],
        allowComments: true,
        comments: {
            B1: 'Initial comments on B1',
            C1: 'Initial comments on C1'
        },
    }]
});
</script>
</html>
import React, { useRef } from "react";
import { Spreadsheet, Worksheet } from "@jspreadsheet-ce/react";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/dist/jspreadsheet.css";

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

    const data = [
        ['US', 'Cheese', '2019-02-12'],
        ['CA', 'Apples', '2019-03-01'],
    ];

    const columns = [
        { width: '170px' },
        { width: '170px' },
        { width: '170px' },
    ];

    const comments = {
        B1: 'Initial comments on B1',
        C1: 'Initial comments on C1'
    };

    return (
        <>
            <Spreadsheet ref={spreadsheet}>
                <Worksheet data={data} columns={columns} comments={comments} allowComments />
            </Spreadsheet>
        </>
    );
}
<template>
  <Spreadsheet ref="spreadsheetRef">
      <Worksheet 
          :data="data" 
          :columns="columns" 
          :comments="comments" 
      />
  </Spreadsheet>
</template>

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

// Spreadsheet ref
const spreadsheetRef = ref(null);

// Data
const data = ref([
  ["US", "Cheese", "2019-02-12"],
  ["CA", "Apples", "2019-03-01"],
]);

// Columns configuration
const columns = ref([
  { width: "170px" },
  { width: "170px" },
  { width: "170px" }
]);

// Initial comments
const comments = ref({
  B1: "Initial comments on B1",
  C1: "Initial comments on C1",
});
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet-ce";

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

@Component({
    standalone: true,
    selector: "app-root",
    template: `<div #spreadsheet></div>`
})
export class AppComponent {
    @ViewChild("spreadsheet") spreadsheet: ElementRef;
    worksheets: jspreadsheet.worksheetInstance[];

    ngAfterViewInit() {
        this.worksheets = jspreadsheet(this.spreadsheet.nativeElement, {
            worksheets: [
                {
                    data: [
                        ['US', 'Cheese', '2019-02-12'],
                        ['CA', 'Apples', '2019-03-01'],
                        ['CA', 'Carrots', '2018-11-10'],
                        ['BR', 'Oranges', '2019-01-12'],
                    ],
                    columns: [
                        { width: '170px' },
                        { width: '170px' },
                        { width: '170px' },
                    ],
                    allowComments: true,
                    comments: {
                        B1: 'Initial comments on B1',
                        C1: 'Initial comments on C1'
                    },
                }
            ],
        });
    }
}
<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" />


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

<script>
jspreadsheet(document.getElementById('spreadsheet'), {
    toolbar: function(toolbar) {
        // Add a new custom item in the end of my toolbar
        toolbar.items.push({
            tooltip: 'My custom item',
            content: 'share',
            onclick: function() {
                alert('Custom click');
            }
        });

        return toolbar;
    },
    worksheets: [{
        minDimensions: [6, 2]
    }]
});
</script>
</html>
import React, { useRef } from "react";
import { Spreadsheet, Worksheet } from "@jspreadsheet-ce/react";
import "jsuites/dist/jsuites.css";
import "jspreadsheet-ce/dist/jspreadsheet.css";

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

    const toolbar = function(toolbar) {
        // Add a new custom item in the end of my toolbar
        toolbar.items.push({
            tooltip: 'My custom item',
            content: 'share',
            onclick: function() {
                alert('Custom click');
            }
        });

        return toolbar;
    }

    return (
        <>
            <Spreadsheet ref={spreadsheet} toolbar={toolbar}>
                <Worksheet minDimensions={[6, 2]} />
            </Spreadsheet>
        </>
    );
}
<template>
  <Spreadsheet ref="spreadsheetRef" :toolbar="toolbar">
      <Worksheet 
          :minDimensions="[5, 2]"
      />
  </Spreadsheet>
</template>

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

// Spreadsheet ref
const spreadsheetRef = ref(null);

const toolbar = (toolbar) => {
    // Add a new custom item in the end of my toolbar
    toolbar.items.push({
        tooltip: 'My custom item',
        content: 'share',
        onclick: function() {
            alert('Custom click');
        }
    });
    return toolbar;
}
</script>
import { Component, ViewChild, ElementRef } from "@angular/core";
import jspreadsheet from "jspreadsheet-ce";

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

// Create component
@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, {
            toolbar: function(toolbar) {
                // Add a new custom item in the end of my toolbar
                toolbar.items.push({
                    tooltip: 'My custom item',
                    content: 'share',
                    onclick: function() {
                        alert('Custom click');
                    }
                });
        
                return toolbar;
            },
            worksheets: [{
                minDimensions: [6, 2]
            }]
        });
    }
}

Create an online spreadsheet from various data formats

With Jspreadsheet, you can quickly create online spreadsheets using JavaScript arrays, JSON, CSV, and XLSX files. This flexibility simplifies data integration and minimizes your application's need for complex processing.

Deliver high-quality interfaces and applications to your end-user

Jspreadsheet reduces customers development time.
Here are some of their experiences.


Rich Interfaces

Make rich and user-friendly web interfaces and applications

User-Friendly Inputs

You can easily handle complicated data inputs in a way users are used to

Enhanced Experience

Improve your user software experience

Beautiful CRUDs

Create rich CRUDS and beautiful UI

Compatibility with excel spreadsheets

Users can move data around with common copy and paste shortcuts

Easy Customization

Easy customizations with easy third-party plugin integrations

Fast and Simple

Lean, fast and simple to use

Faster Data Entry

Speed up your work dealing with difficult data entry in a web-based software

Shareable Spreadsheets

Create and share amazing online spreadsheets

Component Ecosystem

Explore the powerful and versatile components designed to elevate your productivity. From data management to collaboration, our ecosystem seamlessly integrates to meet your needs.


Jspreadsheet Pro

Enterprise JavaScript data grid component to integrate spreadsheet UI into your web-based application.

Intrasheets

Collaborate with ease using Intrasheets, an intuitive tool for managing spreadsheets across teams, ensuring that everyone stays on the same page.

Jsuites

Comprehensive JavaScript plugins and web components for diverse web-based applications and requirements.

LemonadeJS

A light and easy-to-use solution for creating elegant UI elements, giving your web apps a refreshing boost in both style and functionality.



Subscribe to our newsletter

Tech news, tips and technical advice