new-dataset-url
This commit is contained in:
parent
990f42934b
commit
5d87422b97
@ -1064,7 +1064,7 @@ When the app is loaded, the data will be displayed in rows.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
[^1]: <https://catalog.data.gov/dataset/national-student-loan-data-system-aa85f> is the current location for the CC0-licensed dataset. `PortfolioSummary.xls` is the file name.
|
||||
[^1]: The dataset URL has changed many times over the years. The current location for the CC0-licensed dataset can be found by [searching for "National Student Loan Data System" on `data.gov`](https://catalog.data.gov/dataset/?q=national+student+loan+data+system&publisher=Office+of+Federal+Student+Aid+%28FSA%29&organization=ed-gov). `PortfolioSummary.xls` is the file name within the dataset.
|
||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^3]: See ["SheetJS Data Model"](/docs/csf/)
|
||||
[^4]: See ["Workbook Object"](/docs/csf/book)
|
||||
|
@ -159,12 +159,19 @@ import { read, utils } from 'xlsx';
|
||||
|
||||
/* Fetch and update the state once */
|
||||
useEffect(() => { (async() => {
|
||||
/* Download file */
|
||||
const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
|
||||
/* Download from https://sheetjs.com/pres.numbers */
|
||||
const f = await fetch("https://sheetjs.com/pres.numbers");
|
||||
const ab = await f.arrayBuffer();
|
||||
|
||||
// highlight-start
|
||||
const wb = read(f); // parse the array buffer
|
||||
/* parse */
|
||||
const wb = read(ab);
|
||||
|
||||
/* generate array of objects from first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
const data = utils.sheet_to_json(ws); // generate objects
|
||||
|
||||
/* update state */
|
||||
setPres(data); // update state
|
||||
// highlight-end
|
||||
})(); }, []);
|
||||
@ -179,12 +186,19 @@ import { read, utils } from 'xlsx';
|
||||
|
||||
/* Fetch and update the state once */
|
||||
useEffect(() => { (async() => {
|
||||
/* Download file */
|
||||
const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
|
||||
/* Download from https://sheetjs.com/pres.numbers */
|
||||
const f = await fetch("https://sheetjs.com/pres.numbers");
|
||||
const ab = await f.arrayBuffer();
|
||||
|
||||
// highlight-start
|
||||
const wb = read(f); // parse the array buffer
|
||||
/* parse */
|
||||
const wb = read(ab);
|
||||
|
||||
/* generate array of presidents from the first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
const data: President[] = utils.sheet_to_json<President>(ws); // generate objects
|
||||
|
||||
/* update state */
|
||||
setPres(data); // update state
|
||||
// highlight-end
|
||||
})(); }, []);
|
||||
@ -305,6 +319,57 @@ export default function SheetJSReactAoO() {
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 October 08 with ViteJS 4.4.1 and React 18.2.0
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-react -- --template react
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
cd sheetjs-react
|
||||
npm i
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm run dev`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Open a web browser and access the displayed URL (`http://localhost:5173`)
|
||||
|
||||
4) Replace `src/App.jsx` with the `src/SheetJSReactAoO.js` example.
|
||||
|
||||
The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSReactAoA.xlsx`.
|
||||
|
||||
5) Build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The generated site will be placed in the `dist` folder.
|
||||
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
and test the page.
|
||||
|
||||
</TabItem>
|
||||
<TabItem name="CRA" value="create-react-app">
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last run on 2023 July 03 using `create-react-app@5.0.1` and
|
||||
@ -334,8 +399,25 @@ npm start`}
|
||||
The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSReactAoA.xlsx`.
|
||||
|
||||
5) Build the site with `npm run build`, then test with `npx http-server build`.
|
||||
Access `http://localhost:8080` with a web browser to test the bundled site.
|
||||
5) Build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The generated site will be placed in the `build` folder.
|
||||
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server build
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
and test the page.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
</details>
|
||||
|
||||
@ -394,6 +476,57 @@ export default function SheetJSReactHTML() {
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 October 08 with ViteJS 4.4.1 and React 18.2.0
|
||||
|
||||
:::
|
||||
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-react -- --template react
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
cd sheetjs-react
|
||||
npm i
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm run dev`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Open a web browser and access the displayed URL (`http://localhost:5173`)
|
||||
|
||||
4) Replace `src/App.jsx` with the `src/SheetJSReactHTML.js` example.
|
||||
|
||||
The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSReactHTML.xlsx`.
|
||||
|
||||
5) Build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The generated site will be placed in the `dist` folder.
|
||||
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
and test the page.
|
||||
|
||||
</TabItem>
|
||||
<TabItem name="CRA" value="create-react-app">
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last run on 2023 July 03 using `create-react-app@5.0.1` and
|
||||
@ -423,8 +556,25 @@ npm start`}
|
||||
The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSReactHTML.xlsx`.
|
||||
|
||||
5) Build the site with `npm run build`, then test with `npx http-server build`.
|
||||
Access `http://localhost:8080` with a web browser to test the bundled site.
|
||||
5) Build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The generated site will be placed in the `build` folder.
|
||||
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server build
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
and test the page.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -54,27 +54,17 @@ depends on the application.
|
||||
Typically, some users will create a spreadsheet with source data that should be
|
||||
loaded into the site. This sheet will have known columns.
|
||||
|
||||
For example, our [presidents sheet](https://sheetjs.com/pres.xlsx) has "Name" and "Index" columns:
|
||||
#### State
|
||||
|
||||
The example [presidents sheet](https://sheetjs.com/pres.xlsx) has one header row
|
||||
with "Name" and "Index" columns. The natural JS representation is an object for
|
||||
each row, using the values in the first rows as keys:
|
||||
|
||||
<table><thead><tr><th>Spreadsheet</th><th>State</th></tr></thead><tbody><tr><td>
|
||||
|
||||
![`pres.xlsx` data](pathname:///pres.png)
|
||||
|
||||
This naturally maps to an array of typed objects, as in the TS example below:
|
||||
|
||||
```ts
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
interface President {
|
||||
Name: string;
|
||||
Index: number;
|
||||
}
|
||||
|
||||
const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
|
||||
const wb = read(f);
|
||||
const data = utils.sheet_to_json<President>(wb.Sheets[wb.SheetNames[0]]);
|
||||
console.log(data);
|
||||
```
|
||||
|
||||
`data` will be an array of objects:
|
||||
</td><td>
|
||||
|
||||
```js
|
||||
[
|
||||
@ -86,8 +76,234 @@ console.log(data);
|
||||
]
|
||||
```
|
||||
|
||||
A component will typically map over the data. The following example generates
|
||||
a TABLE with a row for each President:
|
||||
</td></tr></tbody></table>
|
||||
|
||||
Using the VueJS Composition API, the `ref`[^1] function creates state objects:
|
||||
|
||||
<Tabs groupId="lang">
|
||||
<TabItem name="JS" value="JavaScript">
|
||||
|
||||
```html
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
|
||||
/* the component state is an array of objects */
|
||||
const pres = ref([]);
|
||||
</script>
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem name="TS" value="TypeScript" default>
|
||||
|
||||
```html
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
|
||||
/* the component state is an array of objects */
|
||||
const pres = ref<any[]>([]);
|
||||
</script>
|
||||
```
|
||||
|
||||
When the spreadsheet header row is known ahead of time, row typing is possible:
|
||||
|
||||
```html
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
|
||||
interface President {
|
||||
Name: string;
|
||||
Index: number;
|
||||
}
|
||||
|
||||
/* the component state is an array of presidents */
|
||||
const pres = ref<President[]>([]);
|
||||
</script>
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
The types are informative. They do not enforce that worksheets include the named
|
||||
columns. A runtime data validation library should be used to verify the dataset.
|
||||
|
||||
When the file header is not known in advance, `any` should be used.
|
||||
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Updating State
|
||||
|
||||
The SheetJS [`read`](/docs/api/parse-options) and [`sheet_to_json`](/docs/api/utilities/array#array-output)
|
||||
functions simplify state updates. They are best used in the function bodies of
|
||||
lifecycle hooks including `onMounted`[^2].
|
||||
|
||||
The `onMounted` hook can download and update state when a person loads the site:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
url[(Remote\nFile)]
|
||||
ab[(Data\nArrayBuffer)]
|
||||
wb(SheetJS\nWorkbook)
|
||||
ws(SheetJS\nWorksheet)
|
||||
aoo(array of\nobjects)
|
||||
state((component\nstate))
|
||||
url --> |fetch\n\n| ab
|
||||
ab --> |read\n\n| wb
|
||||
wb --> |wb.Sheets\nselect sheet| ws
|
||||
ws --> |sheet_to_json\n\n| aoo
|
||||
aoo --> |setPres\nfrom `setState`| state
|
||||
```
|
||||
|
||||
<Tabs groupId="lang">
|
||||
<TabItem name="JS" value="JavaScript">
|
||||
|
||||
```html
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
/* the component state is an array of objects */
|
||||
const pres = ref([]);
|
||||
|
||||
/* Fetch and update the state once */
|
||||
onMounted(async() => {
|
||||
/* Download from https://sheetjs.com/pres.numbers */
|
||||
const f = await fetch("https://sheetjs.com/pres.numbers");
|
||||
const ab = await f.arrayBuffer();
|
||||
|
||||
// highlight-start
|
||||
/* parse */
|
||||
const wb = read(ab);
|
||||
|
||||
/* generate array of objects from first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
const data = utils.sheet_to_json(ws); // generate objects
|
||||
|
||||
/* update state */
|
||||
pres.value = data;
|
||||
// highlight-end
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem name="TS" value="TypeScript" default>
|
||||
|
||||
```html
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
interface President {
|
||||
Name: string;
|
||||
Index: number;
|
||||
}
|
||||
|
||||
/* the component state is an array of presidents */
|
||||
const pres = ref<President[]>([]);
|
||||
|
||||
/* Fetch and update the state once */
|
||||
onMounted(async() => {
|
||||
/* Download from https://sheetjs.com/pres.numbers */
|
||||
const f = await fetch("https://sheetjs.com/pres.numbers");
|
||||
const ab = await f.arrayBuffer();
|
||||
|
||||
// highlight-start
|
||||
/* parse */
|
||||
const wb = read(ab);
|
||||
|
||||
/* generate array of presidents from the first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
const data: President[] = utils.sheet_to_json<President>(ws); // generate objects
|
||||
|
||||
/* update state */
|
||||
pres.value = data;
|
||||
// highlight-end
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Rendering Data
|
||||
|
||||
A component will typically map over the data with `v-for`[^3]. The following
|
||||
example generates a TABLE with a row for each President:
|
||||
|
||||
```html title="Example SFC for displaying arrays of objects"
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
const rows = ref([]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table>
|
||||
<!-- The `thead` section includes the table header row -->
|
||||
<thead><th>Name</th><th>Index</th></thead>
|
||||
<!-- The `tbody` section includes the data rows -->
|
||||
<tbody>
|
||||
<!-- generate row (TR) for each president -->
|
||||
<!-- highlight-start-->
|
||||
<tr v-for="(row, idx) in rows" :key="idx">
|
||||
<td>{{ row.Name }}</td>
|
||||
<td>{{ row.Index }}</td>
|
||||
</tr>
|
||||
<!-- highlight-end-->
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
```
|
||||
|
||||
#### Exporting Data
|
||||
|
||||
The [`writeFile`](/docs/api/write-options) and [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
|
||||
functions simplify exporting data. They are best used in the function bodies of
|
||||
`v-on` event handlers like `@click`[^4].
|
||||
|
||||
A callback can generate a local file when a user clicks a button:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
state((component\nstate))
|
||||
ws(SheetJS\nWorksheet)
|
||||
wb(SheetJS\nWorkbook)
|
||||
file[(XLSX\nexport)]
|
||||
state --> |json_to_sheet\n\n| ws
|
||||
ws --> |book_new\nbook_append_sheet| wb
|
||||
wb --> |writeFile\n\n| file
|
||||
```
|
||||
|
||||
```html
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { utils, writeFileXLSX } from 'xlsx';
|
||||
|
||||
const pres = ref([]);
|
||||
|
||||
/* get state data and export to XLSX */
|
||||
function exportFile() {
|
||||
/* generate worksheet from state */
|
||||
// highlight-next-line
|
||||
const ws = utils.json_to_sheet(pres.value);
|
||||
/* create workbook and append worksheet */
|
||||
const wb = utils.book_new();
|
||||
utils.book_append_sheet(wb, ws, "Data");
|
||||
/* export to XLSX */
|
||||
writeFileXLSX(wb, "SheetJSVueAoO.xlsx");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click="exportFile">Export XLSX</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
#### Complete Component
|
||||
|
||||
This complete component example fetches a test file and displays the contents in
|
||||
a HTML table. When the export button is clicked, a callback will export a file:
|
||||
|
||||
```html title="src/SheetJSVueAoO.vue"
|
||||
<script setup>
|
||||
@ -157,8 +373,22 @@ The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSVueAoA.xlsx`. There may be a delay
|
||||
since Vite will try to optimize the SheetJS library on the fly.
|
||||
|
||||
5) Build the site with `npm run build`, then test with `npx http-server dist`.
|
||||
Access `http://localhost:8080` with a web browser to test the bundled site.
|
||||
5) Build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The generated site will be placed in the `dist` folder.
|
||||
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
and test the page.
|
||||
|
||||
</details>
|
||||
|
||||
@ -168,9 +398,14 @@ The main disadvantage of the Array of Objects approach is the specific nature
|
||||
of the columns. For more general use, passing around an Array of Arrays works.
|
||||
However, this does not handle merge cells well!
|
||||
|
||||
The `sheet_to_html` function generates HTML that is aware of merges and other
|
||||
worksheet features. VueJS `v-html` attribute allows assignment of `innerHTML`
|
||||
attribute, effectively inserting the code into the page:
|
||||
The [`sheet_to_html`](/docs/api/utilities/html#html-table-output) function
|
||||
generates HTML that is aware of merges and other worksheet features. VueJS
|
||||
`v-html`[^5] attribute allows code to set the `innerHTML` attribute, effectively
|
||||
inserting the code into the page.
|
||||
|
||||
In this example, the component attaches a `ref` to the `DIV` container. During
|
||||
export, the first `TABLE` child element can be parsed with [`table_to_book`](/docs/api/utilities/html#html-table-input) to
|
||||
generate a workbook object.
|
||||
|
||||
```html title="src/SheetJSVueHTML.vue"
|
||||
<script setup>
|
||||
@ -233,8 +468,40 @@ The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSVueHTML.xlsx`. There may be a delay
|
||||
since Vite will try to optimize the SheetJS library on the fly.
|
||||
|
||||
5) Build the site with `npm run build`, then test with `npx http-server dist`.
|
||||
Access `http://localhost:8080` with a web browser to test the bundled site.
|
||||
5) Build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The generated site will be placed in the `dist` folder.
|
||||
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
and test the page.
|
||||
|
||||
|
||||
5) Build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The generated site will be placed in the `dist` folder.
|
||||
|
||||
6) Start a local web server:
|
||||
|
||||
```bash
|
||||
npx http-server dist
|
||||
```
|
||||
|
||||
Access the displayed URL (typically `http://localhost:8080`) with a web browser
|
||||
and test the page.
|
||||
|
||||
</details>
|
||||
|
||||
@ -284,3 +551,9 @@ The entire demo is designed to run in Internet Explorer and does not reflect
|
||||
modern design patterns.
|
||||
|
||||
:::
|
||||
|
||||
[^1]: See [`ref()`](https://vuejs.org/api/reactivity-core.html#ref) in the VueJS documentation.
|
||||
[^2]: See [`onMounted()`](https://vuejs.org/api/composition-api-lifecycle.html#onmounted) in the VueJS documentation.
|
||||
[^3]: See [`v-for`](https://vuejs.org/api/built-in-directives.html#v-for) in the VueJS documentation.
|
||||
[^4]: See [`v-on`](https://vuejs.org/api/built-in-directives.html#v-on) in the VueJS documentation.
|
||||
[^5]: See [`v-html`](https://vuejs.org/api/built-in-directives.html#v-html) in the VueJS documentation.
|
@ -1,5 +1,7 @@
|
||||
---
|
||||
title: GatsbyJS
|
||||
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:
|
||||
@ -7,21 +9,27 @@ sidebar_custom_props:
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[GatsbyJS](https://www.gatsbyjs.com/) is a framework for creating websites. It
|
||||
uses React components for page templates and GraphQL for loading data.
|
||||
GatsbyJS is a framework for creating websites. It uses React components for page
|
||||
templates and GraphQL for loading data.
|
||||
|
||||
[`gatsby-transformer-excel`](https://www.gatsbyjs.com/plugins/gatsby-transformer-excel/)
|
||||
is a transformer that generates GraphQL nodes for each row of each worksheet.
|
||||
The plugin is officially supported by the Gatsby team. The plugin documentation
|
||||
includes examples and more detailed usage instructions.
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
:::note pass
|
||||
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 project.
|
||||
in the parsing logic, issues should then be raised with the SheetJS team.
|
||||
|
||||
:::
|
||||
|
||||
@ -30,7 +38,7 @@ in the parsing logic, issues should then be raised with the SheetJS project.
|
||||
`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:
|
||||
|
||||
<CodeBlock language="json">{`\
|
||||
<CodeBlock language="json" title="package.json (add highlighted lines)">{`\
|
||||
{
|
||||
"overrides": {
|
||||
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
|
||||
@ -40,11 +48,93 @@ overridden through a `package.json` override in the latest versions of NodeJS:
|
||||
|
||||
:::
|
||||
|
||||
## GraphQL details
|
||||
:::warning Telemetry
|
||||
|
||||
`gatsby-transformer-excel` generates nodes for each data row of each worksheet.
|
||||
Under the hood, it uses [`sheet_to_json`](/docs/api/utilities#array-output)
|
||||
to generate row objects using the headers in the first row as keys.
|
||||
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`:
|
||||
|
||||
<CodeBlock language="json" title="package.json (add highlighted lines)">{`\
|
||||
{
|
||||
// highlight-start
|
||||
"overrides": {
|
||||
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
|
||||
}
|
||||
// highlight-end
|
||||
}`}
|
||||
</CodeBlock>
|
||||
|
||||
`gatsby-transformer-excel` and `gatsby-source-filesystem` should be installed
|
||||
after installing SheetJS modules:
|
||||
|
||||
<Tabs groupId="pm">
|
||||
<TabItem value="npm" label="npm">
|
||||
<CodeBlock language="bash">{`\
|
||||
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`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="pnpm" label="pnpm">
|
||||
<CodeBlock language="bash">{`\
|
||||
npx gatsby telemetry --disable
|
||||
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
pnpm install gatsby-transformer-excel gatsby-source-filesystem`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="yarn" label="Yarn" default>
|
||||
<CodeBlock language="bash">{`\
|
||||
npx gatsby telemetry --disable
|
||||
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
yarn add gatsby-transformer-excel gatsby-source-filesystem`}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### 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)
|
||||
|
||||
@ -78,18 +168,28 @@ The following query pulls the `Name` and `Index` fields from each row:
|
||||
}
|
||||
```
|
||||
|
||||
## GatsbyJS Demo
|
||||
## Complete Example
|
||||
|
||||
:::note
|
||||
|
||||
This demo was tested on 2023 September 13 against `create-gatsby@3.12.0`. The
|
||||
generated project used `gatsby@5.12.4` and `react@18.2.0`.
|
||||
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
|
||||
|
||||
1) Run `npm init gatsby -- -y sheetjs-gatsby` to create the template site.
|
||||
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:
|
||||
|
||||
@ -157,7 +257,7 @@ Stop and restart the development server process (`npm run develop`).
|
||||
|
||||
### GraphiQL test
|
||||
|
||||
7) Open the GraphiQL editor at `http://localhost:8000/___graphql`.
|
||||
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:
|
||||
|
||||
@ -203,8 +303,8 @@ const PageComponent = ({data}) => {
|
||||
export default PageComponent;
|
||||
```
|
||||
|
||||
After saving the file, access `http://localhost:8000/pres`. The displayed JSON
|
||||
is the data that the component receives:
|
||||
After saving the file, access `http://localhost:8000/pres` in the browser. The
|
||||
displayed JSON is the data that the component receives:
|
||||
|
||||
```js
|
||||
{
|
||||
@ -301,3 +401,9 @@ There will be a HTML row:
|
||||
```html title="public/pres/index.html"
|
||||
<tr><td>SheetJS Dev</td><td>47</td></tr>
|
||||
```
|
||||
|
||||
[^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)
|
@ -25,14 +25,15 @@ plugin and compare a few different data loading strategies.
|
||||
The ["Complete Demo"](#complete-demo) section creates a complete website powered
|
||||
by a XLSX spreadsheet.
|
||||
|
||||
:::tip pass
|
||||
:::info pass
|
||||
|
||||
This demo covers use cases where data is available at build time. This flow is
|
||||
suitable for end of week or end of month (EOM) reports published in HTML tables
|
||||
suitable for end of week or end of month (EOM) reports published in HTML tables.
|
||||
|
||||
For processing user-submitted files in the browser, the
|
||||
["Bundlers" demo](/docs/demos/frontend/bundler#vite) shows client-side bundling
|
||||
of the SheetJS library.
|
||||
of the SheetJS library. The ["ReactJS" demo](/docs/demos/frontend/react) shows
|
||||
example sites using ViteJS with the ReactJS starter.
|
||||
|
||||
:::
|
||||
|
||||
|
@ -7,10 +7,15 @@ pagination_next: demos/mobile/index
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
Eleventy is a static site generator.
|
||||
[Eleventy](https://www.11ty.dev/docs) is a telemetry-free static site generator.
|
||||
The data pipeline can be augmented with custom data file parsers.
|
||||
|
||||
The [NodeJS module](/docs/getting-started/installation/nodejs) can be loaded in
|
||||
`.eleventy.js` and used in custom data file format parsers.
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
This demo uses Eleventy and SheetJS to pull data from a spreadsheet and display
|
||||
the content in a page. We'll explore how to load SheetJS libraries in a custom
|
||||
data file format parser and generate arrays of objects for use in pages.
|
||||
|
||||
The following diagram depicts the workbook waltz:
|
||||
|
||||
@ -27,19 +32,33 @@ flowchart LR
|
||||
aoo --> |index.njk\ntemplate| html
|
||||
```
|
||||
|
||||
:::tip No Telemetry
|
||||
|
||||
The author has publicly stated that Eleventy does not embed any telemetry or
|
||||
data collection.[^1]
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be
|
||||
loaded in `.eleventy.js` and used in custom data file format parsers.
|
||||
|
||||
### Data File Parser
|
||||
|
||||
Custom data file parsers must be registered in `.eleventy.js`
|
||||
|
||||
`addDataExtension` accepts a list of file extensions and a parser object.
|
||||
The Eleventy config `addDataExtension` method[^2] accepts a list of file
|
||||
extensions and a parser configuration object.
|
||||
|
||||
The parser object must include the options `read: true` and `encoding: null` .
|
||||
Eleventy will read files and pass raw `Buffer` objects to the parser callback.
|
||||
|
||||
The `parser` callback can parse the data with `XLSX.read`. In this demo, the
|
||||
parser will generate an array of row objects using `XLSX.utils.sheet_to_json`:
|
||||
The `parser` callback can parse the raw `Buffer` data with the SheetJS `read`
|
||||
method[^3]. The method returns a workbook object[^4].
|
||||
|
||||
In this example, the parser will use the SheetJS `sheet_to_json` method[^5] to
|
||||
generate an array of objects from the data in the first worksheet:
|
||||
|
||||
```js title=".eleventy.js"
|
||||
const XLSX = require("xlsx");
|
||||
@ -91,7 +110,7 @@ using the variable `pres` in a template:
|
||||
|
||||
:::note
|
||||
|
||||
This demo was tested on 2023 May 07 using Eleventy `2.0.1`
|
||||
This demo was tested on 2023 October 08 using Eleventy `2.0.1`
|
||||
|
||||
:::
|
||||
|
||||
@ -179,3 +198,9 @@ npx http-server _site
|
||||
Open a web browser and access the displayed URL ( `http://localhost:8080` ).
|
||||
View the page source and confirm that no JS was added to the page. It only
|
||||
contains the content from the file in an HTML table.
|
||||
|
||||
[^1]: See [the "Telemetry" section](https://www.zachleat.com/web/site-generator-review/#telemetry) of the site generator review from the author of Eleventy. When this page was last checked, the author proudly asserted that Eleventy had "No known Telemetry or data collection".
|
||||
[^2]: See ["Custom Data File Formats"](https://www.11ty.dev/docs/data-custom/) in the Eleventy 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)
|
@ -37,13 +37,11 @@ the browser refreshes to show the new content.
|
||||
|
||||
:::note Recommendation
|
||||
|
||||
It is strongly recommended to use a framework that provides an official plugin
|
||||
for working with SheetJS.
|
||||
It is strongly recommended to use a telemetry-free framework that provides an
|
||||
official plugin for working with SheetJS.
|
||||
|
||||
Lume is a great choice for lightweight sites.
|
||||
|
||||
GatsbyJS is excellent for teams well-versed in the ReactJS framework.
|
||||
|
||||
:::
|
||||
|
||||
### Official
|
||||
|
@ -145,10 +145,6 @@ If the file does not exist, servers will send a 404 response that may include a
|
||||
friendly HTML page. Without checking the response code, the integration will try
|
||||
to read the 404 page and fail since the HTML typically has no TABLE elements.
|
||||
|
||||
When building a project with CRA or other templates, spreadsheets must be placed
|
||||
in the `public` folder. That folder is served by the dev server and copied in
|
||||
the build process.
|
||||
|
||||
Integration code should defend against network issues by checking status code.
|
||||
For example, when using `fetch`:
|
||||
|
||||
@ -161,6 +157,14 @@ async function fetch_workbook_and_error_on_404(url) {
|
||||
}
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
When building a project with `create-react-app` or other templates, spreadsheets
|
||||
must be placed in the `public` folder. That folder is typically served by the
|
||||
dev server and copied to the production site in the build process.
|
||||
|
||||
:::
|
||||
|
||||
#### Cloudflare Worker "Error: Script startup exceeded CPU time limit."
|
||||
|
||||
This may show up in projects with many dependencies. The official workaround is
|
||||
|
Loading…
Reference in New Issue
Block a user