This commit is contained in:
SheetJS 2023-04-29 07:21:37 -04:00
parent b96947e8f4
commit 514ed5f76d
21 changed files with 337 additions and 226 deletions

@ -151,7 +151,7 @@ xport.addEventListener("click", async() => {
</script>`}
</code></pre>
Web Worker support is noted in [the demo](/docs/demos/worker#installation)
Web Worker support is noted in [the demo](/docs/demos/bigdata/worker#installation)
## Bower

@ -7,6 +7,7 @@ sidebar_custom_props:
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
# Frameworks and Bundlers
@ -84,6 +85,19 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</TabItem>
</Tabs>
When the `xlsx` library is a dependency of a dependency, the `overrides` field
in `package.json` can control module resolution:
<CodeBlock language="json" title="package.json">{`\
{
// highlight-start
"overrides": {
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
}
// highlight-end
}`}
</CodeBlock>
:::
## Encoding support

@ -7,6 +7,7 @@ sidebar_custom_props:
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
# NodeJS
@ -80,6 +81,19 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</TabItem>
</Tabs>
When the `xlsx` library is a dependency of a dependency, the `overrides` field
in `package.json` can control module resolution:
<CodeBlock language="json" title="package.json">{`\
{
// highlight-start
"overrides": {
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
}
// highlight-end
}`}
</CodeBlock>
:::
### Vendoring

@ -7,6 +7,7 @@ sidebar_custom_props:
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
# AMD (define)
@ -124,27 +125,27 @@ require(["xlsx"], function(
When `async` is disabled, the scripts can be referenced directly in `require`
calls.
```html
<CodeBlock language="html">{`\
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js" data-dojo-config="isDebug:1, async:0"></script>
<script>
require([
// highlight-next-line
"https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"
"https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"
], function(
// highlight-next-line
_XLSX // !! NOTE: this is not XLSX! A different variable name must be used
) {
// ... use XLSX here
})
</script>
```
});
</script>`}
</CodeBlock>
#### Asynchronous Loading
When `async` is enabled, Dojo will only understand the name `xlsx`. The config
object can map package names to scripts:
```html
<CodeBlock language="html">{`\
<script>
// This setting must appear *before* loading dojo.js
dojoConfig = {
@ -153,18 +154,18 @@ dojoConfig = {
{
name: "xlsx",
// if self-hosting the script, location should be a folder relative to baseUrl setting
location: "https://cdn.sheetjs.com/xlsx-latest/package/dist",
location: "https://cdn.sheetjs.com/xlsx-${current}/package/dist",
// name of the script (without the .js extension)
main: "xlsx.full.min"
}
// highlight-end
]
}
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js" data-dojo-config="isDebug:1, async:1"></script>
<script>
require(["xlsx"], function(_XLSX) {
// ... use XLSX here
});
</script>
```
</script>`}
</CodeBlock>

@ -10,6 +10,7 @@ sidebar_custom_props:
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
SheetJS predates ECMAScript modules and bundler tools like Webpack. As best
practices have evolved, stress testing SheetJS libraries have revealed bugs in
@ -799,7 +800,7 @@ other tools using SystemJS have switched to Webpack.
SystemJS fails by default because the library does not export anything in the
web browser. The `meta` configuration option can be used to expose `XLSX`:
```js
<CodeBlock language="js">{`\
SystemJS.config({
meta: {
'xlsx': {
@ -807,14 +808,14 @@ SystemJS.config({
}
},
map: {
'xlsx': 'https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js',
'xlsx': 'https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js',
'fs': '', // <--|
'crypto': '', // <--| suppress native node modules
'stream': '' // <--|
}
});
SystemJS.import('main.js'); // load `main.js`
```
SystemJS.import('main.js'); // load \`main.js\``}
</CodeBlock>
The `main.js` script can freely `require("xlsx")`.

@ -5,6 +5,7 @@ pagination_next: demos/net/index
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
:::note
@ -112,9 +113,9 @@ cd sheetjs-vtl
2) Install dependencies:
```bash
npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz vue3-table-lite@1.2.4
```
<CodeBlock language="bash">{`\
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz vue3-table-lite@1.2.4`}
</CodeBlock>
3) Download [`src/App.vue`](pathname:///vtl/App.vue) and replace the contents:

@ -5,6 +5,7 @@ title: Browser Automation
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
Headless automation involves controlling "headless browsers" to access websites
and submit or download data. It is also possible to automate browsers using
@ -31,13 +32,10 @@ sequenceDiagram
U->>C: run script
rect rgba(255, 0, 0, 0.25)
C->>B: launch browser
B->>C: ready
C->>B: load URL
B->>C: site loaded
end
rect rgba(0, 127, 0, 0.25)
C->>B: add SheetJS script
B->>C: script loaded
end
rect rgba(255, 0, 0, 0.25)
C->>B: ask for file
@ -50,7 +48,7 @@ sequenceDiagram
end
```
Steps:
<details open><summary><b>Key Steps</b> (click to hide)</summary>
1) Launch the headless browser and load the target site.
@ -64,6 +62,8 @@ Steps:
4) When the automation context receives data, save to a file
</details>
This demo exports data from <https://sheetjs.com/demos/table>.
:::note
@ -76,11 +76,7 @@ the automation context is more efficient and strongly recommended.
## Puppeteer
Puppeteer enables headless Chromium automation for NodeJS. Releases ship with
an installer script. Installation is straightforward:
```bash
npm i https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz puppeteer
```
an installer script that prepares a compatible browser version.
<Tabs>
<TabItem value="nodejs" label="NodeJS">
@ -89,10 +85,9 @@ Binary strings are the favored data type. They can be safely passed from the
browser context to the automation script. NodeJS provides an API to write
binary strings to file (`fs.writeFileSync` using encoding `binary`).
To run the example, after installing the packages, save the following script to
`SheetJSPuppeteer.js` and run `node SheetJSPuppeteer.js`. Steps are commented:
The key steps are commented below:
```js title="SheetJSPuppeteer.js"
<CodeBlock language="js" title="SheetJSPuppeteer.js">{`\
const fs = require("fs");
const puppeteer = require('puppeteer');
(async () => {
@ -102,34 +97,53 @@ const puppeteer = require('puppeteer');
page.on("console", msg => console.log("PAGE LOG:", msg.text()));
await page.setViewport({width: 1920, height: 1080});
await page.goto('https://sheetjs.com/demos/table');
\n\
/* (2) Load the standalone SheetJS build from the CDN */
await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js' });
await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js' });
\n\
/* (3) Run the snippet in browser and return data */
const bin = await page.evaluate(() => {
/* NOTE: this function will be evaluated in the browser context.
`page`, `fs` and `puppeteer` are not available.
`XLSX` will be available thanks to step 2 */
\`page\`, \`fs\` and \`puppeteer\` are not available.
\`XLSX\` will be available thanks to step 2 */
\n\
/* find first table */
var table = document.body.getElementsByTagName('table')[0];
\n\
/* call table_to_book on first table */
var wb = XLSX.utils.table_to_book(table);
\n\
/* generate XLSB and return binary string */
return XLSX.write(wb, {type: "binary", bookType: "xlsb"});
});
\n\
/* (4) write data to file */
fs.writeFileSync("SheetJSPuppeteer.xlsb", bin, { encoding: "binary" });
\n\
await browser.close();
})();
```
})();`}
</CodeBlock>
This script will generate `SheetJSPuppeteer.xlsb` which can be opened in Excel.
**Demo**
:::note
This demo was last tested on 2023 April 29 against Puppeteer 19.11.1.
:::
1) Install SheetJS and Puppeteer:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@19.11.1`}
</CodeBlock>
2) Save the `SheetJSPuppeteer.js` code snippet to `SheetJSPuppeteer.js`.
3) Run `node SheetJSPuppeteer.js`.
When the script finishes, the file `SheetJSPuppeteer.xlsb` will be created.
This file can be opened with Excel.
</TabItem>
<TabItem value="deno" label="Deno">
@ -140,55 +154,67 @@ Deno Puppeteer is a fork. It is not officially supported by the Puppeteer team.
:::
Installation is straightforward:
```bash
env PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@14.1.1/install.ts
```
Base64 strings are the favored data type. They can be safely passed from the
browser context to the automation script. Deno can decode the Base64 strings
and write the decoded `Uint8Array` data to file with `Deno.writeFileSync`
To run the example, after installing the packages, save the following script to
`SheetJSPuppeteer.ts` and run `deno run -A --unstable SheetJSPuppeteer.js`.
The key steps are commented below:
```js title="SheetJSPuppeteer.ts"
import puppeteer from "https://deno.land/x/puppeteer@14.1.1/mod.ts";
<CodeBlock language="ts" title="SheetJSPuppeteer.ts">{`\
import puppeteer from "https://deno.land/x/puppeteer@16.2.0/mod.ts";
import { decode } from "https://deno.land/std/encoding/base64.ts"
\n\
/* (1) Load the target page */
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on("console", msg => console.log("PAGE LOG:", msg.text()));
await page.setViewport({width: 1920, height: 1080});
await page.goto('https://sheetjs.com/demos/table');
\n\
/* (2) Load the standalone SheetJS build from the CDN */
await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js' });
await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js' });
\n\
/* (3) Run the snippet in browser and return data */
const b64 = await page.evaluate(() => {
/* NOTE: this function will be evaluated in the browser context.
`page`, `fs` and `puppeteer` are not available.
`XLSX` will be available thanks to step 2 */
\`page\`, \`fs\` and \`puppeteer\` are not available.
\`XLSX\` will be available thanks to step 2 */
\n\
/* find first table */
var table = document.body.getElementsByTagName('table')[0];
\n\
/* call table_to_book on first table */
var wb = XLSX.utils.table_to_book(table);
\n\
/* generate XLSB and return binary string */
return XLSX.write(wb, {type: "base64", bookType: "xlsb"});
});
/* (4) write data to file */
Deno.writeFileSync("SheetJSPuppeteer.xlsb", decode(b64));
\n\
await browser.close();`}
</CodeBlock>
await browser.close();
**Demo**
:::note
This demo was last tested on 2023 April 29 against deno-puppeteer 16.2.0.
:::
1) Install deno-puppeteer:
```bash
env PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts
```
This script will generate `SheetJSPuppeteer.xlsb` which can be opened in Excel.
2) Save the `SheetJSPuppeteer.ts` code snippet to `SheetJSPuppeteer.ts`.
3) Run `deno run -A --unstable SheetJSPuppeteer.ts`.
When the script finishes, the file `SheetJSPuppeteer.xlsb` will be created.
This file can be opened with Excel.
</TabItem>
</Tabs>
@ -200,15 +226,9 @@ Playwright presents a unified scripting framework for Chromium, WebKit, and
other browsers. It draws inspiration from Puppeteer. In fact, the example
code is almost identical!
```bash
npm i https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz playwright
```
Differences from the Puppeteer example are highlighted below:
To run the example, after installing the packages, save the following script to
`SheetJSPlaywright.js` and run `node SheetJSPlaywright.js`. Import divergences
from the Puppeteer example are highlighted below:
```js title="SheetJSPlaywright.js"
<CodeBlock language="js" title="SheetJSPlaywright.js">{`\
const fs = require("fs");
// highlight-next-line
const { webkit } = require('playwright'); // import desired browser
@ -221,33 +241,53 @@ const { webkit } = require('playwright'); // import desired browser
// highlight-next-line
await page.setViewportSize({width: 1920, height: 1080}); // different name :(
await page.goto('https://sheetjs.com/demos/table');
\n\
/* (2) Load the standalone SheetJS build from the CDN */
await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js' });
await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js' });
\n\
/* (3) Run the snippet in browser and return data */
const bin = await page.evaluate(() => {
/* NOTE: this function will be evaluated in the browser context.
`page`, `fs` and the browser engine are not available.
`XLSX` will be available thanks to step 2 */
\`page\`, \`fs\` and the browser engine are not available.
\`XLSX\` will be available thanks to step 2 */
\n\
/* find first table */
var table = document.body.getElementsByTagName('table')[0];
\n\
/* call table_to_book on first table */
var wb = XLSX.utils.table_to_book(table);
\n\
/* generate XLSB and return binary string */
return XLSX.write(wb, {type: "binary", bookType: "xlsb"});
});
\n\
/* (4) write data to file */
fs.writeFileSync("SheetJSPlaywright.xlsb", bin, { encoding: "binary" });
\n\
await browser.close();
})();
```
})();`}
</CodeBlock>
**Demo**
:::note
This demo was last tested on 2023 April 29 against Playwright 1.33.0.
:::
1) Install SheetJS and Playwright:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz playwright@1.33.0`}
</CodeBlock>
2) Save the `SheetJSPlaywright.js` code snippet to `SheetJSPlaywright.js`.
3) Run `node SheetJSPlaywright.js`.
When the script finishes, the file `SheetJSPlaywright.xlsb` will be created.
This file can be opened with Excel.
## PhantomJS
@ -265,46 +305,40 @@ Binary strings are the favored data type. They can be safely passed from the
browser context to the automation script. PhantomJS provides an API to write
binary strings to file (`fs.write` using mode `wb`).
To run the example, save the following script to `SheetJSPhantom.js` in the same
folder as `phantomjs.exe` or `phantomjs` and run
```
./phantomjs SheetJSPhantom.js ## MacOS / Linux
.\phantomjs.exe SheetJSPhantom.js ## windows
```
<details><summary><b>Integration Details and Demo</b> (click to show)</summary>
The steps are marked in the comments:
```js title="SheetJSPhantom.js"
<CodeBlock language="js" title="SheetJSPhantom.js">{`\
var page = require('webpage').create();
page.onConsoleMessage = function(msg) { console.log(msg); };
\n\
/* (1) Load the target page */
page.open('https://sheetjs.com/demos/table', function() {
\n\
/* (2) Load the standalone SheetJS build from the CDN */
page.includeJs("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js", function() {
page.includeJs("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js", function() {
\n\
/* (3) Run the snippet in browser and return data */
var bin = page.evaluateJavaScript([ "function(){",
\n\
/* find first table */
"var table = document.body.getElementsByTagName('table')[0];",
\n\
/* call table_to_book on first table */
"var wb = XLSX.utils.table_to_book(table);",
\n\
/* generate XLSB file and return binary string */
"return XLSX.write(wb, {type: 'binary', bookType: 'xlsb'});",
"}" ].join(""));
\n\
/* (4) write data to file */
require("fs").write("SheetJSPhantomJS.xlsb", bin, "wb");
\n\
phantom.exit();
});
});
```
});`}
</CodeBlock>
:::caution
@ -312,3 +346,28 @@ PhantomJS is very finicky and will hang if there are script errors. It is
strongly recommended to add verbose logging and to lint scripts before use.
:::
**Demo**
:::note
This demo was last tested on 2023 April 29 against PhantomJS 2.1.1
:::
1) Download and unzip the PhantomJS release from the official website.
2) Save the `SheetJSPhantom.js` code snippet to `SheetJSPhantom.js`.
3) Run the command.
In macOS:
```bash
./phantomjs-2.1.1-macosx/bin/phantomjs SheetJSPhantom.js
```
When the script finishes, the file `SheetJSPhantomJS.xlsb` will be created.
This file can be opened with Excel.
</details>

@ -5,6 +5,7 @@ pagination_next: demos/mobile/index
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
:::note
@ -199,9 +200,9 @@ curl -LO https://docs.sheetjs.com/next/sheetjs.xlsx
3) Install dependencies:
```bash
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz next@13.1.1
```
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz next@13.1.1`}
</CodeBlock>
4) Download test scripts:

@ -8,6 +8,7 @@ sidebar_custom_props:
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
from the main entrypoint or any script in the project.
@ -184,9 +185,9 @@ After adding the lines, the `npm install` command will succeed.
3) Install dependencies:
```bash
npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
```
<CodeBlock language="bash">{`\
npm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
4) Add `@ionic-native/file` to the module. Differences highlighted below:

@ -10,6 +10,7 @@ sidebar_custom_props:
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
The [Standalone scripts](/docs/getting-started/installation/standalone) can be
referenced in a `SCRIPT` tag from the entry point HTML page.
@ -114,7 +115,7 @@ This demo was tested against NW.js 0.73.0 on 2023 February 20.
1) Create a `package.json` file that specifies the entry point:
```json title="package.json"
<CodeBlock language="json" title="package.json">{`\
{
"name": "sheetjs-nwjs",
"author": "sheetjs",
@ -122,10 +123,10 @@ This demo was tested against NW.js 0.73.0 on 2023 February 20.
"main": "index.html",
"dependencies": {
"nw": "~0.73.0",
"xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz"
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
}
}
```
}`}
</CodeBlock>
2) Download [`index.html`](pathname:///nwjs/index.html) into the same folder.

@ -7,8 +7,10 @@ sidebar_custom_props:
summary: Webview + Lightweight Extensions
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
The [Standalone build](/docs/getting-started/installation/standalone) can be added
to the entry `index.html`
@ -134,11 +136,12 @@ npx @neutralinojs/neu create sheetjs-neu
cd sheetjs-neu
```
2) Download the standalone script and place in `resources/js/main.js`:
2) Download [Standalone build](/docs/getting-started/installation/standalone)
and place in `resources/js/main.js`:
```bash
curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
```
<CodeBlock language="bash">{`\
curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
</CodeBlock>
3) Add the highlighted line to `neutralino.conf.json` in `nativeAllowList`:

@ -11,6 +11,7 @@ sidebar_custom_props:
</head>
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
AlaSQL is a pure JavaScript in-memory SQL database. It has built-in support for
SheetJS through the `XLSX` target operator.
@ -265,19 +266,19 @@ cd alasql
2) In the folder, create a stub `package.json` with the `xlsx` override:
```json title="package.json"
<CodeBlock language="json" title="package.json">{`\
{
"overrides": {
"xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz"
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
}
}
```
}`}
</CodeBlock>
3) Install SheetJS and AlaSQL:
```bash
npm i --save alasql@3.1.0 https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
```
<CodeBlock language="bash">{`\
npm i --save alasql@3.1.0 https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
4) Download the test file <https://sheetjs.com/pres.numbers> :

@ -7,6 +7,7 @@ sidebar_custom_props:
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
MongoDB is a popular document-oriented database engine.
@ -73,12 +74,12 @@ in the foreground on Intel MacOS:
2) Create base project and install the dependencies:
```bash
<CodeBlock language="bash">{`\
mkdir sheetjs-mongo
cd sheetjs-mongo
npm init -y
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz mongodb@5.1.0
```
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz mongodb@5.1.0`}
</CodeBlock>
3) Save the following to `SheetJSMongoCRUD.mjs` (the key step is highlighted):

@ -6,6 +6,9 @@ sidebar_custom_props:
type: nosql
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
PouchDB is a pure JS database with built-in synchronization features.
## Integration Details
@ -63,14 +66,14 @@ cd getting-started-todo-master
2) Edit `index.html` to reference the SheetJS library and add a button:
```html title="index.html"
<CodeBlock language="html" title="index.html">{`\
<body>
<!-- highlight-start -->
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
<button id="xport">Export!</button>
<!-- highlight-end -->
<section id="todoapp">
```
<section id="todoapp">`}
</CodeBlock>
3) Just before the end of `app.js`, add a `click` event listener:

@ -6,6 +6,9 @@ sidebar_custom_props:
summary: Reading and writing files using various platform APIs
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
Reading and writing files require native platform support. `XLSX.readFile` and
`XLSX.writeFile` include support for some APIs.
@ -74,7 +77,8 @@ self.addEventListener('message', (e) => {
});
```
["User-Submitted File" example](/docs/demos/worker#user-submitted-file) has a live demo.
["User-Submitted File" example](/docs/demos/bigdata/worker#user-submitted-file)
includes a live demo.
</details>
@ -133,7 +137,8 @@ XLSX.writeFile(wb, "SheetJS.xlsx");
The workaround is to generate the file data from the Worker (using `XLSX.write`)
and send the data back to the main context for the actual download action.
["Creating a Local File" includes a live demo](/docs/demos/worker#creating-a-local-file).
["Creating a Local File"](/docs/demos/bigdata/worker#creating-a-local-file)
includes a live demo.
:::
@ -389,13 +394,13 @@ XLSX.writeFile(wb, "sheetjs.csv");
`readFile` uses `Deno.readFileSync` and `writeFile` uses `Deno.writeFileSync`:
```js
// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
const wb = XLSX.readFile("sheetjs.numbers");
XLSX.writeFile(wb, "sheetjs.xlsx");
```
<CodeBlock language="ts">{`\
// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
\n\
const wb: XLSX.WorkBook = XLSX.readFile("sheetjs.numbers");
XLSX.writeFile(wb, "sheetjs.xlsx");`}
</CodeBlock>
:::caution Deno entitlements

@ -136,12 +136,12 @@ cd SheetJSLambda
curl -LO https://docs.sheetjs.com/aws/index.js
```
2) Install dependencies to the current directory;
2) Install dependencies in the project directory;
```bash
<pre><code parentName="pre" {...{"className": "language-bash"}}>{`\
mkdir -p node_modules
npm install https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz busboy
```
npm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz busboy`}
</code></pre>
3) Create a .zip package of the contents of the folder:

@ -5,6 +5,7 @@ pagination_next: demos/extensions/index
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
Azure is a Cloud Services platform which includes traditional virtual machine
support, "Serverless Functions", cloud storage and much more.
@ -21,7 +22,7 @@ and the "Serverless Function" platform ("Azure Functions").
:::note
This was tested on 2022 August 21.
This was tested on 2023 April 29.
:::
@ -113,19 +114,18 @@ module.exports = (context, req) => {
### Demo
<details><summary><b>Complete Example</b> (click to show)</summary>
<details open><summary><b>Complete Example</b> (click to show)</summary>
0) Review the quick start for JavaScript on Azure Functions. This involves
installing the Azure Functions Core Tools and other dependencies.
1) Create a new project and install dependencies:
```bash
<CodeBlock language="bash">{`\
func init sheetjs-azure --worker-runtime node --language javascript
cd sheetjs-azure
npm i
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz formidable
```
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz formidable`}
</CodeBlock>
2) Create a new "HTTP Trigger" function:
@ -142,58 +142,10 @@ func new --template "Http Trigger" --name SheetJSAzure
"name": "req",
```
4) Replace `SheetJSAzure/index.js` with the following:
4) Download [`SheetJSAzure/index.js`](pathname:///aws/index.js):
```js title="SheetJSAzure/index.js"
/* sheetjs (C) 2013-present SheetJS -- https://sheetjs.com */
const XLSX = require('xlsx');
const formidable = require('formidable');
const Readable = require('stream').Readable;
/* formidable expects the request object to be a stream */
const streamify = (req) => {
if(typeof req.on !== 'undefined') return req;
const s = new Readable();
s._read = ()=>{};
s.push(Buffer.from(req.body));
s.push(null);
Object.assign(s, req);
return s;
};
module.exports = (context, req) => {
if(req.method == "POST") {
const form = new formidable.IncomingForm();
form.parse(streamify(req), (err, fields, files) => {
/* grab the first file */
var f = files["upload"];
if(!f) {
context.res = { status: 400, body: "Must submit a file for processing!" };
} else {
/* file is stored in a temp directory, so we can point to that and read it */
const wb = XLSX.read(f.filepath, {type:"file"});
/* generate CSV from first sheet */
const csv = XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);
context.res = { status: 200, body: csv };
}
context.done();
});
} else if(req.method == "GET") {
var ws = XLSX.utils.aoa_to_sheet(["SheetJS".split(""), [5,4,3,3,7,9,5]]);
var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Data");
var buf = XLSX.write(wb, {type: "buffer", bookType: "xlsx"});
context.res = {
status: 200,
headers: { "Content-Disposition": `attachment; filename="SheetJSAzure.xlsx";` },
body: buf
};
context.done();
} else {
context.res = { status: 500, body: `Unsupported method ${req.method}` };
context.done();
}
};
```bash
curl -L -o SheetJSAzure/index.js https://docs.sheetjs.com/azure/index.js
```
5) Test locally with `npm start`
@ -201,6 +153,7 @@ module.exports = (context, req) => {
To test uploads, download <https://sheetjs.com/pres.numbers> and run:
```bash
curl -LO https://sheetjs.com/pres.numbers
curl -X POST -F "upload=@pres.numbers" http://localhost:7071/api/SheetJSAzure
```

@ -141,8 +141,8 @@ for further processing.
:::note
For Chromium browsers, the File System Access API provides a modern worker-only
approach. [The Web Workers demo](/docs/demos/worker#streaming-write) includes a
live example of CSV streaming write.
approach. [The Web Workers demo](/docs/demos/bigdata/worker#streaming-write)
includes a live example of CSV streaming write.
:::
@ -255,8 +255,8 @@ strm.resume();
#### Web Workers
For processing large files in the browser, it is strongly encouraged to use Web
Workers. The [Worker demo](/docs/demos/worker#streaming-write) includes examples
using the File System Access API.
Workers. The [Worker demo](/docs/demos/bigdata/worker#streaming-write) includes
examples using the File System Access API.
Typically, the file and stream processing occurs in the Web Worker. CSV rows
can be sent back to the main thread in the callback:

@ -6,6 +6,9 @@ sidebar_custom_props:
summary: Run large data flows without freezing the browser
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
Parsing and writing large spreadsheets takes time. During the process, if the
SheetJS library is running in the web browser, the website may freeze.
@ -82,36 +85,36 @@ typically workers are written in separate JS files.
For example, an in-line worker like
```js
const worker = new Worker(URL.createObjectURL(new Blob([`\
<CodeBlock language="js">{`\
const worker = new Worker(URL.createObjectURL(new Blob([\`\\
/* load standalone script from CDN */
importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js");
importScripts("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js");
\n\
/* this callback will run once the main context sends a message */
self.addEventListener('message', (e) => {
/* Pass the version string back */
postMessage({ version: XLSX.version });
}, false);
`])));
```
\`])));`}
</CodeBlock>
would typically be stored in a separate JS file like "worker.js":
```js title="worker.js"
<CodeBlock language="js" title="worker.js">{`\
/* load standalone script from CDN */
importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js");
importScripts("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js");
\n\
/* this callback will run once the main context sends a message */
self.addEventListener('message', (e) => {
/* Pass the version string back */
postMessage({ version: XLSX.version });
}, false);
```
}, false);`}
</CodeBlock>
and the main script would pass a URL:
and the main script would pass a URL to the `Worker` constructor:
```js
const worker = new Worker("./worker.js");
const worker = new Worker("./worker.js");
```
</details>
@ -122,9 +125,9 @@ and the main script would pass a URL:
In all cases, `importScripts` in a Worker can load the [Standalone scripts](/docs/getting-started/installation/standalone)
```js
importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js");
```
<CodeBlock language="js">{`\
importScripts("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js");`}
</CodeBlock>
For production use, it is highly encouraged to download and host the script.
@ -141,9 +144,9 @@ For legacy browsers like Firefox and IE, `importScripts` should be used.
Browser ESM imports require a complete URL including the `.mjs` extension:
```js
import * as XLSX from "https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs";
```
<CodeBlock language="js">{`\
import * as XLSX from "https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs";`}
</CodeBlock>
When using Worker ESM, the Worker constructor must set the `type` option:

@ -245,8 +245,8 @@ document.getElementById('file-object').addEventListener("change", function(e) {
#### Browser is stuck!
By default, operations run in the main renderer context and block the browser
from updating. [Web Workers](/docs/demos/worker) offload the hard work to separate
contexts, freeing up the renderer to update.
from updating. [Web Workers](/docs/demos/bigdata/worker) offload the hard work
to separate contexts, freeing up the renderer to update.
#### Strange exported file names in the web browser

@ -0,0 +1,49 @@
/* sheetjs (C) SheetJS -- https://sheetjs.com */
const XLSX = require('xlsx');
const formidable = require('formidable');
const Readable = require('stream').Readable;
/* formidable expects the request object to be a stream */
const streamify = (req) => {
if(typeof req.on !== 'undefined') return req;
const s = new Readable();
s._read = ()=>{};
s.push(Buffer.from(req.body));
s.push(null);
Object.assign(s, req);
return s;
};
module.exports = (context, req) => {
if(req.method == "POST") {
const form = new formidable.IncomingForm();
form.parse(streamify(req), (err, fields, files) => {
/* grab the first file */
var f = files["upload"];
if(!f) {
context.res = { status: 400, body: "Must submit a file for processing!" };
} else {
/* file is stored in a temp directory, so we can point to that and read it */
const wb = XLSX.read(f.filepath, {type:"file"});
/* generate CSV from first sheet */
const csv = XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);
context.res = { status: 200, body: csv };
}
context.done();
});
} else if(req.method == "GET") {
var ws = XLSX.utils.aoa_to_sheet(["SheetJS".split(""), [5,4,3,3,7,9,5]]);
var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Data");
var buf = XLSX.write(wb, {type: "buffer", bookType: "xlsx"});
context.res = {
status: 200,
headers: { "Content-Disposition": `attachment; filename="SheetJSAzure.xlsx";` },
body: buf
};
context.done();
} else {
context.res = { status: 500, body: `Unsupported method ${req.method}` };
context.done();
}
};