Vue.js Spreadsheet Integration

Build powerful, Excel-like data grids in your Vue.js applications. This guide covers both the official Vue wrapper and direct integration approaches, giving you the flexibility to choose the best method for your project requirements.

Quick Setup
Don't forget to import the required CSS files:
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";

Documentation

Using the Official Vue Wrapper

The @jspreadsheet/vue wrapper simplifies setup and provides Vue-specific features for building interactive spreadsheets.

Important Note:
The wrapper uses styles instead of style to avoid conflicts with Vue's built-in style attribute. This ensures proper CSS handling within Vue components.

Installation

Install the Vue wrapper using npm:

npm install @jspreadsheet/vue

Quick Start Example

Create a web-based spreadsheet using the Vue wrapper.

<template>
    <Spreadsheet ref="spreadsheet">
        <Worksheet :data="data" :columns="columns" />
    </Spreadsheet>
    <input type="button" value="getData" @click="getData()" />
</template>

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

// You can use the following license for quick testing on localhost, StackBlitz, or CodeSandbox.
// The license is valid for one day, after which the spreadsheet will become read-only.
// For a longer trial period, you can create a free account and generate a demo license with an extended expiration date.
jspreadsheet.setLicense('MzIzMTRhZTQwZGRmNjBhZGUwZjM4NzZkOWEyMjUwZDE2NDIyNGFjMTg1NmQzNDEwNjU0NzI4YWY3NGVkZWRkOGUzZGU2YzE0MGIyZTE1NDVmMzk2ODljMjRhZWIyOTRlZWY0NTQyMTVlOGUwZDBjZTFhNmY4MjNjNzBjNWY5M2YsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpjME16STRNVEUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2liRzlqWVd4b2IzTjBJbDBzSW5Cc1lXNGlPaUl6TkNJc0luTmpiM0JsSWpwYkluWTNJaXdpZGpnaUxDSjJPU0lzSW5ZeE1DSXNJbll4TVNJc0luWXhNaUlzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElpd2ljR2wyYjNRaVhTd2laR1Z0YnlJNmRISjFaWDA9');

export default {
    components: {
        Spreadsheet,
        Worksheet,
    },
    methods: {
        getData() {
            console.log(this.$refs.spreadsheet.current[0].getData());
        }
    },
    data() {
        // Worksheet data
        const data = [
            ["US", "Cheese", "2019-02-12"],
            ["CA", "Apples", "2019-03-01"],
            ["CA", "Carrots", "2018-11-10"],
            ["BR", "Oranges", "2019-01-12"],
        ]

        // Columns
        const columns = [
            { width: "300px" },
            { width: "200px" },
            { width: "200px" }
        ]

        return {
            data,
            columns
        }
    }
}
</script>

Using the library

The following example demonstrates how to use JSpreadsheet without a dedicated wrapper. By leveraging the library directly, developers gain greater flexibility and control, enabling highly customized implementations tailored to their specific needs.

Integration with Vue 3

<template>
  <div ref="spreadsheetRef"></div>
</template>

<script setup>
import jspreadsheet from 'jspreadsheet';
import "jsuites/dist/jsuites.css";
import "jspreadsheet/dist/jspreadsheet.css";
import { onMounted, ref } from 'vue'

// You can use the following license for quick testing on localhost, StackBlitz, or CodeSandbox.
// The license is valid for one day, after which the spreadsheet will become read-only.
// For a longer trial period, you can create a free account and generate a demo license with an extended expiration date.
jspreadsheet.setLicense('MzIzMTRhZTQwZGRmNjBhZGUwZjM4NzZkOWEyMjUwZDE2NDIyNGFjMTg1NmQzNDEwNjU0NzI4YWY3NGVkZWRkOGUzZGU2YzE0MGIyZTE1NDVmMzk2ODljMjRhZWIyOTRlZWY0NTQyMTVlOGUwZDBjZTFhNmY4MjNjNzBjNWY5M2YsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpjME16STRNVEUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2liRzlqWVd4b2IzTjBJbDBzSW5Cc1lXNGlPaUl6TkNJc0luTmpiM0JsSWpwYkluWTNJaXdpZGpnaUxDSjJPU0lzSW5ZeE1DSXNJbll4TVNJc0luWXhNaUlzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElpd2ljR2wyYjNRaVhTd2laR1Z0YnlJNmRISjFaWDA9');

const options = {
  worksheets: [
    {
      search: true,
      data: [
        [42, 42, 42, 42],
        [42, 42, 42, 42],
      ],
      columns: [
        { title: "First Column", width: 100 },
        { title: "Second Column", width: 150 },
        { title: "Third Column", width: 200 },
        { title: "Fourth Column", width: 250 },
      ],
    },
  ],
};

const spreadsheetRef = ref(null)

onMounted(() => {
  jspreadsheet(spreadsheetRef.value, options)
})
</script>

Creating a Custom Editor with a Vue 3 Component

The following example demonstrates how to integrate a Vue 3 component as a custom editor in JSpreadsheet, enabling advanced interactivity and tailored functionality within spreadsheet cells.

See this example on stackblitz

<template>
  <Spreadsheet ref="spreadsheet">
    <Worksheet :data="data" :columns="columns" /> </Spreadsheet
  ><br />
  <input type="button" value="getData" @click="getData()" />
  <input type="button" value="setValue('A1', false)" @click="setValue()" />
</template>

<script>
  import { h, createApp, ref } from 'vue';
  import { Spreadsheet, Worksheet, jspreadsheet } from '@jspreadsheet/vue';
  import InputSwitch from 'primevue/inputswitch';

  // You can use the following license for quick testing on localhost, StackBlitz, or CodeSandbox.
  // The license is valid for one day, after which the spreadsheet will become read-only.
  // For a longer trial period, you can create a free account and generate a demo license with an extended expiration date.
  jspreadsheet.setLicense('MzIzMTRhZTQwZGRmNjBhZGUwZjM4NzZkOWEyMjUwZDE2NDIyNGFjMTg1NmQzNDEwNjU0NzI4YWY3NGVkZWRkOGUzZGU2YzE0MGIyZTE1NDVmMzk2ODljMjRhZWIyOTRlZWY0NTQyMTVlOGUwZDBjZTFhNmY4MjNjNzBjNWY5M2YsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpjME16STRNVEUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2liRzlqWVd4b2IzTjBJbDBzSW5Cc1lXNGlPaUl6TkNJc0luTmpiM0JsSWpwYkluWTNJaXdpZGpnaUxDSjJPU0lzSW5ZeE1DSXNJbll4TVNJc0luWXhNaUlzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElpd2ljR2wyYjNRaVhTd2laR1Z0YnlJNmRISjFaWDA9');

  const Editor = {
    createCell(cell, value, x, y, instance) {
      // Create reactive state for the cell
      const isChecked = ref(value === 'true' || value === true);

      // Create Vue app for the cell
      createApp({
        setup() {
          return () =>
              h(InputSwitch, {
                modelValue: isChecked.value,
                'onUpdate:modelValue': (newValue) => {
                  isChecked.value = newValue; // Update reactive state
                  instance.setValueFromCoords(x, y, newValue, true); // Force update
                },
              });
        },
      }).mount(cell);

      cell.vueState = isChecked;
    },
    updateCell(cell, value, x, y, instance) {
      if (cell.vueState) {
        const newValue = !!(value === 'true' || value === true || value === 1);
        if (cell.vueState.value !== newValue) {
          cell.vueState.value = newValue;
        }
      }
    },
    openEditor(cell) {
      cell.vueState.value = !cell.vueState.value;
      return false; // No separate editor
    },
    closeEditor() {
      return false; // Not used
    },
    destroyCell(cell) {
      // Cleanup Vue app
      if (cell.vueApp) {
        cell.vueApp.unmount();
        cell.vueState = null;
      }
    },
  };

  export default {
    components: {
      Spreadsheet,
      Worksheet,
    },
    methods: {
      getData() {
        console.log(this.$refs.spreadsheet.current[0].getData());
      },
      setValue() {
        console.log(this.$refs.spreadsheet.current[0].setValue('A1', false));
      },
    },
    data() {
      // Worksheet data
      const data = [
        [true, 'Cheese', ''],
        [true, 'Apples', ''],
        [true, 'Carrots', ''],
        [false, 'Oranges', ''],
      ];

      // Columns
      const columns = [{ type: Editor }];

      return {
        data,
        columns
      };
    },
  };
</script>

Integration with Vue2

<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>

<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" />

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

<br>

<input type="button" value="Add new row" onclick="vm.insertRow()" />

<script>
// You can use the following license for quick testing on localhost, StackBlitz, or CodeSandbox.
// The license is valid for one day, after which the spreadsheet will become read-only.
// For a longer trial period, you can create a free account and generate a demo license with an extended expiration date.
jspreadsheet.setLicense('MzIzMTRhZTQwZGRmNjBhZGUwZjM4NzZkOWEyMjUwZDE2NDIyNGFjMTg1NmQzNDEwNjU0NzI4YWY3NGVkZWRkOGUzZGU2YzE0MGIyZTE1NDVmMzk2ODljMjRhZWIyOTRlZWY0NTQyMTVlOGUwZDBjZTFhNmY4MjNjNzBjNWY5M2YsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpjME16STRNVEUwTENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2liRzlqWVd4b2IzTjBJbDBzSW5Cc1lXNGlPaUl6TkNJc0luTmpiM0JsSWpwYkluWTNJaXdpZGpnaUxDSjJPU0lzSW5ZeE1DSXNJbll4TVNJc0luWXhNaUlzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElpd2ljR2wyYjNRaVhTd2laR1Z0YnlJNmRISjFaWDA9');

let options = {
    worksheets: [{
        data:[[]],
        minDimensions:[8,10],
    }],
}

let vm = new Vue({
    el: '#spreadsheet',
    mounted: function() {
        let spreadsheet = jspreadsheet(this.$el, options);
        Object.assign(this, spreadsheet);
    }
}); 
</script>

More Vue3 and Jspreadsheet examples