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.
This demo was tested in the following environments:
ViteJS | Date |
---|---|
5.4.10 | 2024-11-04 |
4.5.5 | 2024-11-04 |
3.2.11 | 2024-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
- Create a new ViteJS project:
npm create vite@latest sheetjs-vite -- --template vue-ts
cd sheetjs-vite
npm i
- Add the SheetJS dependency:
npm i --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
- Replace
src\components\HelloWorld.vue
with:
<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>
- 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"
-
Open a web browser to
http://localhost:5173/
and click the export button. -
Build the production site:
npx vite build
- Verify the new site by running a local web server in the
dist
folder:
npx http-server dist
- Access the displayed URL (typically
http://localhost:8080
) in a web browser and click the export button.
Footnotes
-
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. ↩