Spreadsheets in GatsbyJS Sites
GatsbyJS is a framework for creating websites. It uses React components for page templates and GraphQL for loading data.
SheetJS is a JavaScript library for reading and writing data from spreadsheets.
This demo uses GatsbyJS and SheetJS (through the gatsby-transformer-excel
1
transformer) to pull data from a spreadsheet and display the content in a page.
The "Complete Example" section includes a complete website powered by an XLSX spreadsheet.
gatsby-transformer-excel
is maintained by the Gatsby core team and all bugs
should be directed to the main Gatsby project. If it is determined to be a bug
in the parsing logic, issues should then be raised with the SheetJS team.
gatsby-transformer-excel
uses an older version of the library. It can be
overridden through a package.json
override in the latest versions of NodeJS:
{
"overrides": {
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
}
}
GatsbyJS collects telemetry by default. The telemetry
subcommand can disable it:
npx gatsby telemetry --disable
Integration Details​
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
filenode[File\nNode]
datanode[Data\nNodes]
end
aoo(array of\nobjects)
html{{HTML\nTABLE}}
file --> |Source\nPlugin| filenode
filenode --> |Transformer\nPlugin| datanode
datanode --> |GraphQL\nQuery| aoo
aoo --> |React\nJSX| html
In the GatsbyJS data system, source plugins read from data sources and generate nodes represent raw data. Transformer plugins transform these nodes into other nodes that represent processed data for use in pages.
This example uses gatsby-source-filesystem
2 to read files from the
filesystem and gatsby-transformer-excel
transformer to perform the transform.
Installation​
The SheetJS NodeJS module will be
referenced by gatsby-transformer-excel
.
Before installing, to ensure that the transformer uses the latest version of the
library, the overrides
section must be added to package.json
:
{
"overrides": {
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
}
}
gatsby-transformer-excel
and gatsby-source-filesystem
should be installed
after installing SheetJS modules:
- npm
- pnpm
- Yarn
npx gatsby telemetry --disable
npm i --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
npm i --save gatsby-transformer-excel gatsby-source-filesystem
npx gatsby telemetry --disable
pnpm install --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
pnpm install --save gatsby-transformer-excel gatsby-source-filesystem
npx gatsby telemetry --disable
yarn add https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
yarn add gatsby-transformer-excel gatsby-source-filesystem
GraphQL details​
Under the hood, gatsby-transformer-excel
uses the SheetJS read
3 method to
parse the workbook into a SheetJS workbook4. Each worksheet is extracted from
the workbook. The sheet_to_json
method5 generates row objects using the
headers in the first row as keys.
Consider the following worksheet:
Assuming the file name is pres.xlsx
and the data is stored in "Sheet1", the
following nodes will be created:
[
{ Name: "Bill Clinton", Index: 42, type: "PresXlsxSheet1" },
{ Name: "GeorgeW Bush", Index: 43, type: "PresXlsxSheet1" },
{ Name: "Barack Obama", Index: 44, type: "PresXlsxSheet1" },
{ Name: "Donald Trump", Index: 45, type: "PresXlsxSheet1" },
{ Name: "Joseph Biden", Index: 46, type: "PresXlsxSheet1" },
]
The type is a proper casing of the file name concatenated with the sheet name.
The following query pulls the Name
and Index
fields from each row:
{
allPresXlsxSheet1 { # "all" followed by type
edges {
node { # each line in this block should be a field in the data
Name
Index
}
}
}
}
Complete Example​
This demo was tested in the following environments:
GatsbyJS | Date |
---|---|
5.13.4 | 2024-05-04 |
4.25.8 | 2024-03-27 |
Project setup​
- Disable GatsbyJS telemetry:
npx gatsby telemetry --disable
In NodeJS 22, the process displayed an error:
ERROR UNKNOWN(node:25039) [DEP0040] DeprecationWarning: The
punycode
module is deprecated. Please use a userland alternative instead. (Usenode --trace-deprecation ...
to show where the warning was created)
This is a false report!
The error can be safely ignored.
- Create a template site:
npx gatsby new sheetjs-gatsby
For older Gatsby versions, the project must be built from the starter project.
For GatsbyJS 4, the starter commit is 6bc4466090845f20650117b3d27e68e6e46dc8d5
and the steps are shown below:
git clone https://github.com/gatsbyjs/gatsby-starter-default sheetjs-gatsby
cd sheetjs-gatsby
git checkout 6bc4466090845f20650117b3d27e68e6e46dc8d5
npm install
cd ..
- Follow the on-screen instructions for starting the local development server:
cd sheetjs-gatsby
npm run develop
Open a web browser to the displayed URL (typically http://localhost:8000/
)
- Edit
package.json
and add the highlighted lines in the JSON object:
{
"overrides": {
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
},
"name": "sheetjs-gatsby",
"version": "1.0.0",
- Install the library and plugins:
npm i --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
npm i --save gatsby-transformer-excel gatsby-source-filesystem
For older versions of Gatsby, older versions of the dependencies must be used.
For GatsbyJS 4, the plugin version numbers align with the Gatsby version:
npm i --save gatsby-transformer-excel@4 gatsby-source-filesystem@4
- Make a
src/data
directory, download https://docs.sheetjs.com/pres.xlsx, and move the downloaded file into the new folder:
mkdir -p src/data
curl -L -o src/data/pres.xlsx https://docs.sheetjs.com/pres.xlsx
- Edit
gatsby-config.js
and add the following lines to theplugins
array:
module.exports = {
siteMetadata: {
title: `sheetjs-gatsby`,
siteUrl: `https://www.yourdomain.tld`,
},
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `data`,
path: `${__dirname}/src/data/`,
},
},
`gatsby-transformer-excel`,
],
}
If the plugins
array exists, the two plugins should be added at the beginning:
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `data`,
path: `${__dirname}/src/data/`,
},
},
`gatsby-transformer-excel`,
// ...
Stop and restart the development server process (npm run develop
).
GraphiQL test​
- Open the GraphiQL editor. The output of the previous step displayed the URL
(typically
http://localhost:8000/___graphql
)
There is an editor in the left pane. Paste the following query into the editor:
{
allPresXlsxSheet1 {
edges {
node {
Name
Index
}
}
}
}
Press the Execute Query button (â–¶
) and data should show up in the right pane:
Sample Output (click to show)
In GatsbyJS version 5.13.4
, the raw output was:
{
"data": {
"allPresXlsxSheet1": {
"edges": [
{
"node": {
"Name": "Bill Clinton",
"Index": 42
}
},
{
"node": {
"Name": "GeorgeW Bush",
"Index": 43
}
},
{
"node": {
"Name": "Barack Obama",
"Index": 44
}
},
{
"node": {
"Name": "Donald Trump",
"Index": 45
}
},
{
"node": {
"Name": "Joseph Biden",
"Index": 46
}
}
]
}
},
"extensions": {}
}
React page​
- Create a new file
src/pages/pres.js
that uses the query and displays the result:
import { graphql } from "gatsby"
import * as React from "react"
export const query = graphql`query {
allPresXlsxSheet1 {
edges {
node {
Name
Index
}
}
}
}`;
const PageComponent = ({data}) => {
return ( <pre>{JSON.stringify(data, 2, 2)}</pre> );
};
export default PageComponent;
After saving the file, access http://localhost:8000/pres
in the browser. The
displayed JSON is the data that the component receives:
{
"allPresXlsxSheet1": {
"edges": [
{
"node": {
"Name": "Bill Clinton",
"Index": 42
}
},
// ....
- Change
PageComponent
to display a table based on the data:
import { graphql } from "gatsby"
import * as React from "react"
export const query = graphql`query {
allPresXlsxSheet1 {
edges {
node {
Name
Index
}
}
}
}`;
const PageComponent = ({data}) => {
const rows = data.allPresXlsxSheet1.edges.map(r => r.node);
return ( <table>
<thead><tr><th>Name</th><th>Index</th></tr></thead>
<tbody>{rows.map(row => ( <tr>
<td>{row.Name}</td>
<td>{row.Index}</td>
</tr> ))}</tbody>
</table> );
};
export default PageComponent;
Going back to the browser, http://localhost:8000/pres
will show a table:
Live refresh​
- Open the file
src/data/pres.xlsx
in Excel or another spreadsheet editor. Add a new row at the end of the file, setting cellA7
to "SheetJS Dev" and cellB7
to47
. The sheet should look like the following screenshot:
Save the file and observe that the table has refreshed with the new data:
Static site​
- Stop the development server and build the site:
npm run build
The build output will confirm that the /pres
route is static:
Pages
┌ src/pages/404.js
│ ├ /404/
│ └ /404.html
├ src/pages/index.js
│ └ /
â”” src/pages/pres.js
â”” /pres/
â•â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â•®
│ │
│ (SSG) Generated at build time │
│ D (DSG) Deferred static generation - page generated at runtime │
│ ∞ (SSR) Server-side renders at runtime (uses getServerData) │
│ λ (Function) Gatsby function │
│ │
╰────────────────────────────────────────────────────────────────╯
The generated page will be placed in public/pres/index.html
.
- Open
public/pres/index.html
with a text editor and search for "SheetJS". There will be a HTML row:
<tr><td>SheetJS Dev</td><td>47</td></tr>
Footnotes​
-
The package is available as
gatsby-transformer-excel
on the public NPM registry. It is also listed on the GatsbyJS plugin library. ↩ -
See the
gatsby-source-filesystem
plugin in the GatsbyJS documentation ↩ -
See "Workbook Object" for more details on the SheetJS workbook object. ↩