Skip to main content

Bundling Sheets with ViteJS

ViteJS is a modern build tool for generating static sites.

SheetJS is a JavaScript library for reading and writing data from spreadsheets.

This demo uses ViteJS and SheetJS to export data. We'll explore how to add SheetJS to a site using ViteJS and how to export data to spreadsheets.

The Vite section of the Content demo covers asset loaders. They are ideal for static sites pulling data from sheets at build time.

This demo focuses on integration details with the ViteJS bundler.

The demos follow the "Export Tutorial", which covers SheetJS library usage in more detail.

Tested Deployments

This demo was tested in the following environments:

ViteJSDate
5.4.102024-11-04
4.5.52024-11-04
3.2.112024-11-04

Integration Details

The "Frameworks" section covers installation with Yarn and other package managers.

After installing the SheetJS module in a ViteJS project, import statements can load relevant parts of the library.

import { read, utils, writeFileXLSX } from 'xlsx';

ViteJS requires third-party libraries to provide additional package.json metadata. SheetJS library version 0.18.10 added the required metadata.

It is strongly recommended to upgrade to the latest version

Complete Example

  1. Create a new ViteJS project:
npm create vite@latest sheetjs-vite -- --template vue-ts
cd sheetjs-vite
npm i
  1. Add the SheetJS dependency:
npm i --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
  1. Replace src\components\HelloWorld.vue with:
src\components\HelloWorld.vue
<script setup lang="ts">
import { version, utils, writeFileXLSX } from 'xlsx';

interface President {
terms: { "type": "prez" | "viceprez"; }[];
name: { first: string; last: string; }
bio: { birthday: string; }
}

async function xport() {
/* fetch JSON data and parse */
const url = "https://docs.sheetjs.com/executive.json";
const raw_data: President[] = await (await fetch(url)).json();

/* filter for the Presidents */
const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));

/* sort by first presidential term */
prez.forEach(row => row.start = row.terms.find(term => term.type === "prez").start);
prez.sort((l,r) => l.start.localeCompare(r.start));

/* flatten objects */
const rows = prez.map(row => ({
name: row.name.first + " " + row.name.last,
birthday: row.bio.birthday
}));

/* generate worksheet and workbook */
const worksheet = utils.json_to_sheet(rows);
const workbook = utils.book_new();
utils.book_append_sheet(workbook, worksheet, "Dates");

/* fix headers */
utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });

/* calculate column width */
const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
worksheet["!cols"] = [ { wch: max_width } ];

/* create an XLSX file and try to save to Presidents.xlsx */
writeFileXLSX(workbook, "Presidents.xlsx");
}

</script>

<template>
<button type="button" @click="xport">Export with SheetJS version {{ version }}</button>
</template>
  1. Start the development server:
npm run dev

When this was last tested in ViteJS version 4, the process crashed with the error

Search string not found: "for (const existingRoot of buildInfoVersionMap.roots) {"

This is a known issue with ViteJS 4 and its dependency tree!1

The recommended workaround is to forcefully upgrade vue-tsc:

npm i "vue-tsc@2"
  1. Open a web browser to http://localhost:5173/ and click the export button.

  2. Build the production site:

npx vite build
  1. Verify the new site by running a local web server in the dist folder:
npx http-server dist
  1. Access the displayed URL (typically http://localhost:8080) in a web browser and click the export button.

Footnotes

  1. See issue 4484 in the vuejs/language-tools repository on GitHub for the issue triage and workaround. This issue does not affect other ViteJS major versions.