docs.sheetjs.com/docz/docs/03-demos/02-frontend/19-bundler/20-parcel.md
SheetJS 92e3c5aa72 mdx cleanup in preparation for v2
- use autolinks (e.g <https://sheetjs.com> -> https://sheetjs.com)
- move <summary> blocks to separate lines
2024-04-08 00:57:39 -04:00

6.7 KiB

title sidebar_label pagination_prev pagination_next sidebar_position
Bundling Sheets with ParcelJS ParcelJS demos/index demos/grid/index 20

import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock';

ParcelJS is a module bundler.

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

This demo uses ParcelJS and SheetJS to export data. We'll explore how to bundle SheetJS in a site using ParcelJS and how to export data to spreadsheets.

:::note pass

This demo focuses on integration details with the ParcelJS bundler.

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

:::

:::note Tested Deployments

This demo was tested in the following environments:

Version Date
2.10.3 2023-12-04
1.12.3 2023-12-04

:::

Integration Details

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

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

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

:::warning Parcel Bug

Errors of the form Could not statically evaluate fs call stem from a Parcel bug1. Upgrade to Parcel version 1.5.0 or later.

:::

Complete Example

This demo follows the Export Example.

  1. Initialize a new project:
mkdir sheetjs-parceljs
cd sheetjs-parceljs
npm init -y
  1. Save the following to index.html:
<body>
<h3>SheetJS <span id="vers"></span> export demo</h3>
<button id="xport">Click to Export!</button>
<!-- the script tag must be marked as `type="module"` -->
<!-- highlight-next-line -->
<script type="module">
// ESM-style import from "xlsx"
// highlight-next-line
import { utils, version, writeFileXLSX } from 'xlsx';

document.getElementById("vers").innerText = version;
document.getElementById("xport").onclick = async() => {
  /* fetch JSON data and parse */
  const url = "https://sheetjs.com/data/executive.json";
  const raw_data = 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>
<body>

:::caution pass

ParcelJS v1 did not support import statements within inline scripts.

For ParcelJS version 1, the entire script should be copied to index.js and the main index.html page should load the index.js script:

ParcelJS v1 example (click to show)
<body>
<h3>SheetJS <span id="vers"></span> export demo</h3>
<button id="xport">Click to Export!</button>
<script src="index.js"></script>
<body>
// ESM-style import from "xlsx"
import { utils, version, writeFileXLSX } from 'xlsx';

document.getElementById("vers").innerText = version;
document.getElementById("xport").onclick = async() => {
  /* fetch JSON data and parse */
  const url = "https://sheetjs.com/data/executive.json";
  const raw_data = 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");
};

:::

  1. Install the SheetJS NodeJS module:
{`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} {`\ pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} {`\ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}

Development

  1. Run the ParcelJS development server:
npx -y parcel@2.10.3 index.html

The process will print a URL:

Server running at http://localhost:1234
  1. Access the URL from the previous step (typically http://localhost:1234) in a web browser and click the "Click to Export!" button to generate a file.

Production

  1. Edit package.json and remove the following line:
   "main": "index.js"
  1. Build the production site:
npx -y parcel@2.10.0 build index.html

The production site will be stored in the dist folder

  1. Start a local web server and serve the dist folder:
npx http-server dist

Access the displayed URL (typically http://localhost:8080/) in a web browser. Click on "Click here to export" to generate a file.