forked from sheetjs/docs.sheetjs.com
refresh
This commit is contained in:
parent
c76ec7f27d
commit
e3d16d8108
@ -216,7 +216,7 @@ in the example JSX code:
|
||||
```jsx title="Example JSX for displaying arrays of objects"
|
||||
<table>
|
||||
{/* The `thead` section includes the table header row */}
|
||||
<thead><th>Name</th><th>Index</th></thead>
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
{/* The `tbody` section includes the data rows */}
|
||||
<tbody>
|
||||
{/* generate row (TR) for each president */}
|
||||
@ -302,7 +302,7 @@ export default function SheetJSReactAoO() {
|
||||
writeFileXLSX(wb, "SheetJSReactAoO.xlsx");
|
||||
}, [pres]);
|
||||
|
||||
return (<table><thead><th>Name</th><th>Index</th></thead><tbody>
|
||||
return (<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
|
||||
{ /* generate row for each president */
|
||||
// highlight-start
|
||||
pres.map(pres => (<tr>
|
||||
@ -317,14 +317,18 @@ export default function SheetJSReactAoO() {
|
||||
}
|
||||
```
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
<details open><summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 08 with ViteJS 4.4.1 and React 18.2.0
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| ReactJS | ViteJS | Date |
|
||||
|:---------|:--------|:-----------|
|
||||
| `18.2.0` | `5.0.5` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -348,7 +352,7 @@ npm run dev`}
|
||||
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`.
|
||||
and the page will attempt to download `SheetJSReactAoO.xlsx`.
|
||||
|
||||
5) Build the site:
|
||||
|
||||
@ -370,7 +374,7 @@ and test the page.
|
||||
</TabItem>
|
||||
<TabItem name="CRA" value="create-react-app">
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023 October 24 using `create-react-app@5.0.1` and
|
||||
`react-scripts@5.0.1`.
|
||||
@ -397,7 +401,7 @@ npm start`}
|
||||
4) Replace `src/App.js` 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`.
|
||||
and the page will attempt to download `SheetJSReactAoO.xlsx`.
|
||||
|
||||
5) Build the site:
|
||||
|
||||
@ -474,12 +478,12 @@ export default function SheetJSReactHTML() {
|
||||
}
|
||||
```
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
<details open><summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
<Tabs groupId="starter">
|
||||
<TabItem name="vite" value="ViteJS">
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 08 with ViteJS 4.4.1 and React 18.2.0
|
||||
|
||||
@ -527,7 +531,7 @@ and test the page.
|
||||
</TabItem>
|
||||
<TabItem name="CRA" value="create-react-app">
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023 October 24 using `create-react-app@5.0.1` and
|
||||
`react-scripts@5.0.1`.
|
@ -241,7 +241,7 @@ const rows = ref([]);
|
||||
<template>
|
||||
<table>
|
||||
<!-- The `thead` section includes the table header row -->
|
||||
<thead><th>Name</th><th>Index</th></thead>
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<!-- The `tbody` section includes the data rows -->
|
||||
<tbody>
|
||||
<!-- generate row (TR) for each president -->
|
||||
@ -334,7 +334,7 @@ function exportFile() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table><thead><th>Name</th><th>Index</th></thead><tbody>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
|
||||
<tr v-for="(row, idx) in rows" :key="idx">
|
||||
<td>{{ row.Name }}</td>
|
||||
<td>{{ row.Index }}</td>
|
||||
@ -352,8 +352,11 @@ function exportFile() {
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023 November 09 using `vue@3.3.8`. When running
|
||||
`npm init`, the package `create-vue@3.8.0` was installed.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| VueJS | ViteJS | Date |
|
||||
|:--------|:--------|:-----------|
|
||||
| `3.3.9` | `4.5.1` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -377,7 +380,7 @@ npm run dev`}
|
||||
4) Replace `src/App.vue` with the `src/SheetJSVueAoO.vue` example.
|
||||
|
||||
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
|
||||
and the page will attempt to download `SheetJSVueAoO.xlsx`. There may be a delay
|
||||
since Vite will try to optimize the SheetJS library on the fly.
|
||||
|
||||
5) Stop the dev server and build the site:
|
||||
@ -427,7 +430,7 @@ npm run dev`}
|
||||
4) Replace `App.vue` with the `src/SheetJSVueAoO.vue` example.
|
||||
|
||||
The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSVueAoA.xlsx`.
|
||||
and the page will attempt to download `SheetJSVueAoO.xlsx`.
|
||||
|
||||
5) Stop the dev server and build the site:
|
||||
|
@ -219,7 +219,7 @@ storied syntax, instead opting for a `@for` block reminiscent of JavaScript[^4].
|
||||
|
||||
```html title="Example Template for displaying arrays of objects (Angular 2-16)"
|
||||
<div class="content" role="main"><table>
|
||||
<thead><th>Name</th><th>Index</th></thead>
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
// highlight-start
|
||||
<tr *ngFor="let row of rows">
|
||||
@ -236,7 +236,7 @@ storied syntax, instead opting for a `@for` block reminiscent of JavaScript[^4].
|
||||
|
||||
```html title="Example Template for displaying arrays of objects (Angular 17+)"
|
||||
<div class="content" role="main"><table>
|
||||
<thead><th>Name</th><th>Index</th></thead>
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
// highlight-start
|
||||
@for(row of rows; track $index) { <tr>
|
||||
@ -311,7 +311,7 @@ interface President { Name: string; Index: number };
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<div class="content" role="main"><table>
|
||||
<thead><th>Name</th><th>Index</th></thead>
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
// highlight-start
|
||||
<tr *ngFor="let row of rows">
|
||||
@ -367,7 +367,7 @@ interface President { Name: string; Index: number };
|
||||
standalone: true,
|
||||
template: `
|
||||
<div class="content" role="main"><table>
|
||||
<thead><th>Name</th><th>Index</th></thead>
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
// highlight-start
|
||||
@for(row of rows; track $index) {
|
||||
@ -414,11 +414,16 @@ export class AppComponent {
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
<details open><summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023-11-18 using Angular 17.0.3 and CLI `17.0.1`
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Angular | Date |
|
||||
|:---------|:-----------|
|
||||
| `17.0.5` | 2023-12-04 |
|
||||
| `16.2.7` | 2023-10-22 |
|
||||
|
||||
:::
|
||||
|
||||
@ -431,7 +436,7 @@ npx @angular/cli analytics disable -g
|
||||
1) Create a new project:
|
||||
|
||||
```bash
|
||||
npx @angular/cli@17.0.1 new --minimal --defaults --no-interactive sheetjs-angular
|
||||
npx @angular/cli@17.0.5 new --minimal --defaults --no-interactive sheetjs-angular
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
@ -590,7 +595,7 @@ export class AppComponent {
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
<details open><summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
:::note Tested Deployments
|
||||
|
@ -115,7 +115,7 @@ function exportFile() {
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<table><thead><th>Name</th><th>Index</th></thead><tbody>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
|
||||
<!-- highlight-start -->
|
||||
{#each pres as p}<tr>
|
||||
<td>{p.Name}</td>
|
||||
@ -128,16 +128,23 @@ function exportFile() {
|
||||
</main>
|
||||
```
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
<details open><summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023 August 27 using `svelte@4.2.0`. When running
|
||||
`npm create`, the package `create-vite@4.4.1` was installed.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Svelte | ViteJS | Date |
|
||||
|:--------|:--------|:-----------|
|
||||
| `4.2.8` | `5.0.5` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
1) Run `npm create vite@latest sheetjs-svelte -- --template svelte-ts`.
|
||||
1) Create a new project:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-svelte -- --template svelte-ts
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
@ -156,8 +163,22 @@ The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSSvelteAoA.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>
|
||||
|
||||
@ -206,16 +227,23 @@ function exportFile() {
|
||||
</main>
|
||||
```
|
||||
|
||||
<details open><summary><b>How to run the example</b> (click to show)</summary>
|
||||
<details open><summary><b>How to run the example</b> (click to hide)</summary>
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023 August 27 using `svelte@4.2.0`. When running
|
||||
`npm create`, the package `create-vite@4.4.1` was installed.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Svelte | ViteJS | Date |
|
||||
|:--------|:--------|:-----------|
|
||||
| `4.2.8` | `5.0.5` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
1) Run `npm create vite@latest sheetjs-svelte -- --template svelte-ts`.
|
||||
1) Create a new project:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-svelte -- --template svelte-ts
|
||||
```
|
||||
|
||||
2) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
@ -234,7 +262,21 @@ The page will refresh and show a table with an Export button. Click the button
|
||||
and the page will attempt to download `SheetJSSvelteHTML.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>
|
@ -32,7 +32,12 @@ models and data flow strategies.
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023 November 19 using AngularJS `1.8.2`
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:------------------|:-----------|
|
||||
| `1.8.2` (latest) | 2023-12-04 |
|
||||
| `1.2.32` (legacy) | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -294,7 +299,7 @@ However, this does not handle merge cells well!
|
||||
The `sheet_to_html` function generates HTML that is aware of merges and other
|
||||
worksheet features. The generated HTML does not contain any `<script>` tags,
|
||||
and should therefore be safe to pass to an `ng-bind-html` binding. This approach
|
||||
requires the `ngSanitize` plugin.
|
||||
requires the `ngSanitize` plugin[^4].
|
||||
|
||||
```html
|
||||
<div ng-controller="sheetjs">
|
||||
@ -381,4 +386,5 @@ URL with a web browser (typically `http://localhost:8080`)
|
||||
|
||||
[^1]: See [`$http`](https://docs.angularjs.org/api/ng/service/$http) in the AngularJS documentation.
|
||||
[^2]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^3]: See ["Creating Directives"](https://docs.angularjs.org/guide/directive#creating-a-directive-that-manipulates-the-dom) in the AngularJS documentation.
|
||||
[^3]: See ["Creating Directives"](https://docs.angularjs.org/guide/directive#creating-a-directive-that-manipulates-the-dom) in the AngularJS documentation.
|
||||
[^4]: See [`ngSanitize`](https://docs.angularjs.org/api/ngSanitize) in the AngularJS documentation.
|
@ -72,7 +72,7 @@ The script <https://docs.sheetjs.com/dojo/dojo.js> was fetched from the official
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
The demos were last tested on 2023-11-27.
|
||||
The demos were last tested on 2023-12-04.
|
||||
|
||||
Demos exclusively using Dojo Core were tested using Dojo Toolkit `1.17.3`.
|
||||
|
||||
@ -151,7 +151,7 @@ in the first worksheet, and assigns to a `dijit` UI Widget:
|
||||
```html
|
||||
<script>
|
||||
require([
|
||||
"dojo/ready", "dojo/request/xhr", "dojo/store/Memory" "dijit/registry", "xlsx"
|
||||
"dojo/ready", "dojo/request/xhr", "dojo/store/Memory", "dijit/registry", "xlsx"
|
||||
], function(ready, xhr, Memory, registry, _XLSX) {
|
||||
ready(function() {
|
||||
/* fetch test file */
|
@ -203,6 +203,12 @@ KnockoutJS was a popular MVVM framework.
|
||||
The [Live demo](pathname:///knockout/knockout.html) shows a view model that is
|
||||
updated with file data and exported to spreadsheets.
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last run on 2023 December 04 using KnockoutJS `3.4.2`
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>Full Exposition</b> (click to show)</summary>
|
||||
|
||||
**State**
|
@ -17,7 +17,7 @@ import CodeBlock from '@theme/CodeBlock';
|
||||
data from spreadsheets.
|
||||
|
||||
This demo uses ViteJS and SheetJS to export data. We'll explore how to add
|
||||
SheetJS to a site using Browserify and how to export data to spreadsheets.
|
||||
SheetJS to a site using ViteJS and how to export data to spreadsheets.
|
||||
|
||||
:::info pass
|
||||
|
||||
@ -26,9 +26,23 @@ loaders. They are ideal for static sites pulling data from sheets at build time.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was last tested on 2023 October 21 against ViteJS `4.5.0`
|
||||
This demo focuses on integration details with the ViteJS bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| ViteJS | Date |
|
||||
|:---------|:-----------|
|
||||
| `5.0.5` | 2023-12-04 |
|
||||
| `4.5.0` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -89,6 +103,10 @@ 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,
|
@ -25,15 +25,6 @@ bundle with ESBuild for browser use.
|
||||
- ["NodeJS"](#nodejs) explores how to import SheetJS libraries in a script and
|
||||
bundle with ESBuild for NodeJS use.
|
||||
|
||||
:::note pass
|
||||
|
||||
This demo focuses on integration details with the ESBuild bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export).
|
||||
The tutorial covers SheetJS library usage.
|
||||
|
||||
:::
|
||||
|
||||
:::info pass
|
||||
|
||||
The [ESBuild section of the Content demo](/docs/demos/static/esbuild) covers
|
||||
@ -41,9 +32,23 @@ loaders. They are ideal for static sites pulling data from sheets at build time.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was last tested on 2023 October 19 against esbuild `0.19.5`
|
||||
This demo focuses on integration details with the ESBuild bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| ESBuild | Date |
|
||||
|:----------|:-----------|
|
||||
| `0.14.14` | 2023-12-04 |
|
||||
| `0.19.8` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -71,7 +76,7 @@ Assuming the primary source file is `in.js`, the following command will bundle
|
||||
the script and generate `out.js`:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.19.5 in.js --bundle --outfile=out.js
|
||||
npx -y esbuild@0.19.8 in.js --bundle --outfile=out.js
|
||||
```
|
||||
|
||||
### Browser Demo
|
||||
@ -120,7 +125,7 @@ curl -LO https://docs.sheetjs.com/esbuild/esbrowser.js
|
||||
4) Create bundle:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.19.5 esbrowser.js --bundle --outfile=esb.browser.js
|
||||
npx -y esbuild@0.19.8 esbrowser.js --bundle --outfile=esb.browser.js
|
||||
```
|
||||
|
||||
5) Start a local HTTP server:
|
||||
@ -160,7 +165,7 @@ Assuming the primary source file is `in.js`, the following command will bundle
|
||||
the script for NodeJS and generate `out.js`:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.19.5 in.js --bundle --platform=node --outfile=out.js
|
||||
npx -y esbuild@0.19.8 in.js --bundle --platform=node --outfile=out.js
|
||||
```
|
||||
|
||||
### NodeJS Demo
|
||||
@ -209,7 +214,7 @@ curl -LO https://docs.sheetjs.com/esbuild/esbnode.js
|
||||
3) Create bundle:
|
||||
|
||||
```bash
|
||||
npx -y esbuild@0.19.5 esbnode.js --bundle --platform=node --outfile=esb.node.js
|
||||
npx -y esbuild@0.19.8 esbnode.js --bundle --platform=node --outfile=esb.node.js
|
||||
```
|
||||
|
||||
4) Run the bundle:
|
@ -26,16 +26,25 @@ loaders. They are ideal for static sites pulling data from sheets at build time.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was tested against the following Webpack versions:
|
||||
This demo focuses on integration details with the Webpack bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date | Required Workarounds |
|
||||
|:---------|:-----------|:------------------------------------|
|
||||
| `2.7.0` | 2023-10-17 | Import `xlsx/dist/xlsx.full.min.js` |
|
||||
| `3.12.0` | 2023-10-17 | Import `xlsx/dist/xlsx.full.min.js` |
|
||||
| `4.47.0` | 2023-10-17 | Downgrade NodeJS (tested v16.20.2) |
|
||||
| `5.89.0` | 2023-10-17 | |
|
||||
| `5.89.0` | 2023-12-04 | |
|
||||
|
||||
:::
|
||||
|
||||
@ -304,12 +313,14 @@ npx webpack --mode=production
|
||||
</html>
|
||||
```
|
||||
|
||||
6) Start a local HTTP server and go to `http://localhost:8080/`
|
||||
6) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
```
|
||||
|
||||
7) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
Click on "Click here to export" to generate a file.
|
||||
|
||||
## Miscellany
|
@ -19,9 +19,23 @@ data from spreadsheets.
|
||||
This demo uses Browserify and SheetJS to export data. We'll explore how to add
|
||||
SheetJS to a site using Browserify and how to export data to spreadsheets.
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was last tested on 2023 October 21 against Browserify `17.0.0`
|
||||
This demo focuses on integration details with the Browserify bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Browserify | Date |
|
||||
|:-----------|:-----------|
|
||||
| `17.0.0` | 2023-12-04 |
|
||||
| `3.46.1` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -119,16 +133,21 @@ document.getElementById("xport").addEventListener("click", function() {
|
||||
3) Bundle the scripts:
|
||||
|
||||
```bash
|
||||
npx browserify app.js > browserify.js
|
||||
npx browserify index.js > index.min.js
|
||||
```
|
||||
|
||||
4) Spin up a local web server:
|
||||
:::caution pass
|
||||
|
||||
Legacy `browserify` versions must use a local version. For version `3.46.1`:
|
||||
|
||||
```bash
|
||||
npx http-server
|
||||
npm install --save browserify@3.46.1
|
||||
./node_modules/.bin/browserify index.js > index.min.js
|
||||
```
|
||||
|
||||
5) Create a small HTML page that loads the script. Save to `index.html`:
|
||||
:::
|
||||
|
||||
4) Create a small HTML page that loads the script. Save to `index.html`:
|
||||
|
||||
```html title="index.html"
|
||||
<!DOCTYPE html>
|
||||
@ -142,10 +161,12 @@ npx http-server
|
||||
</html>
|
||||
```
|
||||
|
||||
6) Start a local HTTP server and go to `http://localhost:8080/`
|
||||
5) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
```
|
||||
|
||||
6) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
Click on "Click here to export" to generate a file.
|
@ -25,9 +25,23 @@ The [Live demo](pathname:///requirejs/requirejs.html) loads RequireJS from the
|
||||
CDN, uses it to load the standalone script from the SheetJS CDN, and uses the
|
||||
`XLSX` variable to create a button click handler that creates a workbook.
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was last tested on 2023 October 18 against RequireJS `2.3.6`
|
||||
This demo focuses on integration details with the RequireJS loader.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| RequireJS | Date |
|
||||
|:----------|:-----------|
|
||||
| `2.3.6` | 2023-12-04 |
|
||||
| `2.1.22` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -114,6 +128,7 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
|
||||
<body>
|
||||
<h1>SheetJS Presidents Demo</h1>
|
||||
<button id="xport">Click here to export</button>
|
||||
<!-- highlight-next-line -->
|
||||
<script src="http://requirejs.org/docs/release/2.3.6/comments/require.js"></script>
|
||||
<script>
|
||||
/* Wire up RequireJS */
|
||||
@ -130,6 +145,17 @@ require.config({
|
||||
</html>
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
To change the RequireJS version, change the version in the highlighted line. For
|
||||
example, the following script corresponds to RequireJS `2.1.22`:
|
||||
|
||||
```html
|
||||
<script src="http://requirejs.org/docs/release/2.1.22/comments/require.js"></script>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
2) Save the following to `SheetJSRequire.js`:
|
||||
|
||||
```js title="SheetJSRequire.js"
|
||||
@ -142,6 +168,10 @@ require(["xlsx"], function(XLSX) {
|
||||
/* filter for the Presidents */
|
||||
var prez = raw_data.filter(function(row) { return row.terms.some(function(term) { return term.type === "prez"; }); });
|
||||
|
||||
/* sort by first presidential term */
|
||||
prez.forEach(function(row) { row.start = row.terms.find(function(term) {return term.type === "prez"; }).start; });
|
||||
prez.sort(function(l,r) { return l.start.localeCompare(r.start); });
|
||||
|
||||
/* flatten objects */
|
||||
var rows = prez.map(function(row) { return {
|
||||
name: row.name.first + " " + row.name.last,
|
||||
@ -176,17 +206,19 @@ uses normal functions and traditional Promise chains.
|
||||
|
||||
:::
|
||||
|
||||
3) Start a local HTTP server, then go to `http://localhost:8080/`
|
||||
3) Start a local HTTP server:
|
||||
|
||||
```bash
|
||||
npx http-server .
|
||||
```
|
||||
|
||||
4) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.
|
||||
|
||||
Click on "Click here to export" to generate a file.
|
||||
|
||||
### r.js Optimizer
|
||||
|
||||
4) Create `build.js` configuration for the optimizer:
|
||||
5) Create `build.js` configuration for the optimizer:
|
||||
|
||||
```js title="build.js"
|
||||
({
|
||||
@ -199,12 +231,23 @@ Click on "Click here to export" to generate a file.
|
||||
});
|
||||
```
|
||||
|
||||
5) Run the `r.js` optimizer to create `SheetJSRequire.min.js`:
|
||||
6) Run the `r.js` optimizer to create `SheetJSRequire.min.js`:
|
||||
|
||||
```bash
|
||||
npx -p requirejs@2.3.6 r.js -o build.js
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
To change the RequireJS version, change the version in the command. For example,
|
||||
the following command uses RequireJS `2.1.22` to generate an optimized script:
|
||||
|
||||
```bash
|
||||
npx -p requirejs@2.1.22 r.js -o build.js
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
6) Save the following to `optimized.html`:
|
||||
|
||||
```html title="optimized.html"
|
||||
@ -214,12 +257,24 @@ npx -p requirejs@2.3.6 r.js -o build.js
|
||||
<body>
|
||||
<h1>SheetJS Presidents Demo</h1>
|
||||
<button id="xport">Click here to export</button>
|
||||
<script src="http://requirejs.org/docs/release/2.3.3/comments/require.js"></script>
|
||||
<!-- highlight-next-line -->
|
||||
<script src="http://requirejs.org/docs/release/2.3.6/comments/require.js"></script>
|
||||
<script src="SheetJSRequire.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
7) Open `http://localhost:8080/optimized.html`
|
||||
:::note pass
|
||||
|
||||
To change the RequireJS version, change the version in the highlighted line. For
|
||||
example, the following script corresponds to RequireJS `2.1.22`:
|
||||
|
||||
```html
|
||||
<script src="http://requirejs.org/docs/release/2.1.22/comments/require.js"></script>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
7) Open `optimized.html` in the browser (`http://localhost:8080/optimized.html`)
|
||||
|
||||
Click on "Click here to export" to generate a file.
|
@ -31,16 +31,26 @@ other tools using SystemJS have switched to Webpack.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was tested against the following SystemJS versions:
|
||||
This demo focuses on integration details with the SystemJS loader.
|
||||
|
||||
| Version | Date |
|
||||
|:----------|:-----------|
|
||||
| `0.19.47` | 2023-10-18 |
|
||||
| `0.20.19` | 2023-10-18 |
|
||||
| `0.21.6` | 2023-10-18 |
|
||||
| `6.14.2` | 2023-10-18 |
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Platform | Date |
|
||||
|:----------|:---------|:-----------|
|
||||
| `0.19.47` | NodeJS | 2023-10-18 |
|
||||
| `0.20.16` | Browser | 2023-12-04 |
|
||||
| `0.20.19` | NodeJS | 2023-10-18 |
|
||||
| `0.21.6` | NodeJS | 2023-10-18 |
|
||||
| `6.14.2` | NodeJS | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
@ -19,9 +19,23 @@ data from spreadsheets.
|
||||
This demo uses RollupJS and SheetJS to export data. We'll explore how to bundle
|
||||
SheetJS in a site using RollupJS and how to export data to spreadsheets.
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was last tested on 2023 October 21 against RollupJS 4.1.4
|
||||
This demo focuses on integration details with the RollupJS bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:--------|:-----------|
|
||||
| `4.6.1` | 2023-12-04 |
|
||||
| `4.1.4` | 2023-10-21 |
|
||||
|
||||
:::
|
||||
|
||||
@ -62,17 +76,17 @@ npm init -y
|
||||
<Tabs groupId="pm">
|
||||
<TabItem value="npm" label="npm">
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@4.1.4 @rollup/plugin-node-resolve
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@4.6.1 @rollup/plugin-node-resolve
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="pnpm" label="pnpm">
|
||||
<CodeBlock language="bash">{`\
|
||||
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@4.1.4 @rollup/plugin-node-resolve
|
||||
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@4.6.1 @rollup/plugin-node-resolve
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="yarn" label="Yarn" default>
|
||||
<CodeBlock language="bash">{`\
|
||||
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@4.1.4 @rollup/plugin-node-resolve
|
||||
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup@4.6.1 @rollup/plugin-node-resolve
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@ -91,6 +105,10 @@ 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,
|
@ -19,9 +19,23 @@ 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
|
||||
:::note pass
|
||||
|
||||
This demo was last tested on 2023 October 21 against parcel `2.10.0`
|
||||
This demo focuses on integration details with the ParcelJS bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
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 |
|
||||
|
||||
:::
|
||||
|
||||
@ -78,6 +92,10 @@ document.getElementById("xport").onclick = async() => {
|
||||
/* 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,
|
||||
@ -103,6 +121,67 @@ document.getElementById("xport").onclick = async() => {
|
||||
<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:
|
||||
|
||||
<details><summary><b>ParcelJS v1 example</b> (click to show)</summary>
|
||||
|
||||
```html title="index.html"
|
||||
<body>
|
||||
<h3>SheetJS <span id="vers"></span> export demo</h3>
|
||||
<button id="xport">Click to Export!</button>
|
||||
<script src="index.js"></script>
|
||||
<body>
|
||||
```
|
||||
|
||||
```js title="index.js"
|
||||
// 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");
|
||||
};
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
2) Install the SheetJS NodeJS module:
|
||||
|
||||
<Tabs groupId="pm">
|
||||
@ -128,7 +207,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
3) Run the ParcelJS development server:
|
||||
|
||||
```bash
|
||||
npx -y parcel@2.10.0 index.html
|
||||
npx -y parcel@2.10.3 index.html
|
||||
```
|
||||
|
||||
The process will print a URL:
|
@ -20,9 +20,22 @@ data from spreadsheets.
|
||||
This demo uses `spack` and SheetJS to export data. We'll explore how to bundle
|
||||
SheetJS in a site using `spack` and how to export data to spreadsheets.
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo was last tested on 2023 October 20 against SWC 1.2.246
|
||||
This demo focuses on integration details with the `spack` bundler.
|
||||
|
||||
The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export),
|
||||
which covers SheetJS library usage in more detail.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:----------|:-----------|
|
||||
| `1.2.246` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -52,12 +65,14 @@ import { utils, writeFile } from 'xlsx';
|
||||
|
||||
:::warning pass
|
||||
|
||||
When this demo was tested against the latest version, `spack` crashed:
|
||||
When this demo was tested against the `@swc/core@1.3.100`, `spack` crashed:
|
||||
|
||||
```
|
||||
thread '<unnamed>' panicked at 'cannot access a scoped thread local variable without calling `set` first',
|
||||
```
|
||||
|
||||
**This is a bug in SWC**
|
||||
|
||||
Until the bug is fixed, it is strongly recommended to use `@swc/core@1.2.246`.
|
||||
|
||||
:::
|
||||
@ -112,6 +127,10 @@ 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,
|
||||
@ -174,7 +193,7 @@ This command will create the script `lib/web.js`
|
||||
6) Start a local HTTP server, then go to `http://localhost:8080/`
|
||||
|
||||
```bash
|
||||
npx http-server
|
||||
npx http-server .
|
||||
```
|
||||
|
||||
Click on "Click here to export" to generate a file.
|
@ -47,9 +47,13 @@ Snowpack works with no caveats.
|
||||
|
||||
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 21 against Snowpack `3.8.8`
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:--------|:-----------|
|
||||
| `3.8.8` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -95,6 +99,10 @@ 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,
|
||||
@ -160,9 +168,13 @@ WMR works with no caveats.
|
||||
|
||||
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 Oct 21 against WMR `3.8.0`
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date |
|
||||
|:--------|:-----------|
|
||||
| `3.8.0` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -208,6 +220,10 @@ 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,
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"label": "Web Frameworks",
|
||||
"position": 1
|
||||
"position": 2
|
||||
}
|
@ -64,4 +64,8 @@ The following demos are in separate pages:
|
||||
return (<li style={listyle} {...(item.customProps?.class ? {className: item.customProps.class}: {})}>
|
||||
<a href={item.href}>{item.label}</a>{item.customProps?.summary && (" - " + item.customProps.summary)}
|
||||
</li>);
|
||||
})}</ul>
|
||||
})}
|
||||
<li><a href="/docs/demos/frontend/bundler#dojo">Dojo Toolkit</a></li>
|
||||
<li><a href="/docs/demos/frontend/bundler#snowpack">Snowpack</a></li>
|
||||
<li><a href="/docs/demos/frontend/bundler#wmr">WMR</a></li>
|
||||
</ul>
|
@ -365,7 +365,7 @@ function SheetJSPreviewPSTSheets() {
|
||||
<p>Use the file input to select a file, or click "Use a Sample PST"</p>
|
||||
<input type="file" accept=".pst" onChange={chg}/>
|
||||
<button onClick={doit}>Use a Sample PST!</button><br/><br/>
|
||||
<table><thead><th colspan="3">Attachments</th></thead>
|
||||
<table><thead><tr><th colspan="3">Attachments</th></tr></thead>
|
||||
<tbody>{files.map((f,j) => (
|
||||
<tr key={j}><th>{f.filename}</th>
|
||||
<td><a onClick={()=>view(j)}>(preview)</a></td>
|
||||
|
@ -14,9 +14,9 @@ With a familiar UI, `x-spreadsheet` is an excellent choice for a modern editor.
|
||||
|
||||
[Click here for a live standalone integration demo.](pathname:///xspreadsheet/)
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last verified on 2023 September 03.
|
||||
This demo was last verified on 2023 December 04.
|
||||
|
||||
:::
|
||||
|
@ -13,9 +13,9 @@ with a straightforward API.
|
||||
|
||||
[Click here for a live standalone integration demo.](pathname:///cdg/)
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last verified on 2023 September 03.
|
||||
This demo was last verified on 2023 December 04.
|
||||
|
||||
:::
|
||||
|
@ -9,8 +9,8 @@ import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested against `vue3-table-lite 1.3.9`, VueJS `3.3.7` and ViteJS
|
||||
`4.5.0` on 2023 November 03.
|
||||
This demo was tested against `vue3-table-lite 1.3.9`, VueJS `3.3.10` and ViteJS
|
||||
`5.0.5` on 2023 December 04.
|
||||
|
||||
:::
|
||||
|
||||
@ -114,7 +114,7 @@ cd sheetjs-vtl
|
||||
2) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz vue3-table-lite@1.2.4`}
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz vue3-table-lite@1.3.9`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Download [`src/App.vue`](pathname:///vtl/App.vue) and replace the contents:
|
@ -24,9 +24,9 @@ user-supplied sheets and exports data to XLSX workbooks:
|
||||
|
||||
![Glide Data Grid example](pathname:///gdg/gdg.png)
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 September 08 with Glide Data Grid 5.2.1
|
||||
This demo was last tested on 2023 December 04 with Glide Data Grid 5.3.2
|
||||
|
||||
:::
|
||||
|
||||
@ -38,7 +38,7 @@ installation with Yarn and other package managers.
|
||||
Using the `npm` tool, this command installs SheetJS and Glide Data Grid:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @glideapps/glide-data-grid@5.2.1`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @glideapps/glide-data-grid@5.3.2`}
|
||||
</CodeBlock>
|
||||
|
||||
Methods and components in both libraries can be loaded in pages using `import`:
|
||||
@ -340,10 +340,10 @@ cd sheetjs-gdg
|
||||
npm i
|
||||
```
|
||||
|
||||
2) Install SheetJS and Glide Data Grid required dependencies:
|
||||
2) Install SheetJS and Glide Data Grid libraries:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @glideapps/glide-data-grid@5.2.1`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @glideapps/glide-data-grid@5.3.2`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Start dev server:
|
@ -7,19 +7,59 @@ pagination_next: demos/net/index
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
:::note
|
||||
[React Data Grid](https://adazzle.github.io/react-data-grid/) is a data grid
|
||||
designed for the ReactJS web framework.
|
||||
|
||||
This demo was last tested on 2023 September 17 with `react-data-grid` version
|
||||
`7.0.0-beta.39` and React 18.2.0.
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
:::
|
||||
This demo uses React Data Grid and SheetJS to pull data from a spreadsheet and
|
||||
display the content in a data grid. We'll explore how to import data from files
|
||||
into the data grid and how to export modified data from the grid to workbooks.
|
||||
|
||||
The demo creates a site that looks like the screenshot below:
|
||||
The ["Demo"](#demo) section includes a complete example that displays data from
|
||||
user-supplied sheets and exports data to XLSX workbooks:
|
||||
|
||||
![react-data-grid screenshot](pathname:///rdg/rdg1.png)
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Date | Notes |
|
||||
|:----------------|:-----------|:---------------------|
|
||||
| `7.0.0-beta.19` | 2023-12-04 | |
|
||||
| `7.0.0-beta.41` | 2023-12-04 | Editing did not work |
|
||||
|
||||
:::
|
||||
|
||||
:::warning pass
|
||||
|
||||
When this demo was last tested, the grid correctly displayed data but could not
|
||||
be edited by the user.
|
||||
|
||||
The current recommendation is to use version `7.0.0-beta.19`.
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
|
||||
installation with Yarn and other package managers.
|
||||
|
||||
Using the `npm` tool, this command installs SheetJS and React Data Grid:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz react-data-grid@7.0.0-beta.41`}
|
||||
</CodeBlock>
|
||||
|
||||
Methods and components in both libraries can be loaded in pages using `import`:
|
||||
|
||||
```js
|
||||
import { read, utils, writeFile } from 'xlsx';
|
||||
import DataGrid, { Column } from "react-data-grid";
|
||||
```
|
||||
|
||||
#### Rows and Columns state
|
||||
|
||||
`react-data-grid` state consists of an Array of column metadata and an Array of
|
||||
@ -116,7 +156,7 @@ cd sheetjs-rdg
|
||||
2) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz react-data-grid@7.0.0-beta.39`}
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz react-data-grid@7.0.0-beta.41`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Download [`App.tsx`](pathname:///rdg/App.tsx) and replace `src/App.tsx`.
|
@ -9,6 +9,11 @@ import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
This demo covers the traditional Material UI Table as well as the MUI Data Grid.
|
||||
|
||||
## Integration Details
|
||||
|
||||
[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
|
||||
installation in projects using Material UI.
|
||||
|
||||
## Material UI Table
|
||||
|
||||
The `Table` component abstracts the `<table>` element in HTML. `table_to_book`
|
||||
@ -18,8 +23,10 @@ can process a `ref` attached to the `Table` element:
|
||||
import TableContainer from '@mui/material/TableContainer';
|
||||
import Table from '@mui/material/Table';
|
||||
// ...
|
||||
// highlight-next-line
|
||||
// highlight-start
|
||||
import { utils, writeFileXLSX } from "xlsx";
|
||||
import { useRef } from "react";
|
||||
// highlight-end
|
||||
|
||||
// ...
|
||||
export default function BasicTable() {
|
||||
@ -41,13 +48,11 @@ export default function BasicTable() {
|
||||
}
|
||||
```
|
||||
|
||||
#### MUI Table Demo
|
||||
### MUI Table Demo
|
||||
|
||||
<details open><summary><b>Complete Example</b> (click to hide)</summary>
|
||||
:::note Tested Deployments
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last run on 2023 October 12 against Material UI 5.14.13 paired
|
||||
This demo was last run on 2023 December 04 against Material UI 5.14.19 paired
|
||||
with Emotion 11.11.1
|
||||
|
||||
:::
|
||||
@ -62,7 +67,7 @@ cd sheetjs-mui
|
||||
2) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material@5.14.13 @emotion/react@11.11.1 @emotion/styled@11.11.0`}
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material@5.14.19 @emotion/react@11.11.1 @emotion/styled@11.11.0`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Download [`App.tsx`](pathname:///mui/table/App.tsx) and replace `src/App.tsx`.
|
||||
@ -80,8 +85,6 @@ npm run dev
|
||||
The script should open the live demo in a web browser. Click the "Export" button
|
||||
to save the file. Open the generated file in a spreadsheet editor.
|
||||
|
||||
</details>
|
||||
|
||||
## Material UI Data Grid
|
||||
|
||||
[A complete example is included below.](#muidg-demo)
|
||||
@ -186,15 +189,13 @@ export default function App() {
|
||||
|
||||
<!-- spellchecker-disable -->
|
||||
|
||||
#### MUIDG Demo
|
||||
### MUIDG Demo
|
||||
|
||||
<!-- spellchecker-enable -->
|
||||
|
||||
<details open><summary><b>Complete Example</b> (click to hide)</summary>
|
||||
:::note Tested Deployments
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last run on 2023 October 12 against MUI data grid 6.3.1 paired
|
||||
This demo was last run on 2023 December 04 against MUI data grid 6.18.3 paired
|
||||
with Emotion 11.11.1
|
||||
|
||||
:::
|
||||
@ -209,7 +210,7 @@ cd sheetjs-muidg
|
||||
2) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid@6.16.1 @emotion/react@11.11.1 @emotion/styled@11.11.0`}
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid@6.18.3 @emotion/react@11.11.1 @emotion/styled@11.11.0`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Download [`App.tsx`](pathname:///mui/dg/App.tsx) and replace `src/App.tsx`.
|
||||
@ -225,5 +226,3 @@ npm run dev
|
||||
```
|
||||
|
||||
When the page loads, it will fetch and process <https://sheetjs.com/pres.numbers>
|
||||
|
||||
</details>
|
@ -65,7 +65,7 @@ the variable `pres` in a template.
|
||||
When a workbook has one worksheet, the data is an array of row objects:
|
||||
|
||||
```liquid title="single.njk"
|
||||
<table><thead><th>Name</th><th>Index</th></thead>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in pres %}
|
||||
<tr>
|
||||
@ -99,7 +99,7 @@ named `"VicePresidents"`, then the following snippet would print data from the
|
||||
`"Presidents"` sheet:
|
||||
|
||||
```liquid title="multi.njk"
|
||||
<table><thead><th>Name</th><th>Index</th></thead>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in pres["Presidents"] %}
|
||||
<tr>
|
||||
@ -127,9 +127,9 @@ site.use(sheets({
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested against `lume v1.19.1` on 2023 October 14.
|
||||
This demo was last tested against Lume `v1.19.4` on 2023 December 04.
|
||||
|
||||
This example uses the Nunjucks template format. Lume plugins support additional
|
||||
template formats, including Markdown and JSX.
|
||||
@ -156,7 +156,7 @@ When prompted, enter the following options:
|
||||
|
||||
The project will be configured and modules will be installed.
|
||||
|
||||
2) Download <https://sheetjs.com/pres.xlsx> and place in a `_data` folder:
|
||||
2) Download <https://sheetjs.com/pres.xlsx> and place in a `_data` subfolder:
|
||||
|
||||
```bash
|
||||
mkdir -p _data
|
||||
@ -167,7 +167,7 @@ curl -L -o _data/pres.xlsx https://sheetjs.com/pres.xlsx
|
||||
|
||||
```liquid title="index.njk"
|
||||
<h2>Presidents</h2>
|
||||
<table><thead><th>Name</th><th>Index</th></thead>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in pres %}
|
||||
<tr>
|
||||
@ -179,7 +179,11 @@ curl -L -o _data/pres.xlsx https://sheetjs.com/pres.xlsx
|
||||
</table>
|
||||
```
|
||||
|
||||
Since the file name is `pres.xlsx`, the parameter name is `pres`:
|
||||
:::note pass
|
||||
|
||||
Since the file name is `pres.xlsx`, the parameter name is `pres`.
|
||||
|
||||
:::
|
||||
|
||||
### Live Refresh
|
||||
|
||||
@ -189,11 +193,12 @@ Since the file name is `pres.xlsx`, the parameter name is `pres`:
|
||||
deno task serve --port 7262
|
||||
```
|
||||
|
||||
To verify it works, access `http://localhost:7262` from your web browser. The
|
||||
page will show the contents of the spreadsheet.
|
||||
To verify the site, access the "Local" URL (typically `http://localhost:7262`)
|
||||
from a web browser. The page will show the contents of the spreadsheet.
|
||||
|
||||
5) While the server is still running, open `_data/pres.xlsx` in a spreadsheet
|
||||
editor and add a new row at the bottom of the sheet.
|
||||
5) While the server is running, open `_data/pres.xlsx` in a spreadsheet editor.
|
||||
|
||||
Set cell `A7` to "SheetJS Dev" and set `B7` to `47`. Save the spreadsheet.
|
||||
|
||||
After saving the spreadsheet, the page will refresh and show the new contents.
|
||||
|
@ -170,10 +170,10 @@ The following query pulls the `Name` and `Index` fields from each row:
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
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`.
|
||||
This demo was tested on 2023 December 04 against `create-gatsby@3.12.3`. The
|
||||
generated project used `gatsby@5.12.11` and `react@18.2.0`.
|
||||
|
||||
:::
|
||||
|
||||
@ -202,7 +202,7 @@ 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:
|
||||
|
||||
<CodeBlock language="json">{`\
|
||||
<CodeBlock language="json" title="package.json (add highlighted lines)">{`\
|
||||
{
|
||||
// highlight-start
|
||||
"overrides": {
|
||||
@ -232,7 +232,7 @@ 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"
|
||||
```js title="gatsby-config.js (add highlighted lines)"
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: `sheetjs-gatsby`,
|
||||
@ -257,11 +257,12 @@ 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. 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:
|
||||
|
||||
```graphql
|
||||
```graphql title="GraphQL Query (paste into editor)"
|
||||
{
|
||||
allPresXlsxSheet1 {
|
||||
edges {
|
||||
@ -274,7 +275,7 @@ There is an editor in the left pane. Paste the following query into the editor:
|
||||
}
|
||||
```
|
||||
|
||||
Press the Execute Query button and data should show up in the right pane:
|
||||
Press the Execute Query button (`▶`) and data should show up in the right pane:
|
||||
|
||||
![GraphiQL Screenshot](pathname:///gatsby/graphiql.png)
|
||||
|
||||
@ -306,7 +307,7 @@ 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
|
||||
```js title="Expected contents of /pres"
|
||||
{
|
||||
"allPresXlsxSheet1": {
|
||||
"edges": [
|
||||
@ -358,21 +359,27 @@ Going back to the browser, `http://localhost:8000/pres` will show a table:
|
||||
|
||||
### 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:
|
||||
10) Open the file `src/data/pres.xlsx` in Excel or another spreadsheet editor.
|
||||
Add a new row at the end of the file, setting cell `A7` to "SheetJS Dev" and
|
||||
cell `B7` to `47`. The sheet should look like the following screenshot:
|
||||
|
||||
![New Row in File](pathname:///gatsby/pres2.png)
|
||||
|
||||
Save the file and notice that the table has refreshed with the new data:
|
||||
Save the file and observe 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:
|
||||
11) Stop the development server and build the site:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The build output will confirm that the `/pres` route is static:
|
||||
|
||||
```text title="Output from GatsbyJS build process"
|
||||
Pages
|
||||
|
||||
┌ src/pages/404.js
|
||||
@ -398,7 +405,7 @@ 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"
|
||||
```html title="public/pres/index.html (Expected contents)"
|
||||
<tr><td>SheetJS Dev</td><td>47</td></tr>
|
||||
```
|
||||
|
@ -135,7 +135,7 @@ recover the Date objects in the generated code module.
|
||||
|
||||
:::
|
||||
|
||||
```js
|
||||
```js title="build.mjs (plugin implementation)"
|
||||
import * as XLSX from 'xlsx';
|
||||
import * as fs from 'fs';
|
||||
XLSX.set_fs(fs);
|
||||
@ -198,9 +198,9 @@ document.body.appendChild(elt);
|
||||
|
||||
## Demo
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 21 against ESBuild 0.19.5
|
||||
This demo was last tested on 2023 December 04 against ESBuild 0.19.8
|
||||
|
||||
:::
|
||||
|
||||
@ -212,7 +212,7 @@ This demo was last tested on 2023 October 21 against ESBuild 0.19.5
|
||||
mkdir sheetjs-esb
|
||||
cd sheetjs-esb
|
||||
npm init -y
|
||||
npm i --save esbuild@0.19.5
|
||||
npm i --save esbuild@0.19.8
|
||||
```
|
||||
|
||||
1) Install the SheetJS NodeJS module:
|
||||
@ -249,58 +249,13 @@ elt.innerHTML = "<table><tr><th>Name</th><th>Index</th></tr>" +
|
||||
document.body.appendChild(elt);
|
||||
```
|
||||
|
||||
4) Save the following to `build.mjs`:
|
||||
4) Download [`build.mjs`](pathname:///esbuild/build.mjs) to the project folder:
|
||||
|
||||
```js title="build.mjs"
|
||||
import * as esbuild from 'esbuild'
|
||||
import * as XLSX from 'xlsx';
|
||||
import * as fs from 'fs';
|
||||
XLSX.set_fs(fs);
|
||||
|
||||
let sheetjsPlugin = {
|
||||
name: 'sheetjs',
|
||||
setup(build) {
|
||||
/* match NUMBERS, XLSX, XLS, and XLSB files */
|
||||
const EXTS = /.(numbers|xlsx|xls|xlsb)$/;
|
||||
|
||||
/* this method will be called once for each referenced file */
|
||||
build.onLoad({ filter: EXTS }, (args) => {
|
||||
/* parse file from filesystem */
|
||||
const wb = XLSX.readFile(args.path);
|
||||
/* get first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
|
||||
/* workaround for JSON limitation */
|
||||
Date.prototype.toJSON2 = Date.prototype.toJSON;
|
||||
Date.prototype.toJSON = function() { return {d:this.toISOString()}; };
|
||||
|
||||
/* generate row objects */
|
||||
const data = XLSX.utils.sheet_to_json(ws);
|
||||
|
||||
/* generate final module code */
|
||||
const res = JSON.stringify(data);
|
||||
Date.prototype.toJSON = Date.prototype.toJSON2;
|
||||
const contents = `const data = ${res};
|
||||
data.forEach(row => {
|
||||
Object.keys(row).forEach(k => {
|
||||
if(row[k]?.d) row[k] = new Date(row[k].d);
|
||||
})
|
||||
});
|
||||
export default data;`
|
||||
return { contents, loader: 'js' };
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
await esbuild.build({
|
||||
entryPoints: ['app.js'],
|
||||
bundle: true,
|
||||
outfile: 'out.js',
|
||||
plugins: [sheetjsPlugin],
|
||||
});
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/esbuild/build.mjs
|
||||
```
|
||||
|
||||
5) Download <https://sheetjs.com/pres.numbers> and save to the project folder:
|
||||
5) Download <https://sheetjs.com/pres.numbers> to the project folder:
|
||||
|
||||
```bash
|
||||
curl -LO https://sheetjs.com/pres.numbers
|
||||
@ -333,7 +288,7 @@ president names. It will not include SheetJS library references!
|
||||
|
||||
In the last test, the generated source looked like the following snippet
|
||||
|
||||
```js title="out.js"
|
||||
```js title="out.js (Expected output)"
|
||||
(() => {
|
||||
// pres.numbers
|
||||
var data = [{ "Name": "Bill Clinton", "Index": 42 }, /* ... more data */];
|
@ -187,9 +187,16 @@ document.querySelector('#app').innerHTML = `<table>
|
||||
|
||||
## Complete Demo
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested on 2023 September 07 with ViteJS version `4.4.9`.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| ViteJS | Date |
|
||||
|:---------|:-----------|
|
||||
| `5.0.5` | 2023-12-04 |
|
||||
| `4.5.0` | 2023-12-04 |
|
||||
| `3.2.7` | 2023-12-04 |
|
||||
| `2.9.16` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -200,8 +207,15 @@ A Git repository with the completed site can be cloned[^7].
|
||||
|
||||
1) Create a new site with the `vue-ts` template and install the SheetJS package:
|
||||
|
||||
:::note pass
|
||||
|
||||
To force an older major version of ViteJS, change the `vite@5` to the desired
|
||||
major version. For example, `npm create vite@3` will use ViteJS major version 3.
|
||||
|
||||
:::
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm create vite@latest sheetjs-vite -- --template vue-ts
|
||||
npm create vite@5 sheetjs-vite -- --template vue-ts
|
||||
cd sheetjs-vite
|
||||
npm i
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
@ -157,9 +157,9 @@ document.body.appendChild(elt);
|
||||
|
||||
## Webpack 5 Demo
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 10 against Webpack 5.88.2
|
||||
This demo was last tested on 2023 December 04 against Webpack 5.89.0
|
||||
|
||||
:::
|
||||
|
||||
@ -171,7 +171,7 @@ This demo was last tested on 2023 October 10 against Webpack 5.88.2
|
||||
mkdir sheetjs-wp5
|
||||
cd sheetjs-wp5
|
||||
npm init -y
|
||||
npm install webpack@5.88.2 webpack-cli@5.1.4 webpack-dev-server@4.15.1 --save
|
||||
npm install webpack@5.89.0 webpack-cli@5.1.4 webpack-dev-server@4.15.1 --save
|
||||
mkdir -p dist
|
||||
mkdir -p src
|
||||
mkdir -p data
|
@ -5,6 +5,8 @@ pagination_next: demos/mobile/index
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[Eleventy](https://www.11ty.dev/docs) is a telemetry-free static site generator.
|
||||
@ -93,7 +95,7 @@ For example, [`pres.numbers`](https://sheetjs.com/pres.numbers) can be accessed
|
||||
using the variable `pres` in a template:
|
||||
|
||||
```liquid title="index.njk"
|
||||
<table><thead><th>Name</th><th>Index</th></thead>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in pres %}
|
||||
<tr>
|
||||
@ -108,9 +110,17 @@ using the variable `pres` in a template:
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested on 2023 October 08 using Eleventy `2.0.1`
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Eleventy | Date |
|
||||
|:----------------|:-----------|
|
||||
| `2.0.1` | 2023-10-08 |
|
||||
| `3.0.0-alpha.1` | 2023-12-04 |
|
||||
|
||||
At the time of writing, the `3.0.0-alpha.1` ("Alpha") release was only available
|
||||
through the Git repository. Steps for `2.0.1` ("Stable") and Alpha are included.
|
||||
|
||||
:::
|
||||
|
||||
@ -126,10 +136,23 @@ npm init -y
|
||||
|
||||
2) Install Eleventy and SheetJS libraries:
|
||||
|
||||
<Tabs groupId="11ty">
|
||||
<TabItem value="2" label="Stable">
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @11ty/eleventy`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="3" label="Alpha">
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz 11ty/eleventy`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
3) Make a new `_data` subdirectory in the project. Download the example file
|
||||
[`pres.xlsx`](https://sheetjs.com/pres.xlsx) into `_data`:
|
||||
|
@ -36,13 +36,13 @@ time and how to read files on the server in NextJS lifecycle methods.
|
||||
NextJS collects telemetry by default. The `telemetry` subcommand can disable it:
|
||||
|
||||
```js
|
||||
npx next@13.4.19 telemetry disable
|
||||
npx next@13.5.6 telemetry disable
|
||||
```
|
||||
|
||||
The setting can be verified by running
|
||||
|
||||
```js
|
||||
npx next@13.4.19 telemetry status
|
||||
npx next@13.5.6 telemetry status
|
||||
```
|
||||
|
||||
:::
|
||||
@ -61,17 +61,18 @@ module.exports = {
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
The following deployments were tested:
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| NextJS | NodeJS | Date |
|
||||
|:----------|:----------|:-----------|
|
||||
| ` 9.5.5` | `16.20.2` | 2023-08-20 |
|
||||
| `10.2.3` | `16.20.2` | 2023-08-20 |
|
||||
| `11.1.4` | `16.20.2` | 2023-08-20 |
|
||||
| `12.3.4` | `18.17.1` | 2023-08-20 |
|
||||
| `13.4.19` | `18.17.1` | 2023-08-20 |
|
||||
| ` 9.5.5` | `16.20.2` | 2023-12-04 |
|
||||
| `10.2.3` | `16.20.2` | 2023-12-04 |
|
||||
| `11.1.4` | `16.20.2` | 2023-12-04 |
|
||||
| `12.3.4` | `20.10.0` | 2023-12-04 |
|
||||
| `13.5.6` | `20.10.0` | 2023-12-04 |
|
||||
| `14.0.3` | `20.10.0` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -189,9 +190,9 @@ imported from page scripts.
|
||||
|
||||
:::warning pass
|
||||
|
||||
[`import`](/docs/getting-started/installation/nodejs#esm-import) does not load
|
||||
NodeJS native modules. The Installation section includes a note on dynamic
|
||||
import of `fs` within lifecycle methods.
|
||||
[The SheetJS ESM build](/docs/getting-started/installation/nodejs#esm-import)
|
||||
does not load NodeJS native modules directly. The Installation section includes
|
||||
a note on dynamic import of `fs` within lifecycle methods.
|
||||
|
||||
:::
|
||||
|
||||
@ -522,7 +523,7 @@ This demo showcases the following SheetJS + NextJS flows:
|
||||
| `/sheets/[id]` | asset module | `getStaticPaths` | `sheet_to_html` |
|
||||
| `/getServerSideProps` | lifecycle | `getServerSideProps` | `sheet_to_html` |
|
||||
|
||||
The commands in this demo use `next@13.4.19`. Other versions were tested by
|
||||
The commands in this demo use `next@13.5.6`. Other versions were tested by
|
||||
replacing the version number in the relevant commands.
|
||||
|
||||
:::
|
||||
@ -545,13 +546,13 @@ When upgrading NextJS is not an option, NodeJS should be downgraded to v16.
|
||||
0) Disable NextJS telemetry:
|
||||
|
||||
```js
|
||||
npx next@13.4.19 telemetry disable
|
||||
npx next@13.5.6 telemetry disable
|
||||
```
|
||||
|
||||
Confirm it is disabled by running
|
||||
|
||||
```js
|
||||
npx next@13.4.19 telemetry status
|
||||
npx next@13.5.6 telemetry status
|
||||
```
|
||||
|
||||
1) Set up folder structure. At the end, a `pages` folder with a `sheets`
|
||||
@ -572,8 +573,19 @@ curl -LO https://docs.sheetjs.com/next/sheetjs.xlsx
|
||||
|
||||
3) Install dependencies:
|
||||
|
||||
:::note pass
|
||||
|
||||
The `next@13.5.6` dependency can be adjusted to pick a different version. For
|
||||
example, NextJS `12.3.4` is installed with
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz next@13.4.19`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz next@12.3.4`}
|
||||
</CodeBlock>
|
||||
|
||||
:::
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz next@13.5.6`}
|
||||
</CodeBlock>
|
||||
|
||||
4) Download NextJS config scripts and place in the root folder:
|
||||
@ -631,7 +643,7 @@ cd ../..
|
||||
6) Test the deployment:
|
||||
|
||||
```bash
|
||||
npx next@13.4.19
|
||||
npx next
|
||||
```
|
||||
|
||||
Open a web browser and access:
|
||||
@ -648,7 +660,7 @@ The individual worksheets are available at
|
||||
|
||||
7) While the development server is running, open the `/getStaticProps` page and
|
||||
open `sheetjs.xlsx` with a spreadsheet editor. In the editor, add a row to the
|
||||
bottom of the "Indices" worksheet.
|
||||
bottom of the "Indices" worksheet (set `A7` to "SheetJS Dev" and `B7` to `47`)
|
||||
|
||||
After saving the file, the website should refresh with the new row.
|
||||
|
||||
@ -657,7 +669,7 @@ After saving the file, the website should refresh with the new row.
|
||||
8) Stop the server and run a production build:
|
||||
|
||||
```bash
|
||||
npx next@13.4.19 build
|
||||
npx next build
|
||||
```
|
||||
|
||||
The final output will show a list of the routes and types:
|
||||
@ -681,24 +693,71 @@ worksheets in the file. `/getServerSideProps` is server-rendered.
|
||||
|
||||
9) Try to build a static site:
|
||||
|
||||
<Tabs groupId="nextver">
|
||||
<TabItem value="13" label="NextJS 9 - 13">
|
||||
|
||||
```bash
|
||||
npx next@13.4.19 export
|
||||
npx next export
|
||||
```
|
||||
|
||||
:::note The static export will fail!
|
||||
</TabItem>
|
||||
<TabItem value="14" label="NextJS 14">
|
||||
|
||||
A static page cannot be generated at this point because `/getServerSideProps`
|
||||
is still server-rendered.
|
||||
:::warning NextJS breaking changes
|
||||
|
||||
**NextJS 14 removed the `export` subcommand!**
|
||||
|
||||
:::
|
||||
|
||||
|
||||
Edit `next.config.js` and add the highlighted line:
|
||||
|
||||
```js title="next.config.js (add highlighted line)"
|
||||
module.exports = {
|
||||
// highlight-next-line
|
||||
output: "export",
|
||||
webpack: (config) => {
|
||||
```
|
||||
|
||||
After adding the line, run the `build` command:
|
||||
|
||||
```bash
|
||||
npx next build
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This build will fail. A static page cannot be generated at this point because
|
||||
`/getServerSideProps` is server-rendered.
|
||||
|
||||
### Static Site
|
||||
|
||||
10) Delete `pages/getServerSideProps.js` and rebuild:
|
||||
|
||||
<Tabs groupId="nextver">
|
||||
<TabItem value="13" label="NextJS 9 - 13">
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="14" label="NextJS 14">
|
||||
|
||||
Edit `next.config.js` and comment the highlighted line:
|
||||
|
||||
```js title="next.config.js (comment highlighted line)"
|
||||
module.exports = {
|
||||
// highlight-next-line
|
||||
// output: "export",
|
||||
webpack: (config) => {
|
||||
```
|
||||
|
||||
After editing `next.config.js`:
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
```bash
|
||||
rm -f pages/getServerSideProps.js
|
||||
npx next@13.4.19 build
|
||||
npx next build
|
||||
```
|
||||
|
||||
Inspecting the output, there should be no lines with the `λ` symbol:
|
||||
@ -717,10 +776,34 @@ Route (pages) Size First Load JS
|
||||
|
||||
11) Generate the static site:
|
||||
|
||||
<Tabs groupId="nextver">
|
||||
<TabItem value="13" label="NextJS 9 - 13">
|
||||
|
||||
```bash
|
||||
npx next@13.4.19 export
|
||||
npx next export
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="14" label="NextJS 14">
|
||||
|
||||
Edit `next.config.js` and restore the highlighted line:
|
||||
|
||||
```js title="next.config.js (restore highlighted line)"
|
||||
module.exports = {
|
||||
// highlight-next-line
|
||||
output: "export",
|
||||
webpack: (config) => {
|
||||
```
|
||||
|
||||
After adding the line, run the `build` command:
|
||||
|
||||
```bash
|
||||
npx next build
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The static site will be written to the `out` subfolder
|
||||
|
||||
12) Serve the static site:
|
@ -7,6 +7,8 @@ pagination_next: demos/mobile/index
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[Nuxt Content](https://content.nuxtjs.org/) is a file-based CMS for NuxtJS,
|
||||
@ -40,28 +42,65 @@ that process spreadsheets in the browser.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
The following deployments were tested:
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Nuxt Content | Nuxt | Date |
|
||||
|:-------------|:---------|:-----------|
|
||||
| `1.15.1` | `2.17.1` | 2023-08-16 |
|
||||
| `2.7.2` | `3.6.5` | 2023-08-16 |
|
||||
| `1.15.1` | `2.17.2` | 2023-12-04 |
|
||||
| `2.9.0` | `3.8.2` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
:::caution Telemetry
|
||||
:::warning Telemetry
|
||||
|
||||
Nuxt embeds telemetry. According to the developers, it is disabled by default.
|
||||
To explicitly disable telemetry, the official documentation recommends:
|
||||
Nuxt embeds telemetry. According to the docs, it can be disabled with:
|
||||
|
||||
```bash
|
||||
npx nuxt telemetry disable
|
||||
```
|
||||
|
||||
At the time the demo was last tested, this command did not work. Instead, a
|
||||
option should be added in `nuxt.config.ts` or `nuxt.config.js` for Nuxt 3 sites:
|
||||
**At the time the demo was last tested, this command did not work.**
|
||||
|
||||
Disabling telemetry requires a few steps:
|
||||
|
||||
1) Set the environment variable `NUXT_TELEMETRY_DISABLED` to `1`
|
||||
|
||||
<Tabs groupId="os">
|
||||
<TabItem value="unix" label="Linux/MacOS">
|
||||
|
||||
Add the following line to `.profile`, `.bashrc` and `.zshrc`:
|
||||
|
||||
```bash
|
||||
export NUXT_TELEMETRY_DISABLED=1
|
||||
```
|
||||
|
||||
Close and restart the Terminal to load the changes.
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win" label="Windows">
|
||||
|
||||
Type `env` in the search bar and select "Edit the system environment variables".
|
||||
|
||||
In the new window, click the "Environment Variables..." button.
|
||||
|
||||
In the new window, look for the "System variables" section and click "New..."
|
||||
|
||||
Set the "Variable name" to `NUXT_TELEMETRY_DISABLED` and the value to `1`.
|
||||
|
||||
Click "OK" in each window (3 windows) and restart your computer.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
2) A global setting should be added to `.nuxtrc` in the user home directory:
|
||||
|
||||
```ini title="~/.nuxtrc"
|
||||
telemetry.enabled=false
|
||||
```
|
||||
|
||||
3) For Nuxt 3 sites, set the `telemetry` option in the Nuxt config file (either `nuxt.config.ts` or `nuxt.config.js`):
|
||||
|
||||
```js title="nuxt.config.js"
|
||||
// ...
|
||||
@ -74,12 +113,6 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
A global setting can be added to `.nuxtrc` in the user home directory:
|
||||
|
||||
```ini title=".nuxtrc"
|
||||
telemetry.enabled=false
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Nuxt Content v1
|
||||
@ -342,7 +375,9 @@ not, click Refresh manually or open a new browser window.
|
||||
![Nuxt Demo end of step 5](pathname:///nuxt/nuxt5.png)
|
||||
|
||||
6) To verify that live reload works, open `pres.xlsx` from the `content` folder
|
||||
in Excel. Add a new row to the bottom and save the file:
|
||||
with Excel or another spreadsheet editor.
|
||||
|
||||
Set cell `A7` to "SheetJS Dev" and set `B7` to `47`. Save the spreadsheet.
|
||||
|
||||
![Adding a new line to `pres.xlsx`](pathname:///nuxt/nuxl6.png)
|
||||
|
||||
@ -595,17 +630,23 @@ curl -O https://docs.sheetjs.com/nuxt/3/sheetmodule.ts
|
||||
|
||||
After creating the source files, the module must be added to `nuxt.config.ts`:
|
||||
|
||||
```ts title="nuxt.config.ts"
|
||||
```ts title="nuxt.config.ts (add highlighted lines)"
|
||||
// highlight-next-line
|
||||
import SheetJSModule from './sheetmodule'
|
||||
|
||||
export default defineNuxtConfig({
|
||||
// highlight-start
|
||||
// @ts-ignore
|
||||
telemetry: false,
|
||||
// highlight-end
|
||||
devtools: { enabled: true },
|
||||
// highlight-start
|
||||
modules: [
|
||||
SheetJSModule,
|
||||
'@nuxt/content'
|
||||
],
|
||||
content: {}
|
||||
// highlight-end
|
||||
});
|
||||
```
|
||||
|
||||
@ -613,6 +654,7 @@ Restart the dev server by exiting the process (Control+C) and running:
|
||||
|
||||
```bash
|
||||
npx -y nuxi clean
|
||||
npx -y nuxi cleanup
|
||||
npx -y nuxi typecheck
|
||||
npx -y yarn run dev
|
||||
```
|
||||
@ -645,13 +687,16 @@ Restart the dev server by exiting the process (Control+C) and running:
|
||||
|
||||
```bash
|
||||
npx -y nuxi clean
|
||||
npx -y nuxi cleanup
|
||||
npx -y yarn run dev
|
||||
```
|
||||
|
||||
The browser should now display an HTML table.
|
||||
|
||||
6) To verify that hot loading works, open `pres.xlsx` from the `content` folder
|
||||
in Excel. Add a new row to the bottom and save the file.
|
||||
with Excel or another spreadsheet editor.
|
||||
|
||||
Set cell `A7` to "SheetJS Dev" and set `B7` to `47`. Save the spreadsheet.
|
||||
|
||||
The page should automatically refresh with the new content.
|
||||
|
@ -45,9 +45,14 @@ flowchart LR
|
||||
aoo --> |+page.svelte\ncomponent| html
|
||||
```
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested on 2023 October 24 using SvelteKit `1.27.0` and Svelte `4.2.2`
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Svelte | Kit | Date |
|
||||
|:----------------|:---------|:-----------|
|
||||
| `4.2.8` | `1.27.6` | 2023-12-04 |
|
||||
| `5.0.0-next.17` | `1.27.6` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -160,7 +165,7 @@ Using standard Svelte patterns, HTML tables can be generated from the data:
|
||||
</script>
|
||||
|
||||
<h1>Presidents</h1>
|
||||
<table><thead><th>Name</th><th>Index</th></thead><tbody>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
|
||||
{#each pres as p}<tr>
|
||||
<td>{p.Name}</td>
|
||||
<td>{p.Index}</td>
|
||||
@ -187,6 +192,12 @@ When prompted:
|
||||
- `Add type checking with TypeScript?` select `Yes, using JavaScript with JSDoc`
|
||||
- `Select additional options` press Enter (do not select options)
|
||||
|
||||
:::note pass
|
||||
|
||||
To test the Svelte 5 beta, select "Try out Svelte 5 beta" before pressing Enter.
|
||||
|
||||
:::
|
||||
|
||||
2) Enter the project folder and install dependencies:
|
||||
|
||||
```bash
|
||||
@ -208,18 +219,75 @@ curl -Lo data/pres.xlsx https://sheetjs.com/pres.xlsx
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
</CodeBlock>
|
||||
|
||||
5) Replace the contents of `vite.config.js` with the contents of the code block
|
||||
named [`vite.config.js` in the "Loader" section](#loader)
|
||||
5) Replace the contents of `vite.config.js` with the following:
|
||||
|
||||
6) Append the lines from [`src/app.d.ts` snippet in the "Types" section](#types)
|
||||
to the `src/app.d.ts` file.
|
||||
```js title="vite.config.js"
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
export default defineConfig({
|
||||
assetsInclude: ['**/*.numbers', '**/*.xlsx'],
|
||||
plugins: [sveltekit(), {
|
||||
name: "sheet-base64",
|
||||
transform(code, id) {
|
||||
if(!id.match(/\.(numbers|xlsx)$/)) return;
|
||||
var data = readFileSync(id, "base64");
|
||||
return `export default '${data}'`;
|
||||
}
|
||||
}]
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
6) Append the following lines to `src/app.d.ts`:
|
||||
|
||||
```ts title="src/app.d.ts (add to end of file)"
|
||||
declare global {
|
||||
declare module '*.numbers' { const data: string; export default data; }
|
||||
declare module '*.xlsx' { const data: string; export default data; }
|
||||
}
|
||||
```
|
||||
|
||||
7) Replace the contents of `src/routes/+page.server.js` with following:
|
||||
|
||||
```js title="src/routes/+page.server.js"
|
||||
import b64 from "../../data/pres.xlsx";
|
||||
import { read, utils } from "xlsx";
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
/** @type {import('./$types').PageServerLoad} */
|
||||
export async function load({ params }) {
|
||||
const wb = read(b64);
|
||||
/** @type {[string, any[]][]} */
|
||||
const data = wb.SheetNames.map(n => [n, utils.sheet_to_json(wb.Sheets[n])]);
|
||||
return Object.fromEntries(data);
|
||||
}
|
||||
```
|
||||
|
||||
7) Replace the contents of `src/routes/+page.server.ts` with the contents of the
|
||||
code block named [`src/routes/+page.server.ts` in "Data Processing"](#data-processing).
|
||||
If the file does not exist, create a new file.
|
||||
|
||||
8) Replace the contents of `src/routes/+page.svelte` with the contents of the
|
||||
code block named [`src/routes/+page.svelte` in "Data Rendering"](#data-rendering)
|
||||
8) Replace the contents of `src/routes/+page.svelte` with the following:
|
||||
|
||||
```html title="src/routes/+page.svelte"
|
||||
<script>
|
||||
/** @type {import('./$types').PageData} */
|
||||
export let data;
|
||||
|
||||
/* `pres` will be the data from Sheet1 */
|
||||
/** @type {Array<{Name: string, Index: number}>}*/
|
||||
export let pres = data["Sheet1"];
|
||||
</script>
|
||||
|
||||
<h1>Presidents</h1>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
|
||||
{#each pres as p}<tr>
|
||||
<td>{p.Name}</td>
|
||||
<td>{p.Index}</td>
|
||||
</tr>{/each}
|
||||
</tbody></table>
|
||||
```
|
||||
|
||||
### Live Reload
|
||||
|
||||
@ -245,11 +313,18 @@ the file. After saving, the browser should automatically refresh with new data.
|
||||
npm i --save @sveltejs/adapter-static
|
||||
```
|
||||
|
||||
13) Edit `svelte.config.js` to use the new adapter:
|
||||
13) Edit `svelte.config.js` to use the new adapter.
|
||||
|
||||
```diff title="svelte.config.js (diff)"
|
||||
-import adapter from '@sveltejs/adapter-auto';
|
||||
+import adapter from '@sveltejs/adapter-static';
|
||||
The config should currently use `adapter-auto`:
|
||||
|
||||
```js title="svelte.config.js (default configuration)"
|
||||
import adapter from '@sveltejs/adapter-auto';
|
||||
```
|
||||
|
||||
Replace the module name with `@sveltejs/adapter-static`:
|
||||
|
||||
```js title="svelte.config.js (change dependency)"
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
```
|
||||
|
||||
14) Build the static site:
|
||||
@ -270,7 +345,7 @@ View the page source and confirm that the raw HTML table includes the data.
|
||||
Searching for `Bill Clinton` should reveal the following row:
|
||||
|
||||
```html
|
||||
<tr><td>Bill Clinton</td> <td>42</td> </tr>
|
||||
<tr><td>Bill Clinton</td><td>42</td></tr>
|
||||
```
|
||||
|
||||
[^1]: See ["SvelteKit vs Svelte"](https://kit.svelte.dev/docs/introduction#sveltekit-vs-svelte) in the SvelteKit documentation.
|
@ -46,9 +46,22 @@ npx astro telemetry disable
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 24 using AstroJS `v3.3.4`
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| AstroJS | Date |
|
||||
|:---------------|:-----------|
|
||||
| `3.6.4` | 2023-12-04 |
|
||||
| `4.0.0-beta.4` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
AstroJS has introduced a number of breaking changes in minor releases.
|
||||
|
||||
**The demos worked as expected with the listed versions on the listed dates.**
|
||||
|
||||
:::
|
||||
|
||||
@ -197,6 +210,22 @@ npm create astro@latest -- --template starlight --yes ./sheetjs-astro
|
||||
cd sheetjs-astro
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
To test the AstroJS 4 beta release, run the following command:
|
||||
|
||||
```bash
|
||||
npm install --force @astrojs/starlight@^0.14.0 astro@4.0.0-beta.4
|
||||
```
|
||||
|
||||
The version can be verified by running:
|
||||
|
||||
```bash
|
||||
npx astro --version
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
2) Fetch the example file [`pres.numbers`](https://sheetjs.com/pres.numbers):
|
||||
|
||||
```bash
|
||||
@ -268,6 +297,18 @@ curl -o src/pages/index.astro https://docs.sheetjs.com/astrojs/index.astro
|
||||
rm src/content/index.*
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
This command may show an error:
|
||||
|
||||
```
|
||||
zsh: no matches found: src/content/index.*
|
||||
```
|
||||
|
||||
This error can be ignored.
|
||||
|
||||
:::
|
||||
|
||||
8) Build the static site:
|
||||
|
||||
```bash
|
||||
@ -292,8 +333,8 @@ contains the content from the file in an HTML table.
|
||||
|
||||
When this demo was first written, the `docs` template used `src/pages/index.astro`
|
||||
|
||||
During the most recent test, AstroJS removed the `docs` template and introduced
|
||||
the `starlight` template. This template included `src/content/index.mdx`, which
|
||||
In a later test, AstroJS removed the `docs` template and introduced the
|
||||
`starlight` template. This template included `src/content/index.mdx`, which
|
||||
takes priority over `src/pages/index.astro`.
|
||||
|
||||
To resolve this issue, as noted in step 7, remove any `index.*` files in the
|
@ -215,11 +215,14 @@ const wb = XLSX.read(ab);
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
The Android demo was last tested on 2023 December 01 with RN `0.72.7`. The
|
||||
simulator used Android 13 ("Tiramisu") API 33 on a Pixel 3.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
The iOS demo was last tested on 2023 December 01 with RN `0.72.7`. The
|
||||
simulator used iOS 17.0.1 on an iPhone SE (3rd generation).
|
||||
| OS | Type | Device | RN | Date |
|
||||
|:-----------|:-----|:--------------------|:---------|:-----------|
|
||||
| Android 34 | Sim | Pixel 3a | `0.72.7` | 2023-12-04 |
|
||||
| iOS 17.0.1 | Sim | iPhone 15 Pro Max | `0.72.7` | 2023-12-04 |
|
||||
| Android 29 | Real | NVIDIA Shield | `0.72.7` | 2023-12-04 |
|
||||
| iOS 15.1 | Real | iPad Pro | `0.72.7` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -328,6 +331,38 @@ tapping "Import data from a spreadsheet", verify that the app shows new data:
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
**Android Device Testing**
|
||||
|
||||
10) Connect an Android device using a USB cable.
|
||||
|
||||
If the device asks to allow USB debugging, tap "Allow".
|
||||
|
||||
11) Close any Android / iOS emulators.
|
||||
|
||||
12) Build APK and run on device:
|
||||
|
||||
```bash
|
||||
npx react-native run-android
|
||||
```
|
||||
|
||||
**iOS Device Testing**
|
||||
|
||||
13) Close any Android / iOS emulators.
|
||||
|
||||
14) Enable developer code signing certificates[^7]
|
||||
|
||||
15) Install `ios-deploy` through Homebrew:
|
||||
|
||||
```bash
|
||||
brew install ios-deploy
|
||||
```
|
||||
|
||||
16) Run on device:
|
||||
|
||||
```bash
|
||||
npx react-native run-ios
|
||||
```
|
||||
|
||||
## Local Files
|
||||
|
||||
:::warning pass
|
||||
@ -364,7 +399,7 @@ The following libraries have been tested:
|
||||
|
||||
#### `react-native-document-picker`
|
||||
|
||||
<details open><summary><b>Selecting a file</b> (click to show)</summary>
|
||||
<details open><summary><b>Selecting a file</b> (click to hide)</summary>
|
||||
|
||||
The setting `copyTo: "cachesDirectory"` must be set:
|
||||
|
||||
@ -425,7 +460,7 @@ for the purposes of working with files.
|
||||
The `ascii` type returns an array of numbers corresponding to the raw bytes.
|
||||
A `Uint8Array` from the data is compatible with the `buffer` type.
|
||||
|
||||
<details open><summary><b>Reading and Writing snippets</b> (click to show)</summary>
|
||||
<details open><summary><b>Reading and Writing snippets</b> (click to hide)</summary>
|
||||
|
||||
The snippets use `rn-fetch-blob`. To use `react-native-blob-util`, change the
|
||||
`import` statements to load the module.
|
||||
@ -487,7 +522,7 @@ const res = await writeFile(file, Array.from(wbout), 'ascii');
|
||||
|
||||
The `base64` encoding returns strings compatible with the `base64` type:
|
||||
|
||||
<details open><summary><b>Reading and Writing snippets</b> (click to show)</summary>
|
||||
<details open><summary><b>Reading and Writing snippets</b> (click to hide)</summary>
|
||||
|
||||
_Reading Data_
|
||||
|
||||
@ -518,7 +553,7 @@ await FileSystem.writeFile(DDP + "sheetjs.xlsx", b64, "base64");
|
||||
|
||||
The `ascii` encoding returns binary strings compatible with the `binary` type:
|
||||
|
||||
<details open><summary><b>Reading and Writing snippets</b> (click to show)</summary>
|
||||
<details open><summary><b>Reading and Writing snippets</b> (click to hide)</summary>
|
||||
|
||||
_Reading Data_
|
||||
|
||||
@ -605,7 +640,7 @@ simulator used iOS 17.0 on an iPhone 15 Pro Max.
|
||||
|
||||
There are many moving parts and pitfalls with React Native apps. It is strongly
|
||||
recommended to follow the official React Native tutorials for iOS and Android
|
||||
before approaching this demo.[^7] Details including Android Virtual Device
|
||||
before approaching this demo.[^8] Details including Android Virtual Device
|
||||
configuration are not covered here.
|
||||
|
||||
:::
|
||||
@ -953,4 +988,5 @@ npx xlsx-cli /tmp/sheetjsw.xlsx
|
||||
[^4]: See ["Array of Arrays Input" in "Utility Functions"](/docs/api/utilities/array#array-of-arrays-input)
|
||||
[^5]: React-Native commit [`5b597b5`](https://github.com/facebook/react-native/commit/5b597b5ff94953accc635ed3090186baeecb3873) added the final piece required for `fetch` support. It landed in version `0.72.0-rc.1` and is available in official releases starting from `0.72.0`.
|
||||
[^6]: When the demo was last tested, the Zulu11 distribution of Java 11 was installed through the macOS Brew package manager. [Direct downloads are available at `azul.com`](https://www.azul.com/downloads/?version=java-11-lts&package=jdk#zulu)
|
||||
[^7]: Follow the ["React Native CLI Quickstart"](https://reactnative.dev/docs/environment-setup) for Android (and iOS, if applicable)
|
||||
[^7]: See ["Running On Device"](https://reactnative.dev/docs/running-on-device) in the React Native documentation
|
||||
[^8]: Follow the ["React Native CLI Quickstart"](https://reactnative.dev/docs/environment-setup) for Android (and iOS, if applicable)
|
76
docz/docs/03-demos/05-mobile/02-nativescript.md → docz/docs/03-demos/17-mobile/02-nativescript.md
76
docz/docs/03-demos/05-mobile/02-nativescript.md → docz/docs/03-demos/17-mobile/02-nativescript.md
@ -47,11 +47,24 @@ Angular and TypeScript is assumed.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS | Type | Device | NS | Date |
|
||||
|:-----------|:-----|:--------------------|:---------|:-----------|
|
||||
| Android 34 | Sim | Pixel 3a | `8.6.1` | 2023-12-04 |
|
||||
| iOS 17.0.1 | Sim | iPhone SE (3rd gen) | `8.6.1` | 2023-12-04 |
|
||||
| Android 29 | Real | NVIDIA Shield | `8.6.1` | 2023-12-04 |
|
||||
| iOS 15.1 | Real | iPad Pro | `8.6.1` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
:::warning Telemetry
|
||||
|
||||
Before starting this demo, manually disable telemetry.
|
||||
|
||||
NativeScript 8.6.0 split the telemetry into two parts: "usage" and "error". Both
|
||||
NativeScript 8.6.1 split the telemetry into two parts: "usage" and "error". Both
|
||||
must be disabled separately:
|
||||
|
||||
```bash
|
||||
@ -174,19 +187,6 @@ const wb = read(ab);
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note
|
||||
|
||||
The project was last tested on 2023 October 12. NativeScript version
|
||||
(as verified with `npx -p nativescript ns --version`) was `8.6.0`.
|
||||
|
||||
The iOS demo was last tested on 2023-10-12 with `@nativescript/ios`
|
||||
version `8.6.1` on an emulated iPhone 15 Pro Max + iOS 17.0
|
||||
|
||||
The Android demo was last tested on 2023-10-12 with `@nativescript/android`
|
||||
version `8.6.2` on an emulated Pixel 3 + Android 13 ("Tiramisu") API 33.
|
||||
|
||||
:::
|
||||
|
||||
### Platform Configuration
|
||||
|
||||
0) Disable telemetry:
|
||||
@ -239,7 +239,7 @@ In the last macOS test, the following output was displayed:
|
||||
<span {...g}>✔</span> Javac is installed and is configured properly.{'\n'}
|
||||
<span {...g}>✔</span> The Java Development Kit (JDK) is installed and is configured properly.{'\n'}
|
||||
<span {...g}>✔</span> Getting NativeScript components versions information...{'\n'}
|
||||
<span {...g}>✔</span> Component nativescript has 8.6.0 version and is up to date.
|
||||
<span {...g}>✔</span> Component nativescript has 8.6.1 version and is up to date.
|
||||
</pre>
|
||||
|
||||
</details>
|
||||
@ -266,9 +266,9 @@ No issues were detected.{'\n'}
|
||||
<span {...g}>✔</span> Your current CocoaPods version is newer than 1.0.0.{'\n'}
|
||||
<span {...g}>✔</span> Python installed and configured correctly.{'\n'}
|
||||
<span {...g}>✔</span> The Python 'six' package is found.{'\n'}
|
||||
<span {...g}>✔</span> Xcode version 15.0.0 satisfies minimum required version 10.{'\n'}
|
||||
<span {...g}>✔</span> Xcode version 15.0.1 satisfies minimum required version 10.{'\n'}
|
||||
<span {...g}>✔</span> Getting NativeScript components versions information...{'\n'}
|
||||
<span {...g}>✔</span> Component nativescript has 8.6.0 version and is up to date.
|
||||
<span {...g}>✔</span> Component nativescript has 8.6.1 version and is up to date.
|
||||
</pre>
|
||||
|
||||
</details>
|
||||
@ -293,6 +293,14 @@ npx -p nativescript ns run android
|
||||
Once the simulator launches and the test app is displayed, end the script by
|
||||
selecting the terminal and entering the key sequence `CTRL + C`
|
||||
|
||||
:::note pass
|
||||
|
||||
If the emulator is not running, `nativescript` may fail with the message:
|
||||
|
||||
```
|
||||
Emulator start failed with: No emulator image available for device identifier 'undefined'.
|
||||
```
|
||||
|
||||
6) From the project folder, install the library:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
@ -603,6 +611,37 @@ npx -p nativescript ns run android
|
||||
|
||||
The app should show Presidential data.
|
||||
|
||||
### Android Device
|
||||
|
||||
28) Connect an Android device using a USB cable.
|
||||
|
||||
If the device asks to allow USB debugging, tap "Allow".
|
||||
|
||||
29) Close any Android / iOS emulators.
|
||||
|
||||
30) Build APK and run on device:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run android
|
||||
```
|
||||
|
||||
If the Android emulators are closed and an Android device is connected, the last
|
||||
command will build an APK and install on the device.
|
||||
|
||||
### iOS Device
|
||||
|
||||
31) Connect an iOS device using a USB cable
|
||||
|
||||
32) Close any Android / iOS emulators.
|
||||
|
||||
33) Enable developer code signing certificates[^9]
|
||||
|
||||
34) Run on device:
|
||||
|
||||
```bash
|
||||
npx -p nativescript ns run ios
|
||||
```
|
||||
|
||||
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^2]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^3]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
@ -610,4 +649,5 @@ The app should show Presidential data.
|
||||
[^5]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^6]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^7]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^8]: See ["Local setup"](https://docs.nativescript.org/setup/#local-setup) in the NativeScript documentation. For Windows and Linux, follow the "Android" instructions. For macOS, follow both the iOS and Android instructions.
|
||||
[^8]: See ["Local setup"](https://docs.nativescript.org/setup/#local-setup) in the NativeScript documentation. For Windows and Linux, follow the "Android" instructions. For macOS, follow both the iOS and Android instructions.
|
||||
[^9]: The [Flutter documentation](https://docs.flutter.dev/get-started/install/macos?tab=ios15#enable-developer-code-signing-certificates) covers the instructions in more detail. The correct workspace is `platforms/ios/SheetJSNS.xcodeproj/project.xcworkspace`
|
@ -37,6 +37,17 @@ The ["Demo"](#demo) creates an app that looks like the screenshots below:
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS | Type | Device | Quasar | Date |
|
||||
|:-----------|:-----|:--------------------|:---------|:-----------|
|
||||
| Android 34 | Sim | Pixel 3a | `2.14.1` | 2023-12-04 |
|
||||
| iOS 17.0.1 | Sim | iPhone SE (3rd gen) | `2.14.1` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
|
||||
@ -143,16 +154,6 @@ window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
|
||||
|
||||
## Demo
|
||||
|
||||
:::note
|
||||
|
||||
The Android demo was last tested on 2023 September 18 with Quasar `2.12.7` on an
|
||||
emulated Pixel 3 + Android 13 ("Tiramisu") API 33.
|
||||
|
||||
The iOS demo was last tested on 2023 September 18 with Quasar `2.12.7` on an
|
||||
emulated iPhone SE (3rd generation) + iOS 16.4.
|
||||
|
||||
:::
|
||||
|
||||
The demo draws from the ViteJS example. Familiarity with VueJS and TypeScript
|
||||
is assumed.
|
||||
|
@ -45,6 +45,24 @@ The [CapacitorJS demo](/docs/demos/mobile/capacitor) covers CapacitorJS apps.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS | Type | Device | Date |
|
||||
|:-----------|:-----|:--------------------|:-----------|
|
||||
| Android 34 | Sim | Pixel 3a | 2023-12-04 |
|
||||
| iOS 17.0.1 | Sim | iPhone SE (3rd gen) | 2023-12-04 |
|
||||
|
||||
`ionic info` showed:
|
||||
|
||||
- Ionic: `@ionic/angular 7.5.7`, `@ionic/angular-toolkit 9.0.0`
|
||||
- Cordova: `cordova-lib@12.0.1`, `android 12.0.1, ios 7.0.1`
|
||||
|
||||
The file integration uses `@awesome-cordova-plugins/file` version `6.4.0`.
|
||||
|
||||
:::
|
||||
|
||||
:::warning Telemetry
|
||||
|
||||
Before starting this demo, manually disable telemetry. On Linux and MacOS:
|
||||
@ -173,23 +191,6 @@ this.file.writeFile(url, filename, blob, {replace: true});
|
||||
|
||||
## Demo
|
||||
|
||||
:::note
|
||||
|
||||
The project was last tested in 2023 September 10. `ionic info` showed:
|
||||
|
||||
- Ionic: `@ionic/angular 7.3.3`, `@ionic/angular-toolkit 9.0.0`
|
||||
- Cordova: `cordova-lib@12.0.1`, `android 12.0.1, ios 7.0.1`
|
||||
|
||||
The file integration uses `@awesome-cordova-plugins/file` version `6.4.0`.
|
||||
|
||||
The iOS demo was last tested on 2023 September 10 on an emulated iPhone SE
|
||||
(3rd generation) + iOS 16.4
|
||||
|
||||
The Android demo was last tested on 2023 September 10 on an emulated Pixel 3 +
|
||||
Android 13 ("Tiramisu") API 33.
|
||||
|
||||
:::
|
||||
|
||||
The app in this demo will display data in a table.
|
||||
|
||||
On load, a [test file](https://sheetjs.com/pres.numbers) will be processed.
|
||||
@ -230,6 +231,21 @@ If a prompt asks to confirm Cordova use, enter `Yes` to continue.
|
||||
|
||||
If a prompt asks about creating an Ionic account, enter `N` to opt out.
|
||||
|
||||
:::caution pass
|
||||
|
||||
Due to conflicts in the dependency tree, the command failed in the last test.
|
||||
|
||||
The fix is to force install all modules:
|
||||
|
||||
```bash
|
||||
cd SheetJSIonic
|
||||
npm i --force @angular/cli
|
||||
npm i --force
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
4) Set up Cordova:
|
||||
|
||||
```bash
|
||||
@ -379,6 +395,25 @@ native-run ios --app platforms/ios/build/Debug-iphonesimulator/SheetJSIonic.app
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
In some tests, the `emulate` command failed with:
|
||||
|
||||
```
|
||||
Error: Unknown argument: platform
|
||||
[ERROR] An error occurred while running subprocess ng.
|
||||
|
||||
ng run app:ionic-cordova-build --platform=ios exited with exit code 1.
|
||||
```
|
||||
|
||||
The fix is to manually add `@ionic/cordova-builders`:
|
||||
|
||||
```bash
|
||||
ng add @ionic/cordova-builders
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Android
|
||||
|
||||
10) Enable file reading and writing in the Android app.
|
@ -28,6 +28,19 @@ The "Complete Example" creates an app that looks like the screenshots below:
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS | Type | Device | CapacitorJS + FS | Date |
|
||||
|:-----------|:-----|:--------------------|:------------------|:-----------|
|
||||
| Android 34 | Sim | Pixel 3a | `5.5.1` / `5.1.4` | 2023-12-04 |
|
||||
| iOS 17.0.1 | Sim | iPhone 15 Pro Max | `5.5.1` / `5.1.4` | 2023-12-04 |
|
||||
| Android 29 | Real | NVIDIA Shield | `5.5.1` / `5.1.4` | 2023-12-04 |
|
||||
| iOS 15.1 | Real | iPad Pro | `5.5.1` / `5.1.4` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
:::warning Telemetry
|
||||
|
||||
Before starting this demo, manually disable telemetry. On Linux and MacOS:
|
||||
@ -113,16 +126,6 @@ async function exportFile() {
|
||||
|
||||
## Demo
|
||||
|
||||
:::note
|
||||
|
||||
The Android demo was last tested on 2023 September 03 with CapacitorJS `5.3.0`
|
||||
and filesystem `5.1.3` on an emulated Pixel 3 + Android 13 ("Tiramisu") API 33.
|
||||
|
||||
The iOS demo was last tested on 2023 September 03 with CapacitorJS `5.3.0`
|
||||
and filesystem `5.1.3` on an emulated iPhone SE (3rd generation) + iOS 16.4.
|
||||
|
||||
:::
|
||||
|
||||
### Base Project
|
||||
|
||||
0) Follow the official "Environment Setup"[^1] instructions to set up Android
|
||||
@ -175,6 +178,12 @@ npx cap init sheetjs-cap com.sheetjs.cap --web-dir=dist
|
||||
npm run build
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
If prompted to create an Ionic account, type `N` and press Enter.
|
||||
|
||||
:::
|
||||
|
||||
5) Download [`src/App.svelte`](pathname:///cap/App.svelte) and replace:
|
||||
|
||||
```bash
|
||||
@ -192,8 +201,8 @@ npx cap add android
|
||||
|
||||
7) Enable file reading and writing in the Android app.
|
||||
|
||||
The following lines must be added to `android/app/src/main/AndroidManifest.xml`
|
||||
after the `Permissions` comment:
|
||||
Add the highlighted lines to `android/app/src/main/AndroidManifest.xml` after
|
||||
the `Permissions` comment:
|
||||
|
||||
```xml title="android/app/src/main/AndroidManifest.xml (add to file)"
|
||||
<!-- Permissions -->
|
||||
@ -259,6 +268,8 @@ npx cap sync
|
||||
npx cap run ios
|
||||
```
|
||||
|
||||
If prompted to select a target device, select "iPhone 15 Pro Max (simulator)".
|
||||
|
||||
13) Test the app
|
||||
|
||||
Open the app and observe that presidents are listed in the table.
|
||||
@ -268,4 +279,61 @@ Touch "Export XLSX" and a popup will be displayed.
|
||||
To see the generated file, switch to the "Files" app in the simulator and look
|
||||
for `SheetJSCap.xlsx` in "On My iPhone" > "`sheetjs-cap`"
|
||||
|
||||
[^1]: See ["Environment Setup"](https://capacitorjs.com/docs/getting-started/environment-setup) in the CapacitorJS documentation.
|
||||
### Android Device
|
||||
|
||||
14) Connect an Android device using a USB cable.
|
||||
|
||||
If the device asks to allow USB debugging, tap "Allow".
|
||||
|
||||
15) Close any Android / iOS emulators.
|
||||
|
||||
16) Build APK and run on device:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npx cap sync
|
||||
npx cap run android
|
||||
```
|
||||
|
||||
If the Android emulators are closed and an Android device is connected, the last
|
||||
command will build an APK and install on the device.
|
||||
|
||||
:::caution pass
|
||||
|
||||
For real devices running API level 29 or below, the following line must be added
|
||||
to the `application` open tag in `android/app/src/main/AndroidManifest.xml`:
|
||||
|
||||
```xml title="android/app/src/main/AndroidManifest.xml (add highlighted attribute)"
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
// highlight-next-line
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:theme="@style/AppTheme">
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### iOS Device
|
||||
|
||||
17) Connect an iOS device using a USB cable
|
||||
|
||||
18) Close any Android / iOS emulators.
|
||||
|
||||
19) Enable developer code signing certificates[^2]
|
||||
|
||||
19) Run on device:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npx cap sync
|
||||
npx cap run ios
|
||||
```
|
||||
|
||||
When prompted to select a target device, select the real device in the list.
|
||||
|
||||
[^1]: See ["Environment Setup"](https://capacitorjs.com/docs/getting-started/environment-setup) in the CapacitorJS documentation.
|
||||
[^2]: The [Flutter documentation](https://docs.flutter.dev/get-started/install/macos?tab=ios15#enable-developer-code-signing-certificates) covers the instructions in more detail. The correct workspace is `ios/App/App.xcworkspace`
|
@ -37,6 +37,19 @@ The "Demo" creates an app that looks like the screenshots below:
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| OS | Type | Device | Dart | Flutter | Date |
|
||||
|:-----------|:-----|:------------------|:--------|:---------|:-----------|
|
||||
| Android 34 | Sim | Pixel 3a | `3.2.2` | `3.16.2` | 2023-12-04 |
|
||||
| iOS 17.0.1 | Sim | iPhone 15 Pro Max | `3.2.2` | `3.16.2` | 2023-12-04 |
|
||||
| Android 29 | Real | NVIDIA Shield | `3.2.2` | `3.16.2` | 2023-12-04 |
|
||||
| iOS 15.1 | Real | iPad Pro | `3.2.2` | `3.16.2` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
:::warning Telemetry
|
||||
|
||||
Before starting this demo, manually disable telemetry. On MacOS:
|
||||
@ -195,32 +208,51 @@ class SheetJSFlutterState extends State<SheetJSFlutter> {
|
||||
|
||||
## Demo
|
||||
|
||||
:::note
|
||||
|
||||
The Android demo was last tested on 2023 September 03 with Flutter `3.13.2`. The
|
||||
simulator used Android 13 ("Tiramisu") API 33 on a Pixel 3.
|
||||
|
||||
The iOS demo was last tested on 2023 September 03 with Flutter `3.13.2`. The
|
||||
simulator used iOS 16.4 on an iPhone SE (3rd generation).
|
||||
|
||||
Both tests used Dart 3.1.0 and Flutter JS plugin version `0.8.0`.
|
||||
|
||||
:::
|
||||
|
||||
0) Follow the official "Install" instructions for Flutter[^8].
|
||||
|
||||
Run `flutter doctor` and confirm the following items are checked:
|
||||
|
||||
```
|
||||
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
|
||||
[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
|
||||
[✓] Android Studio (version 2022.1)
|
||||
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
|
||||
[✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
|
||||
[✓] Android Studio (version 2022.3)
|
||||
```
|
||||
|
||||
(the actual version numbers may differ)
|
||||
|
||||
<details open><summary><b>Installation Notes</b> (click to hide)</summary>
|
||||
|
||||
:::note pass
|
||||
|
||||
On first run, there may be a warning with "Android toolchain":
|
||||
|
||||
```
|
||||
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
|
||||
! Some Android licenses not accepted. To resolve this, run: flutter doctor
|
||||
--android-licenses
|
||||
```
|
||||
|
||||
As stated, the fix is to run the command:
|
||||
|
||||
```bash
|
||||
flutter doctor --android-licenses
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::note pass
|
||||
|
||||
On first run, there may be a warning with "Xcode":
|
||||
|
||||
```
|
||||
[!] Xcode - develop for iOS and macOS (Xcode 15.0.1)
|
||||
✗ Unable to get list of installed Simulator runtimes.
|
||||
```
|
||||
|
||||
Open "Settings" panel in Xcode. Under "Platforms", click "Get" next to "iOS".
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
In local testing, there were issues with the Android toolchain:
|
||||
@ -234,7 +266,7 @@ back to `Android SDK Command-Line Tools (revision: 10.0)`
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
:::note pass
|
||||
|
||||
If Google Chrome is not installed, `flutter doctor` will show an issue:
|
||||
|
||||
@ -258,7 +290,7 @@ Run `flutter emulators` and check for both `ios` and `android` emulators:
|
||||
|
||||
```
|
||||
apple_ios_simulator • iOS Simulator • Apple • ios
|
||||
Pixel_3_API_33 • Pixel 3 API 33 • Google • android
|
||||
Pixel_3a_API_34 • Pixel 3a API 34 • Google • android
|
||||
```
|
||||
|
||||
1) Disable telemetry.
|
||||
@ -297,17 +329,29 @@ List the available emulators with `flutter emulators`:
|
||||
2 available emulators:
|
||||
|
||||
apple_ios_simulator • iOS Simulator • Apple • ios
|
||||
Pixel_3_API_33 • Pixel 3 API 33 • Google • android
|
||||
^^^^^^^^^^^^^^--- the first column is the name
|
||||
Pixel_3a_API_34 • Pixel 3a API 34 • Google • android
|
||||
^^^^^^^^^^^^^^^--- the first column is the name
|
||||
```
|
||||
|
||||
The first column shows the name that should be passed to `emulator -avd`. In a
|
||||
previous test, the name was `Pixel_3_API_33` and the launch command was:
|
||||
previous test, the name was `Pixel_3a_API_34` and the launch command was:
|
||||
|
||||
```bash
|
||||
emulator -avd Pixel_3a_API_34
|
||||
```
|
||||
% emulator -avd Pixel_3_API_33
|
||||
|
||||
:::note pass
|
||||
|
||||
On macOS, `~/Library/Android/sdk/emulator/` is the typical location for the
|
||||
`emulator` binary. If it cannot be found, add the folder to `PATH`:
|
||||
|
||||
```bash
|
||||
export PATH="$PATH":~/Library/Android/sdk/emulator
|
||||
emulator -avd Pixel_3a_API_34
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
</details>
|
||||
|
||||
4) While the Android emulator is open, start the application:
|
||||
@ -444,6 +488,82 @@ flutter run
|
||||
The app fetches <https://sheetjs.com/pres.numbers>, parses, converts data to an
|
||||
array of arrays, and presents the data in a Flutter `Table` widget.
|
||||
|
||||
### Android Device
|
||||
|
||||
14) Connect an Android device using a USB cable.
|
||||
|
||||
If the device asks to allow USB debugging, tap "Allow".
|
||||
|
||||
15) Verify that `flutter` can find the device:
|
||||
|
||||
```bash
|
||||
flutter devices
|
||||
```
|
||||
|
||||
The list should include the device:
|
||||
|
||||
```
|
||||
SheetJS (mobile) • 1234567890 • android-arm64 • Android 10 (API 29)
|
||||
^^^^^^^--- the first column is the name
|
||||
```
|
||||
|
||||
16) Build an APK:
|
||||
|
||||
```bash
|
||||
flutter build apk --release
|
||||
```
|
||||
|
||||
17) Install on the Android device:
|
||||
|
||||
```bash
|
||||
flutter install
|
||||
```
|
||||
|
||||
The script will ask for a device:
|
||||
|
||||
```
|
||||
[1]: SheetJS (1234567890)
|
||||
[2]: iPhone 15 Pro Max (12345678-9ABC-DEF0-1234-567890ABCDEF)
|
||||
[3]: macOS (macos)
|
||||
[4]: Chrome (chrome)
|
||||
Please choose one (or "q" to quit):
|
||||
```
|
||||
|
||||
Select the number corresponding to the device.
|
||||
|
||||
18) Launch the installed `sheetjs_flutter` app on the device
|
||||
|
||||
:::caution pass
|
||||
|
||||
The app may take 30 seconds to load the content.
|
||||
|
||||
**There are known bugs in the Dart HTTP client in Android 12[^9].**
|
||||
|
||||
:::
|
||||
|
||||
### iOS Device
|
||||
|
||||
19) Follow the official "Deploy to physical iOS devices" instructions[^10]
|
||||
|
||||
20) Connect the iOS device and verify that `flutter` can find the device:
|
||||
|
||||
```bash
|
||||
flutter devices
|
||||
```
|
||||
|
||||
The list should include the device:
|
||||
|
||||
```
|
||||
SheetPad (mobile) • 00000000-0000000000000000 • ios • iOS 15.1 19B74
|
||||
^^^^^^^^--- the first column is the name
|
||||
```
|
||||
|
||||
21) Run the program on the device:
|
||||
|
||||
```bash
|
||||
flutter run -d SheetPad
|
||||
```
|
||||
|
||||
[^1]: <https://dart.dev/> is the official site for the Dart Programming Language.
|
||||
[^2]: <https://flutter.dev/> is the official site for the Flutter Framework.
|
||||
[^3]: [The `flutter_js` package](https://pub.dev/packages/flutter_js) is hosted on the Dart package repository.
|
||||
@ -452,3 +572,5 @@ array of arrays, and presents the data in a Flutter `Table` widget.
|
||||
[^6]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^7]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)
|
||||
[^8]: See [the Flutter Installation Instructions](https://docs.flutter.dev/get-started/install)
|
||||
[^9]: For example, [Issue 836 in the `http` repository](https://github.com/dart-lang/http/issues/836) mentions that API calls may take 10+ seconds. This is an issue in Dart + Flutter.
|
||||
[^10]: See ["Deploy to physical iOS devices"](https://docs.flutter.dev/get-started/install/macos?tab=ios15#deploy-to-physical-ios-devices) in the Flutter documentation
|
@ -858,7 +858,7 @@ highlighted lines:
|
||||
npx react-native run-macos
|
||||
```
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
If the app runs but no window is displayed, clear caches and try again:
|
||||
|
||||
|
@ -156,85 +156,4 @@ can be adapted to generate SQL statements for a variety of databases, including:
|
||||
|
||||
**MySQL / MariaDB**
|
||||
|
||||
The `mysql2` connector library was tested. The differences are shown below,
|
||||
primarily stemming from the different quoting requirements and field types.
|
||||
|
||||
<details><summary><b>Differences</b> (click to show)</summary>
|
||||
|
||||
```js
|
||||
// highlight-start
|
||||
// define mapping between determined types and MySQL types
|
||||
const PG = { "n": "REAL", "s": "TEXT", "b": "TINYINT" };
|
||||
// highlight-end
|
||||
|
||||
function generate_sql(ws, wsname) {
|
||||
|
||||
// generate an array of objects from the data
|
||||
const aoo = XLSX.utils.sheet_to_json(ws);
|
||||
|
||||
// types will map column headers to types, while hdr holds headers in order
|
||||
const types = {}, hdr = [];
|
||||
|
||||
// loop across each row object
|
||||
aoo.forEach(row =>
|
||||
// Object.entries returns a row of [key, value] pairs. Loop across those
|
||||
Object.entries(row).forEach(([k,v]) => {
|
||||
|
||||
// If this is first time seeing key, mark unknown and append header array
|
||||
if(!types[k]) { types[k] = "?"; hdr.push(k); }
|
||||
|
||||
// skip null and undefined
|
||||
if(v == null) return;
|
||||
|
||||
// check and resolve type
|
||||
switch(typeof v) {
|
||||
case "string": // strings are the broadest type
|
||||
types[k] = "s"; break;
|
||||
case "number": // if column is not string, number is the broadest type
|
||||
if(types[k] != "s") types[k] = "n"; break;
|
||||
case "boolean": // only mark boolean if column is unknown or boolean
|
||||
if("?b".includes(types[k])) types[k] = "b"; break;
|
||||
default: types[k] = "s"; break; // default to string type
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// The final array consists of the CREATE TABLE query and a series of INSERTs
|
||||
return [
|
||||
// generate CREATE TABLE query and return batch
|
||||
// highlight-next-line
|
||||
`CREATE TABLE ${wsname} (${hdr.map(h =>
|
||||
// highlight-next-line
|
||||
`${h} ${PG[types[h]]}`
|
||||
).join(", ")});`
|
||||
].concat(aoo.map(row => { // generate INSERT query for each row
|
||||
// entries will be an array of [key, value] pairs for the data in the row
|
||||
const entries = Object.entries(row);
|
||||
// fields will hold the column names and values will hold the values
|
||||
const fields = [], values = [];
|
||||
// check each key/value pair in the row
|
||||
entries.forEach(([k,v]) => {
|
||||
// skip null / undefined
|
||||
if(v == null) return;
|
||||
// highlight-next-line
|
||||
fields.push(`${k}`);
|
||||
// when the field type is numeric, `true` -> 1 and `false` -> 0
|
||||
if(types[k] == "n") values.push(typeof v == "boolean" ? (v ? 1 : 0) : v);
|
||||
// otherwise,
|
||||
// highlight-next-line
|
||||
else values.push(`"${v.toString().replaceAll('"', '""')}"`);
|
||||
})
|
||||
if(fields.length) return `INSERT INTO \`${wsname}\` (${fields.join(", ")}) VALUES (${values.join(", ")})`;
|
||||
})).filter(x => x); // filter out skipped rows
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
The first property of a query result is an array of objects that plays nice
|
||||
with `json_to_sheet`:
|
||||
|
||||
```js
|
||||
const aoa = await connection.query(`SELECT * FROM DataTable`)[0];
|
||||
const worksheet = XLSX.utils.json_to_sheet(aoa);
|
||||
```
|
||||
**[The exposition has been moved to a separate page.](/docs/demos/data/mariadb)**
|
@ -24,12 +24,6 @@ This demo uses SQLite and SheetJS to exchange data between spreadsheets and SQL
|
||||
servers. We'll explore how to use save tables from a database to spreadsheets
|
||||
and how to add data from spreadsheets into a database.
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 October 13
|
||||
|
||||
:::
|
||||
|
||||
:::info pass
|
||||
|
||||
This demo covers SQLite `.db` file processing.
|
||||
@ -39,6 +33,19 @@ SQLite-compatible database built into Chromium and Google Chrome.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Platform | Connector Library | Date |
|
||||
|:-----------------|:---------------------------|:-----------|
|
||||
| Chromium 119 | `sql.js` (`1.8.0`) | 2023-12-04 |
|
||||
| NodeJS `20.10.0` | `better-sqlite3` (`9.2.0`) | 2023-12-04 |
|
||||
| BunJS `1.0.15` | (built-in) | 2023-12-04 |
|
||||
| Deno `1.38.4` | `sqlite` (`3.8`) | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
## Demo
|
||||
|
||||
The following examples show how to query for each table in an SQLite database,
|
||||
@ -161,7 +168,7 @@ function SheetJSQLJS() { return (<button onClick={async() => {
|
||||
|
||||
const rowobj = stmt.getAsObject();
|
||||
/* add to sheet */
|
||||
XLSX.utils.sheet_add_json(ws, [rowobj], { header, origin: -1, skipHeader: true});
|
||||
XLSX.utils.sheet_add_json(ws, [rowobj], { header, origin: -1, skipHeader: true });
|
||||
}
|
||||
if(ws) XLSX.utils.book_append_sheet(wb, ws, row.name);
|
||||
}
|
||||
@ -190,6 +197,8 @@ var aoo = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all();
|
||||
var ws = XLSX.utils.json_to_sheet(aoo, {dense: true});
|
||||
```
|
||||
|
||||
#### NodeJS Demo
|
||||
|
||||
0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql):
|
||||
|
||||
```bash
|
||||
@ -200,7 +209,8 @@ sqlite3 chinook.db ".read chinook.sql"
|
||||
1) Install the dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz better-sqlite3@9.0.0`}
|
||||
npm init -y
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz better-sqlite3@9.2.0`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Download [`SheetJSQLiteNode.mjs`](pathname:///sqlite/SheetJSQLiteNode.mjs):
|
||||
@ -235,6 +245,8 @@ var aoo = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all();
|
||||
var ws = XLSX.utils.json_to_sheet(aoo, {dense: true});
|
||||
```
|
||||
|
||||
#### BunJS Demo
|
||||
|
||||
0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql):
|
||||
|
||||
```bash
|
||||
@ -282,6 +294,8 @@ var data = [query.columns().map(x => x.name)].concat(aoa);
|
||||
var ws = XLSX.utils.aoa_to_sheet(data, {dense: true});`}
|
||||
</CodeBlock>
|
||||
|
||||
#### Deno Demo
|
||||
|
||||
0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql):
|
||||
|
||||
```bash
|
@ -19,10 +19,14 @@ This demo uses KnexJS and SheetJS to exchange data between spreadsheets and SQL
|
||||
servers. We'll explore how to use save tables from a database to spreadsheets
|
||||
and how to add data from spreadsheets into a database.
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 September 23 with Knex 2.5.1. The demo uses
|
||||
the SQLite backend with the `better-sqlite3` connector.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Version | Database | Connector Module | Date |
|
||||
|:--------|:---------|:-----------------|:-----------|
|
||||
| `2.5.1` | SQLite | `better-sqlite` | 2023-12-04 |
|
||||
| `3.0.1` | SQLite | `better-sqlite` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
@ -30,10 +30,14 @@ against SQL injection and other vulnerabilities.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 30 with PostgreSQL 16.0.1. The demo
|
||||
uses `pg` connector module version 8.11.3.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Postgres | Connector Library | Date |
|
||||
|:---------|:------------------|:-----------|
|
||||
| `16.0.1` | `pg` (`8.11.3`) | 2023-10-30 |
|
||||
| `15.5` | `pg` (`8.11.3`) | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -372,18 +376,24 @@ correct host name and port number.
|
||||
- If the server expects a different username and password, uncomment the `user`
|
||||
and `password` lines and replace the values with the username and password.
|
||||
|
||||
11) Run the script:
|
||||
11) Fetch the example file [`pres.numbers`](https://sheetjs.com/pres.numbers):
|
||||
|
||||
```bash
|
||||
curl -L -O https://sheetjs.com/pres.numbers
|
||||
```
|
||||
|
||||
12) Run the script:
|
||||
|
||||
```bash
|
||||
node SheetJSPG.js
|
||||
```
|
||||
|
||||
12) Verify the result:
|
||||
13) Verify the result:
|
||||
|
||||
- `SheetJSPG.xlsx` can be opened in a spreadsheet app or tested in the terminal
|
||||
- `SheetJSPGExport.xlsx` can be opened in a spreadsheet app or tested in the terminal
|
||||
|
||||
```bash
|
||||
npx xlsx-cli SheetJSPG.xlsx
|
||||
npx xlsx-cli SheetJSPGExport.xlsx
|
||||
```
|
||||
|
||||
- The database server can be queried using the `psql` command line tool.
|
401
docz/docs/03-demos/23-data/17-mariadb.md
Normal file
401
docz/docs/03-demos/23-data/17-mariadb.md
Normal file
@ -0,0 +1,401 @@
|
||||
---
|
||||
title: Sheets with MariaDB and MySQL
|
||||
sidebar_label: MariaDB / MySQL
|
||||
pagination_prev: demos/desktop/index
|
||||
pagination_next: demos/local/index
|
||||
sidebar_custom_props:
|
||||
sql: true
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
[MariaDB](https://mariadb.com/) is an open source object-relational database
|
||||
system compatible with MySQL.
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
This demo uses SheetJS to exchange data between spreadsheets and MariaDB
|
||||
databases. We'll explore how to save tables from a database to spreadsheets and
|
||||
how to add data from spreadsheets into a database.
|
||||
|
||||
:::caution pass
|
||||
|
||||
**It is strongly recommended to use MariaDB with a query builder or ORM.**
|
||||
|
||||
While it is possible to generate SQL statements directly, there are many subtle
|
||||
details and pitfalls. Battle-tested solutions generally provide mitigations
|
||||
against SQL injection and other vulnerabilities.
|
||||
|
||||
:::
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| MariaDB | Connector Library | Date |
|
||||
|:---------|:-------------------|:-----------|
|
||||
| `11.2.2` | `mysql2` (`3.6.5`) | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be
|
||||
loaded in NodeJS scripts that connect to MariaDB and MySQL databases.
|
||||
|
||||
This demo uses the `mysql2` connector module[^1], but the same mechanics apply
|
||||
to other MariaDB and MySQL libraries.
|
||||
|
||||
### Exporting Data
|
||||
|
||||
`Connection#execute` returns a Promise that resolves to a result array. The
|
||||
first entry of the result is an array of objects.
|
||||
|
||||
The SheetJS `json_to_sheet` method[^2] can generate a worksheet object[^3] from
|
||||
the array of objects:
|
||||
|
||||
```js
|
||||
const mysql = require("mysql2/promise"), XLSX = require("xlsx");
|
||||
const conn = await mysql.createConnection({
|
||||
database: "SheetJSMariaDB",
|
||||
/* ... other options ... */
|
||||
});
|
||||
|
||||
const table_name = "Tabeller1"; // name of table
|
||||
|
||||
/* fetch all data from specified table */
|
||||
const [rows, fields] = await conn.execute(`SELECT * FROM ${mysql.escapeId(table_name)}`);
|
||||
|
||||
/* generate a SheetJS worksheet object from the data */
|
||||
const worksheet = XLSX.utils.json_to_sheet(rows);
|
||||
```
|
||||
|
||||
A workbook object can be built from the worksheet using utility functions[^4].
|
||||
The workbook can be exported using the SheetJS `writeFile` method[^5]:
|
||||
|
||||
```js
|
||||
/* create a new workbook and add the worksheet */
|
||||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, worksheet, "Sheet1");
|
||||
|
||||
/* export workbook to XLSX */
|
||||
XLSX.writeFile(wb, "SheetJSMariaDBExport.xlsx");
|
||||
```
|
||||
|
||||
### Importing Data
|
||||
|
||||
The SheetJS `sheet_to_json` function[^6] takes a worksheet object and generates
|
||||
an array of objects.
|
||||
|
||||
Queries must be manually generated from the objects. Assuming the field names
|
||||
in the object match the column headers, a loop can generate `INSERT` queries.
|
||||
|
||||
:::warning pass
|
||||
|
||||
**MariaDB does not allow parameterized queries with variable column names**
|
||||
|
||||
```sql
|
||||
INSERT INTO table_name (?) VALUES (?);
|
||||
-- ---------------------^ variable column names are not valid
|
||||
```
|
||||
|
||||
Queries are generated manually. To help prevent SQL injection vulnerabilities,
|
||||
the undocumented `escapeId` method [^7] escapes identifiers and fields.
|
||||
|
||||
:::
|
||||
|
||||
```js
|
||||
/* generate an array of arrays from the worksheet */
|
||||
const aoo = XLSX.utils.sheet_to_json(ws);
|
||||
|
||||
const table_name = "Blatte1"; // name of table
|
||||
|
||||
/* loop through the data rows */
|
||||
for(let row of aoo) {
|
||||
/* generate INSERT column names and values */
|
||||
const ent = Object.entries(row);
|
||||
const Istr = ent.map(e => I(e[0])).join(", ");
|
||||
const Vstr = ent.map(e => E(e[1])).join(", ");
|
||||
|
||||
/* execute INSERT statement */
|
||||
await conn.execute(`INSERT INTO ${I(table_name)} (${Istr}) VALUES (${Vstr})`);
|
||||
}
|
||||
```
|
||||
|
||||
### Creating a Table
|
||||
|
||||
The array of objects can be scanned to determine column names and types. With
|
||||
the names and types, a `CREATE TABLE` query can be written.
|
||||
|
||||
<details><summary><b>Implementation Details</b> (click to show)</summary>
|
||||
|
||||
The `aoo_to_mariadb_table` function:
|
||||
|
||||
- scans each row object to determine column names and types
|
||||
- drops and creates a new table with the determined column names and types
|
||||
- loads the entire dataset into the new table
|
||||
|
||||
```js
|
||||
/* create table and load data given an array of objects and a mysql2 connection */
|
||||
async function aoo_to_mariadb_table(conn, aoo, table_name) {
|
||||
/* define types that can be converted (e.g. boolean can be stored in float) */
|
||||
const T_FLOAT = ["DOUBLE", "BOOLEAN"];
|
||||
const T_BOOL = ["BOOLEAN"];
|
||||
|
||||
/* types is a map from column headers to Knex schema column type */
|
||||
const types = {};
|
||||
|
||||
/* names is an ordered list of the column header names */
|
||||
const names = [];
|
||||
|
||||
/* loop across each row object */
|
||||
aoo.forEach(row =>
|
||||
/* Object.entries returns a row of [key, value] pairs */
|
||||
Object.entries(row).forEach(([k,v]) => {
|
||||
|
||||
/* If this is first occurrence, mark unknown and append header to names */
|
||||
if(!types[k]) { types[k] = ""; names.push(k); }
|
||||
|
||||
/* skip null and undefined values */
|
||||
if(v == null) return;
|
||||
|
||||
/* check and resolve type */
|
||||
switch(typeof v) {
|
||||
/* change type if it is empty or can be stored in a float */
|
||||
case "number": if(!types[k] || T_FLOAT.includes(types[k])) types[k] = "DOUBLE"; break;
|
||||
/* change type if it is empty or can be stored in a boolean */
|
||||
case "boolean": if(!types[k] || T_BOOL.includes(types[k])) types[k] = "BOOLEAN"; break;
|
||||
/* no other type can hold strings */
|
||||
case "string": types[k] = "TEXT"; break;
|
||||
default: types[k] = "TEXT"; break;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const I = (id) => mysql.escapeId(id), E = (d) => mysql.escape(d);
|
||||
|
||||
/* Delete table if it exists in the DB */
|
||||
await conn.execute(`DROP TABLE IF EXISTS ${I(table_name)};`);
|
||||
|
||||
/* Create table */
|
||||
{
|
||||
const Istr = Object.entries(types).map(e => `${I(e[0])} ${e[1]}`).join(", ");
|
||||
await conn.execute(`CREATE TABLE ${I(table_name)} (${Istr});`);
|
||||
}
|
||||
|
||||
/* Insert each row */
|
||||
for(let row of aoo) {
|
||||
const ent = Object.entries(row);
|
||||
const Istr = ent.map(e => I(e[0])).join(", ");
|
||||
const Vstr = ent.map(e => E(e[1])).join(", ");
|
||||
await conn.execute(`INSERT INTO ${I(table_name)} (${Istr}) VALUES (${Vstr})`);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Complete Example
|
||||
|
||||
0) Install and start the MariaDB server.
|
||||
|
||||
<details><summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
On macOS, install the `mariadb` formula with Homebrew:
|
||||
|
||||
```bash
|
||||
brew install mariadb
|
||||
```
|
||||
|
||||
The last few lines of the installer explain how to start the database:
|
||||
|
||||
```text
|
||||
Or, if you don't want/need a background service you can just run:
|
||||
// highlight-next-line
|
||||
/usr/local/opt/mariadb/bin/mysqld_safe --datadir\=/usr/local/var/mysql
|
||||
```
|
||||
|
||||
Run the command to start a local database instance.
|
||||
|
||||
</details>
|
||||
|
||||
1) Drop any existing database with the name `SheetJSMariaDB`:
|
||||
|
||||
```bash
|
||||
mysql -e 'drop database if exists SheetJSMariaDB;'
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
If the server is running elsewhere, or if the username is different from the
|
||||
current user, command-line flags can override the defaults.
|
||||
|
||||
| Option | Explanation
|
||||
|:--------------|:--------------------------|
|
||||
| `-h HOSTNAME` | Name of the server |
|
||||
| `-P PORT` | specifies the port number |
|
||||
| `-U USERNAME` | specifies the username |
|
||||
| `-p PASSWORD` | specifies the password |
|
||||
|
||||
:::
|
||||
|
||||
2) Create an empty `SheetJSMariaDB` database:
|
||||
|
||||
```bash
|
||||
mysql -e 'create database SheetJSMariaDB;'
|
||||
```
|
||||
|
||||
### Connector Test
|
||||
|
||||
3) Create a project folder:
|
||||
|
||||
```bash
|
||||
mkdir sheetjs-mariadb
|
||||
cd sheetjs-mariadb
|
||||
npm init -y
|
||||
```
|
||||
|
||||
4) Install the `mysql2` connector module:
|
||||
|
||||
```bash
|
||||
npm i --save mysql2@3.6.5
|
||||
```
|
||||
|
||||
5) Save the following example codeblock to `MariaDBTest.js`:
|
||||
|
||||
```js title="MariaDBTest.js"
|
||||
const mysql = require("mysql2/promise");
|
||||
(async() => {
|
||||
|
||||
const conn = await mysql.createConnection({
|
||||
database:"SheetJSMariaDB",
|
||||
// highlight-start
|
||||
host: "127.0.0.1", // localhost
|
||||
port: 3306,
|
||||
user: "sheetjs",
|
||||
//password: ""
|
||||
// highlight-end
|
||||
});
|
||||
|
||||
const [rows, fields] = await conn.execute('SELECT ? as message', ['Hello world!']);
|
||||
console.log(rows[0].message); // Hello world!
|
||||
await conn.end();
|
||||
|
||||
})();
|
||||
```
|
||||
|
||||
6) Edit the new `MariaDBTest.js` script and modify the highlighted lines from
|
||||
the codeblock to reflect the database deployment settings.
|
||||
|
||||
- Set `user` to the username (it is almost certainly not `"sheetjs"`)
|
||||
|
||||
- If the server is not running on your computer, set `host` and `port` to the
|
||||
correct host name and port number.
|
||||
|
||||
- If the server expects a password, uncomment the `password` line and replace
|
||||
the value with the password.
|
||||
|
||||
7) Run the script:
|
||||
|
||||
```bash
|
||||
node MariaDBTest.js
|
||||
```
|
||||
|
||||
It should print `Hello world!`
|
||||
|
||||
:::caution pass
|
||||
|
||||
If the output is not `Hello world!` or if there is an error, please report the
|
||||
issue to the `mysql2` connector project for further diagnosis[^8]
|
||||
|
||||
:::
|
||||
|
||||
### Add SheetJS
|
||||
|
||||
8) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
</CodeBlock>
|
||||
|
||||
9) Download [`SheetJSMariaDB.js`](pathname:///mariadb/SheetJSMariaDB.js):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/mariadb/SheetJSMariaDB.js
|
||||
```
|
||||
|
||||
This script will:
|
||||
- read and parse the test file `pres.numbers`
|
||||
- create a connection to the `SheetJSMariaDB` database on a local MariaDB server
|
||||
- load data from the first worksheet into a table with name `Presidents`
|
||||
- disconnect and reconnect to the database
|
||||
- dump data from the table `Presidents`
|
||||
- export the dataset to `SheetJSMariaDB.xlsx`
|
||||
|
||||
10) Edit the `SheetJSMariaDB.js` script.
|
||||
|
||||
The script defines an `opts` object:
|
||||
|
||||
```js title="SheetJSMariaDB.js (configuration lines)"
|
||||
const XLSX = require("xlsx");
|
||||
const opts = {
|
||||
database:"SheetJSMariaDB",
|
||||
// highlight-start
|
||||
host: "127.0.0.1", // localhost
|
||||
port: 3306,
|
||||
user: "sheetjs",
|
||||
//password: ""
|
||||
// highlight-end
|
||||
};
|
||||
```
|
||||
|
||||
Modify the highlighted lines to reflect the database deployment settings.
|
||||
|
||||
- Set `user` to the username (it is almost certainly not `"sheetjs"`)
|
||||
|
||||
- If the server is not running on your computer, set `host` and `port` to the
|
||||
correct host name and port number.
|
||||
|
||||
- If the server expects a password, uncomment the `password` line and replace
|
||||
the value with the password.
|
||||
|
||||
11) Fetch the example file [`pres.numbers`](https://sheetjs.com/pres.numbers):
|
||||
|
||||
```bash
|
||||
curl -L -O https://sheetjs.com/pres.numbers
|
||||
```
|
||||
|
||||
12) Run the script:
|
||||
|
||||
```bash
|
||||
node SheetJSMariaDB.js
|
||||
```
|
||||
|
||||
13) Verify the result:
|
||||
|
||||
- `SheetJSMariaDBExport.xlsx` can be opened in a spreadsheet app or tested in the terminal
|
||||
|
||||
```bash
|
||||
npx xlsx-cli SheetJSMariaDBExport.xlsx
|
||||
```
|
||||
|
||||
- The database server can be queried using the `mysql` command line tool.
|
||||
|
||||
If the server is running locally, the command will be:
|
||||
|
||||
```bash
|
||||
mysql -D SheetJSMariaDB -e 'SELECT * FROM `Presidents`;'
|
||||
```
|
||||
|
||||
[^1]: See [the `mysql2` repository](https://github.com/sidorares/node-mysql2) for more info.
|
||||
[^2]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^3]: See ["Sheet Objects"](/docs/csf/sheet) in "SheetJS Data Model" for more details.
|
||||
[^4]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^5]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^6]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^7]: The `mysql2` connector library `escapeId` method is not mentioned in the documentation but is present in the TypeScript definitions.
|
||||
[^8]: The official [issue tracker](https://github.com/sidorares/node-mysql2/issues) is hosted on GitHub
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
title: AlaSQL
|
||||
title: Sheets with AlaSQL
|
||||
sidebar_label: AlaSQL
|
||||
pagination_prev: demos/desktop/index
|
||||
pagination_next: demos/local/index
|
||||
sidebar_custom_props:
|
||||
@ -29,8 +30,8 @@ This demo was tested in the following environments:
|
||||
|
||||
| Environment | AlaSQL | Date |
|
||||
|:--------------------|:-------|:----------:|
|
||||
| NodeJS | 3.1.0 | 2023-10-26 |
|
||||
| Standalone (Chrome) | 3.0.0 | 2023-11-27 |
|
||||
| NodeJS | 3.1.0 | 2023-12-04 |
|
||||
| Standalone (Chrome) | 3.1.0 | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -187,7 +188,7 @@ The `XLSX` "into" target calls `XLSX.writeFile` under the hood:
|
||||
(async() => {
|
||||
const data = [
|
||||
{ Name: "Bill Clinton", Index: 42 },
|
||||
{ Name: "Someone Else", Index: 47 }
|
||||
{ Name: "SheetJS Dev", Index: 47 }
|
||||
];
|
||||
await alasql.promise(`SELECT * INTO XLSX("PresMod5.xlsx") FROM ?`, [data]);
|
||||
/* PresMod5.xlsx will be created */
|
||||
@ -249,7 +250,7 @@ const { promise: alasql } = require("alasql");
|
||||
(async() => {
|
||||
const data = [
|
||||
{ Name: "Bill Clinton", Index: 42 },
|
||||
{ Name: "Someone Else", Index: 47 }
|
||||
{ Name: "SheetJS Dev", Index: 47 }
|
||||
];
|
||||
await alasql(`SELECT * INTO XLSX("PresMod5.xlsx") FROM ?`, [data]);
|
||||
/* PresMod5.xlsx will be created */
|
||||
@ -302,7 +303,7 @@ const { promise: alasql } = require("alasql");
|
||||
console.log(data);
|
||||
|
||||
/* write data from JS to spreadsheet */
|
||||
data.push({Name: "Someone Else", Index: 47});
|
||||
data.push({ Name: "SheetJS Dev", Index: 47 });
|
||||
await alasql(`SELECT * INTO XLSX("SheetJSAlaSQL1.xlsx") FROM ?`, [data]);
|
||||
})();
|
||||
```
|
||||
@ -330,5 +331,5 @@ Name,Index
|
||||
Bill Clinton,42
|
||||
GeorgeW Bush,43
|
||||
Barack Obama,44
|
||||
Someone Else,47
|
||||
SheetJS Dev,47
|
||||
```
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
title: MongoDB
|
||||
title: Sheets with MongoDB
|
||||
sidebar_label: MongoDB
|
||||
pagination_prev: demos/desktop/index
|
||||
pagination_next: demos/local/index
|
||||
sidebar_custom_props:
|
||||
@ -19,10 +20,14 @@ This demo uses SheetJS to exchange data between spreadsheets and MongoDB. We'll
|
||||
explore how to use save tables from a MongoDB collection to spreadsheets and how
|
||||
to add data from spreadsheets into a collection.
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 12 with MongoDB CE 7.0.2, MongoDB
|
||||
connector module 5.7.0 and NodeJS 20.8.0
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| MongoDB CE | Connector Library | Date |
|
||||
|:-----------|:--------------------|:-----------|
|
||||
| `6.0.10` | `mongodb` (`5.7.0`) | 2023-12-04 |
|
||||
| `7.0.2` | `mongodb` (`5.7.0`) | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
@ -21,6 +21,17 @@ This demo defines a schema for storing Redis databases in spreadsheets. We'll
|
||||
explore how to use SheetJS and Redis NodeJS connector modules to pull data
|
||||
from XLSX files to a Redis database and to serialize a database to a workbook.
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Redis | Connector Module | Date |
|
||||
|:--------|--------------------|:----------:|
|
||||
| `6.2.9` | `redis` (`4.6.11`) | 2023-12-04 |
|
||||
| `7.2.3` | `redis` (`4.6.11`) | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
#### Overview
|
||||
|
||||
Redis has 5 core data types: "String", List", "Set", "Sorted Set", and "Hash".
|
||||
@ -208,13 +219,6 @@ const aoa = [ ["Hash"], [key] ].concat(Object.entries(values));
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 November 18 with Redis 7.2.3, Redis connector
|
||||
module 4.6.10 and NodeJS 20.9.0.
|
||||
|
||||
:::
|
||||
|
||||
:::warning pass
|
||||
|
||||
The most recent version of the `redis` node module does not work with most
|
@ -23,10 +23,14 @@ arrays of objects to mesh with both libraries.
|
||||
The ["Complete Example"](#complete-example) section imbues the official "Todos"
|
||||
demo with the ability to export the list to XLSX workbooks.
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 September 04 against PouchDB 8.0.1 standalone
|
||||
browser script in Chrome 116.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| PouchDB | Date |
|
||||
|:--------|:----------:|
|
||||
| `7.3.1` | 2023-12-04 |
|
||||
| `8.0.1` | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
@ -181,7 +181,7 @@ Deno.writeFileSync(out_file, new TextEncoder().encode(csv));`}
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This was last tested by SheetJS users on 2023 September 24 using the GitHub UI.
|
||||
This was last tested by SheetJS users on 2023 December 04.
|
||||
|
||||
:::
|
||||
|
||||
@ -190,7 +190,6 @@ This was last tested by SheetJS users on 2023 September 24 using the GitHub UI.
|
||||
<https://github.com/SheetJS/flat-sheet> is an example from a previous test. The
|
||||
Flat Viewer URL for the repo is <https://flatgithub.com/SheetJS/flat-sheet/>
|
||||
|
||||
|
||||
:::
|
||||
|
||||
### Create Project
|
||||
|
@ -336,13 +336,29 @@ first worksheet name, and the contents of the first sheet as CSV rows.
|
||||
|
||||
### CLI Test
|
||||
|
||||
:::note
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2023 October 11 against QuickJS commit `2788d71`.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Git Commit | Date |
|
||||
|:-----------|:-----------|
|
||||
| `03cc5ec` | 2023-12-01 |
|
||||
| `2788d71` | 2023-10-11 |
|
||||
|
||||
When the demo was tested, commit `03cc5ec` corresponded to the latest commit.
|
||||
|
||||
:::
|
||||
|
||||
0) Ensure `qjs` command line utility is installed
|
||||
0) Build the `qjs` command line utility from source:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/bellard/quickjs
|
||||
cd quickjs
|
||||
git checkout 03cc5ec
|
||||
make
|
||||
cd ..
|
||||
cp quickjs/qjs .
|
||||
```
|
||||
|
||||
1) Download the SheetJS Standalone script and the test file. Save both files in
|
||||
the project directory:
|
||||
@ -366,10 +382,11 @@ curl -LO https://docs.sheetjs.com/quickjs/SheetJSQuick.js
|
||||
3) Test the program:
|
||||
|
||||
```bash
|
||||
qjs SheetJSQuick.js
|
||||
./qjs SheetJSQuick.js
|
||||
```
|
||||
|
||||
If successful, the script will generate `SheetJSQuick.xlsx`.
|
||||
If successful, the script will print CSV rows and generate `SheetJSQuick.xlsx`.
|
||||
The generated file can be opened in Excel or another spreadsheet editor.
|
||||
|
||||
|
||||
[^1]: See ["Runtime and Contexts"](https://bellard.org/quickjs/quickjs.html#Runtime-and-contexts) in the QuickJS documentation
|
||||
|
@ -405,7 +405,7 @@ formula `=CONTAR(A1:C3;B4:D6)` is equivalent to the SheetJS formula string
|
||||
|
||||
[JSON Translation table](https://oss.sheetjs.com/notes/fmla/table.json).
|
||||
|
||||
<details open><summary><b>Function Name Translator</b> (click to show)</summary>
|
||||
<details open><summary><b>Function Name Translator</b> (click to hide)</summary>
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
|
@ -306,7 +306,7 @@ sudo apt-get install curl git mercurial subversion
|
||||
|
||||
Other Linux distributions may use other package managers.
|
||||
|
||||
<details open><summary><b>Steam Deck</b> (click to show)</summary>
|
||||
<details open><summary><b>Steam Deck</b> (click to hide)</summary>
|
||||
|
||||
Desktop Mode on the Steam Deck uses `pacman`. It also requires a few steps.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<table><thead><th>Name</th><th>Index</th></thead>
|
||||
<table><thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
<tbody>
|
||||
{% for row in pres %}
|
||||
<tr>
|
||||
|
47
docz/static/esbuild/build.mjs
Normal file
47
docz/static/esbuild/build.mjs
Normal file
@ -0,0 +1,47 @@
|
||||
import * as esbuild from 'esbuild'
|
||||
import * as XLSX from 'xlsx';
|
||||
import * as fs from 'fs';
|
||||
XLSX.set_fs(fs);
|
||||
|
||||
/* plugin */
|
||||
let sheetjsPlugin = {
|
||||
name: 'sheetjs',
|
||||
setup(build) {
|
||||
/* match NUMBERS, XLSX, XLS, and XLSB files */
|
||||
const EXTS = /.(numbers|xlsx|xls|xlsb)$/;
|
||||
|
||||
/* this method will be called once for each referenced file */
|
||||
build.onLoad({ filter: EXTS }, (args) => {
|
||||
/* parse file from filesystem */
|
||||
const wb = XLSX.readFile(args.path);
|
||||
/* get first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
|
||||
/* workaround for JSON limitation */
|
||||
Date.prototype.toJSON2 = Date.prototype.toJSON;
|
||||
Date.prototype.toJSON = function() { return {d:this.toISOString()}; };
|
||||
|
||||
/* generate row objects */
|
||||
const data = XLSX.utils.sheet_to_json(ws);
|
||||
|
||||
/* generate final module code */
|
||||
const res = JSON.stringify(data);
|
||||
Date.prototype.toJSON = Date.prototype.toJSON2;
|
||||
const contents = `const data = ${res};
|
||||
data.forEach(row => {
|
||||
Object.keys(row).forEach(k => {
|
||||
if(row[k]?.d) row[k] = new Date(row[k].d);
|
||||
})
|
||||
});
|
||||
export default data;`
|
||||
return { contents, loader: 'js' };
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
await esbuild.build({
|
||||
entryPoints: ['app.js'],
|
||||
bundle: true,
|
||||
outfile: 'out.js',
|
||||
plugins: [sheetjsPlugin],
|
||||
});
|
103
docz/static/mariadb/SheetJSMariaDB.js
Normal file
103
docz/static/mariadb/SheetJSMariaDB.js
Normal file
@ -0,0 +1,103 @@
|
||||
const mysql = require("mysql2/promise");
|
||||
const XLSX = require("xlsx");
|
||||
const opts = {
|
||||
database:"SheetJSMariaDB",
|
||||
host: "127.0.0.1", // localhost
|
||||
port: 3306,
|
||||
user: "sheetjs",
|
||||
//password: ""
|
||||
};
|
||||
|
||||
/* create table and load data given an array of objects and a mysql2 connection */
|
||||
async function aoo_to_mariadb_table(conn, aoo, table_name) {
|
||||
/* define types that can be converted (e.g. boolean can be stored in float) */
|
||||
const T_FLOAT = ["DOUBLE", "BOOLEAN"];
|
||||
const T_BOOL = ["BOOLEAN"];
|
||||
|
||||
/* types is a map from column headers to Knex schema column type */
|
||||
const types = {};
|
||||
|
||||
/* names is an ordered list of the column header names */
|
||||
const names = [];
|
||||
|
||||
/* loop across each row object */
|
||||
aoo.forEach(row =>
|
||||
/* Object.entries returns a row of [key, value] pairs */
|
||||
Object.entries(row).forEach(([k,v]) => {
|
||||
|
||||
/* If this is first occurrence, mark unknown and append header to names */
|
||||
if(!types[k]) { types[k] = ""; names.push(k); }
|
||||
|
||||
/* skip null and undefined values */
|
||||
if(v == null) return;
|
||||
|
||||
/* check and resolve type */
|
||||
switch(typeof v) {
|
||||
/* change type if it is empty or can be stored in a float */
|
||||
case "number": if(!types[k] || T_FLOAT.includes(types[k])) types[k] = "DOUBLE"; break;
|
||||
/* change type if it is empty or can be stored in a boolean */
|
||||
case "boolean": if(!types[k] || T_BOOL.includes(types[k])) types[k] = "BOOLEAN"; break;
|
||||
/* no other type can hold strings */
|
||||
case "string": types[k] = "TEXT"; break;
|
||||
default: types[k] = "TEXT"; break;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const I = (id) => mysql.escapeId(id), E = (d) => mysql.escape(d);
|
||||
|
||||
/* Delete table if it exists in the DB */
|
||||
await conn.execute(`DROP TABLE IF EXISTS ${I(table_name)};`);
|
||||
|
||||
/* Create table */
|
||||
{
|
||||
const Istr = Object.entries(types).map(e => `${I(e[0])} ${e[1]}`).join(", ");
|
||||
await conn.execute(`CREATE TABLE ${I(table_name)} (${Istr});`);
|
||||
}
|
||||
|
||||
/* Insert each row */
|
||||
for(let row of aoo) {
|
||||
const ent = Object.entries(row);
|
||||
const Istr = ent.map(e => I(e[0])).join(", ");
|
||||
const Vstr = ent.map(e => E(e[1])).join(", ");
|
||||
await conn.execute(`INSERT INTO ${I(table_name)} (${Istr}) VALUES (${Vstr})`);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
(async() => {
|
||||
|
||||
/* read file and get first worksheet */
|
||||
const oldwb = XLSX.readFile("pres.numbers");
|
||||
const oldws = oldwb.Sheets[oldwb.SheetNames[0]];
|
||||
|
||||
/* import data to mariadb */
|
||||
let conn = await mysql.createConnection(opts);
|
||||
try {
|
||||
/* generate array of objects from worksheet */
|
||||
const aoo = XLSX.utils.sheet_to_json(oldws);
|
||||
|
||||
/* create table and load data */
|
||||
await aoo_to_mariadb_table(conn, aoo, "Presidents");
|
||||
} finally {
|
||||
/* disconnect */
|
||||
await conn.end();
|
||||
}
|
||||
|
||||
/* export data to xlsx */
|
||||
conn = await mysql.createConnection(opts);
|
||||
try {
|
||||
/* fetch all data from specified table */
|
||||
const [ rows ] = await conn.execute(`SELECT * FROM ${mysql.escapeId("Presidents")}`);
|
||||
|
||||
/* export to file */
|
||||
const newws = XLSX.utils.json_to_sheet(rows);
|
||||
const newwb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(newwb, newws, "Export");
|
||||
XLSX.writeFile(newwb, "SheetJSMariaDBExport.xlsx");
|
||||
} finally {
|
||||
/* disconnect */
|
||||
await conn.end();
|
||||
}
|
||||
})();
|
@ -16,6 +16,9 @@ rh.close();
|
||||
/* parse file */
|
||||
var wb = XLSX.read(ab);
|
||||
|
||||
/* print CSV rows from first sheet */
|
||||
console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
|
||||
|
||||
/* write XLSX */
|
||||
var out = XLSX.write(wb, {bookType: "xlsx", type: "array"});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user