Products

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

// Set the license for both plugin and the spreadsheet
jspreadsheet.setLicense('YTRmYTJiNDQ0NDk5Mzc5MDUwNjc0ZDQ3NDAyYjZkY2NiYTFkZmFmZGI2NTk1ZDhiNTIwY2E0Njk0MTlmOTg5MzBiYWFmOGNlMWYwZDNjOGRjOGMzOTJhNGMwZWEyOGZjZDllODA0MWQxZTg0ZjE3N2UyY2ZlOTY5ZDkxOWYxNmEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azJOell5TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

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'

// Set the license for both plugin and the spreadsheet
jspreadsheet.setLicense('YTRmYTJiNDQ0NDk5Mzc5MDUwNjc0ZDQ3NDAyYjZkY2NiYTFkZmFmZGI2NTk1ZDhiNTIwY2E0Njk0MTlmOTg5MzBiYWFmOGNlMWYwZDNjOGRjOGMzOTJhNGMwZWEyOGZjZDllODA0MWQxZTg0ZjE3N2UyY2ZlOTY5ZDkxOWYxNmEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azJOell5TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

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';

  // Set the license for both plugin and the spreadsheet
  jspreadsheet.setLicense('YTRmYTJiNDQ0NDk5Mzc5MDUwNjc0ZDQ3NDAyYjZkY2NiYTFkZmFmZGI2NTk1ZDhiNTIwY2E0Njk0MTlmOTg5MzBiYWFmOGNlMWYwZDNjOGRjOGMzOTJhNGMwZWEyOGZjZDllODA0MWQxZTg0ZjE3N2UyY2ZlOTY5ZDkxOWYxNmEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azJOell5TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

  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/v11/jspreadsheet.js"></script>
<script src="https://jsuites.net/v6/jsuites.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v11/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>
// Set the license for both plugin and the spreadsheet
jspreadsheet.setLicense('YTRmYTJiNDQ0NDk5Mzc5MDUwNjc0ZDQ3NDAyYjZkY2NiYTFkZmFmZGI2NTk1ZDhiNTIwY2E0Njk0MTlmOTg5MzBiYWFmOGNlMWYwZDNjOGRjOGMzOTJhNGMwZWEyOGZjZDllODA0MWQxZTg0ZjE3N2UyY2ZlOTY5ZDkxOWYxNmEsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNU56azJOell5TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');


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