--- title: Spreadsheets in GatsbyJS Sites sidebar_label: GatsbyJS description: Make static websites from spreadsheets using GatsbyJS. Seamlessly integrate data into your website using SheetJS. Generate websites from data in Excel spreadsheets. pagination_prev: demos/net/index pagination_next: demos/mobile/index sidebar_custom_props: type: native --- import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; GatsbyJS is a framework for creating websites. It uses React components for page templates and GraphQL for loading data. [SheetJS](https://sheetjs.com) 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"](#complete-example) section includes a complete website powered by an XLSX spreadsheet. :::info pass `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. ::: :::caution pass `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-${current}/xlsx-${current}.tgz" } }`} ::: :::warning Telemetry GatsbyJS collects telemetry by default. The `telemetry` subcommand can disable it: ```js npx gatsby telemetry --disable ``` ::: ## Integration Details ```mermaid 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](/docs/getting-started/installation/nodejs) 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`: {`\ { // highlight-start "overrides": { "xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz" } // highlight-end }`} `gatsby-transformer-excel` and `gatsby-source-filesystem` should be installed after installing SheetJS modules: {`\ npx gatsby telemetry --disable npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz npm i --save gatsby-transformer-excel gatsby-source-filesystem`} {`\ npx gatsby telemetry --disable pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz pnpm install gatsby-transformer-excel gatsby-source-filesystem`} {`\ npx gatsby telemetry --disable yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.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 workbook[^4]. Each worksheet is extracted from the workbook. The `sheet_to_json` method[^5] generates row objects using the headers in the first row as keys. Consider the following worksheet: ![pres.xlsx](pathname:///pres.png) Assuming the file name is `pres.xlsx` and the data is stored in "Sheet1", the following nodes will be created: ```js [ { 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: ```graphql { allPresXlsxSheet1 { # "all" followed by type edges { node { # each line in this block should be a field in the data Name Index } } } } ``` ## Complete Example :::note This demo was tested on 2023 October 08 against `create-gatsby@3.12.0`. The generated project used `gatsby@5.12.5` and `react@18.2.0`. ::: ### Project setup 0) Disable GatsbyJS telemetry: ```bash npx gatsby telemetry --disable ``` 1) Create a template site: ```bash npm init gatsby -- -y sheetjs-gatsby ``` 2) Follow the on-screen instructions for starting the local development server: ```bash cd sheetjs-gatsby npm run develop ``` Open a web browser to the displayed URL (typically `http://localhost:8000/`) 3) Edit `package.json` and add the highlighted lines in the JSON object: {`\ { // highlight-start "overrides": { "xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz" }, // highlight-end "name": "sheetjs-gatsby", "version": "1.0.0", `} 4) Install the library and plugins: {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz npm i --save gatsby-transformer-excel gatsby-source-filesystem `} 5) Make a `src/data` directory, download , and move the downloaded file into the new folder: ```bash mkdir -p src/data curl -L -o src/data/pres.xlsx https://sheetjs.com/pres.xlsx ``` 6) Edit `gatsby-config.js` and add the following lines to the `plugins` array: ```js title="gatsby-config.js" module.exports = { siteMetadata: { title: `sheetjs-gatsby`, siteUrl: `https://www.yourdomain.tld`, }, // highlight-start plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `data`, path: `${__dirname}/src/data/`, }, }, `gatsby-transformer-excel`, ], // highlight-end } ``` Stop and restart the development server process (`npm run develop`). ### GraphiQL test 7) Open the GraphiQL editor at `http://localhost:8000/___graphql` There is an editor in the left pane. Paste the following query into the editor: ```graphql { allPresXlsxSheet1 { edges { node { Name Index } } } } ``` Press the Execute Query button and data should show up in the right pane: ![GraphiQL Screenshot](pathname:///gatsby/graphiql.png) ### React page 8) Create a new file `src/pages/pres.js` that uses the query and displays the result: ```jsx title="src/pages/pres.js" import { graphql } from "gatsby" import * as React from "react" export const query = graphql`query { allPresXlsxSheet1 { edges { node { Name Index } } } }`; const PageComponent = ({data}) => { return (
{JSON.stringify(data, 2, 2)}
); }; 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: ```js { "allPresXlsxSheet1": { "edges": [ { "node": { "Name": "Bill Clinton", "Index": 42 } }, // .... ``` 9) Change `PageComponent` to display a table based on the data: ```jsx title="src/pages/pres.js" import { graphql } from "gatsby" import * as React from "react" export const query = graphql`query { allPresXlsxSheet1 { edges { node { Name Index } } } }`; // highlight-start const PageComponent = ({data}) => { const rows = data.allPresXlsxSheet1.edges.map(r => r.node); return ( {rows.map(row => ( ))}
NameIndex
{row.Name} {row.Index}
); }; // highlight-end export default PageComponent; ``` Going back to the browser, `http://localhost:8000/pres` will show a table: ![Data in Table](pathname:///gatsby/table1.png) ### Live refresh 10) Open the file `src/data/pres.xlsx` in Excel or LibreOffice or Numbers. Add a new row at the end of the file: ![New Row in File](pathname:///gatsby/pres2.png) Save the file and notice that the table has refreshed with the new data: ![Updated Table](pathname:///gatsby/table2.png) ### Static site 11) Stop the development server and run `npm run build`. Once the build is finished, the 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`. 12) Open `public/pres/index.html` with a text editor and search for "SheetJS". There will be a HTML row: ```html title="public/pres/index.html" SheetJS Dev47 ``` [^1]: The package is available as [`gatsby-transformer-excel` on the public NPM registry](https://www.npmjs.com/package/gatsby-transformer-excel). It is also listed on the [GatsbyJS plugin library](https://www.gatsbyjs.com/plugins/gatsby-transformer-excel/). [^2]: See [the `gatsby-source-filesystem` plugin](https://www.gatsbyjs.com/plugins/gatsby-source-filesystem/) in the GatsbyJS documentation [^3]: See [`read` in "Reading Files"](/docs/api/parse-options) [^4]: See ["Workbook Object"](/docs/csf/book) for more details on the SheetJS workbook object. [^5]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)