diff --git a/docz/docs/03-demos/04-grid.md b/docz/docs/03-demos/04-grid.md
index 470030c..e65f544 100644
--- a/docz/docs/03-demos/04-grid.md
+++ b/docz/docs/03-demos/04-grid.md
@@ -202,7 +202,7 @@ many additional features including massive data streaming, sorting and styling.
### Tabulator
-[Tabulator](http://tabulator.info/docs/5.3/download#xlsx) includes deep support
+[Tabulator](https://tabulator.info/docs/5.4/download#xlsx) includes deep support
through a special Export button. It handles the SheetJS operations internally.
diff --git a/docz/docs/03-demos/07-worker.md b/docz/docs/03-demos/07-worker.md
index 5d1f50d..43aa263 100644
--- a/docz/docs/03-demos/07-worker.md
+++ b/docz/docs/03-demos/07-worker.md
@@ -100,7 +100,8 @@ In the following example, the script:
- generates a workbook object in the Web Worker
- generates a XLSB file using `XLSX.write` in the Web Worker
-- sends the file (`Uint8Array`) to the main browser context
+- generates an object URL in the Web Worker
+- sends the object URL to the main browser context
- performs a download action in the main browser context
```jsx live
@@ -124,11 +125,14 @@ SheetJS,in,Web,Workers
1,2,3,4\`;
const wb = XLSX.read(csv, { type: "string" });
- /* Write XLSB data */
+ /* Write XLSB data (Uint8Array) */
const u8 = XLSX.write(wb, { bookType: "xlsb", type: "buffer" });
+ /* Generate URL */
+ const url = URL.createObjectURL(new Blob([u8]));
+
/* Reply with result */
- postMessage({data: u8});
+ postMessage({ url });
} catch(e) {
/* Pass the error message back */
postMessage({error: String(e.message || e).bold() });
@@ -142,7 +146,7 @@ SheetJS,in,Web,Workers
/* this mantra is the standard HTML5 download attribute technique */
const a = document.createElement("a");
a.download = "SheetJSWriteFileWorker.xlsb";
- a.href = URL.createObjectURL(new Blob([e.data.data]));
+ a.href = e.data.url;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
@@ -176,10 +180,10 @@ In the following example, the script:
```jsx live
function SheetJSDragDropWorker() {
const [html, setHTML] = React.useState("");
- /* suppress default behavior for dragover and drop */
+ /* suppress default behavior for drag and drop */
function suppress(e) { e.stopPropagation(); e.preventDefault(); }
return ( <>
-
{
+
{
suppress(e);
/* this mantra embeds the worker source in the function */
@@ -188,7 +192,7 @@ function SheetJSDragDropWorker() {
importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js");
/* this callback will run once the main context sends a message */
-self.addEventListener('message', async(e) => {
+self.addEventListener('message', (e) => {
try {
/* Read file data */
const ab = new FileReaderSync().readAsArrayBuffer(e.data.file);
diff --git a/docz/docs/03-demos/33-localfile.md b/docz/docs/03-demos/33-localfile.md
index 6e11b9f..6f7004f 100644
--- a/docz/docs/03-demos/33-localfile.md
+++ b/docz/docs/03-demos/33-localfile.md
@@ -2,10 +2,11 @@
title: Local File Access
---
-Reading and writing files require native support. `readFile` and `writeFile`
-include support for some approaches but do not support every API. When an API
-is not supported by `readFile` or `writeFile`, the underlying `read` and
-`write` methods can be used.
+Reading and writing files require native platform support. `XLSX.readFile` and
+`XLSX.writeFile` include support for some APIs.
+
+For other APIs, user code can pass data to `XLSX.read` or use data generated by
+`XLSX.write` directly. Both methods work with a number of common storage types.
This demo looks at various web APIs. More specific approaches for deployments
like mobile apps are covered in their respective demos.
@@ -35,20 +36,63 @@ Modern browser APIs typically use typed arrays or `Blob` or `File` structures.
_Reading Binary Data_
-Given a `Blob` or `File`, the underlying data cannot be read synchronously!
+`XLSX.read` supports `Uint8Array` and `ArrayBuffer` data. For `Blob` or `File`
+objects, the underlying data must be pulled into an `ArrayBuffer`.
The callback-based approach uses a `FileReader`:
```js
-const reader = new FileReader();
-reader.onload = function(e) {
- /* e.target.result is an ArrayBuffer */
- const wb = XLSX.read(e.target.result);
- console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
+// usage: file_to_wb(file, function(wb) { /* wb is a workbook object */ });
+function file_to_wb(file, callback) {
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ /* e.target.result is an ArrayBuffer */
+ callback(XLSX.read(e.target.result));
+ };
+ reader.readAsArrayBuffer(file);
}
-reader.readAsArrayBuffer(file);
```
+FileReaderSync in Web Workers (click to show)
+
+`FileReaderSync` is only available in Web Workers:
+
+```js
+// assuming main thread called worker.postMessage({ file: file_object })
+self.addEventListener('message', (e) => {
+ /* get file object from message */
+ var file = e.data.file;
+ /* Read file data */
+ const ab = new FileReaderSync().readAsArrayBuffer(file);
+ /* Parse file */
+ const wb = XLSX.read(ab);
+ /* DO SOMETHING WITH wb HERE */
+});
+```
+
+["User-Submitted File" example](./worker#user-submitted-file) has a live demo.
+
+
+
+IE10 Binary Strings (click to show)
+
+In IE10, binary strings are more performant than `ArrayBuffer`. `XLSX.read`
+supports binary strings with `type: "binary"`:
+
+```js
+// usage: file_bs_to_wb(file, function(wb) { /* wb is a workbook object */ });
+function file_bs_to_wb(file, callback) {
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ /* e.target.result is a binary string */
+ callback(XLSX.read(e.target.result, { type: "binary" }));
+ };
+ reader.readAsBinaryString(file);
+}
+```
+
+
+
The Promise-based approach uses `Blob#arrayBuffer`:
```js
@@ -60,8 +104,9 @@ async function blob_to_wb(blob) {
_Writing Binary Data_
-`XLSX.write` can generate `Uint8Array` results by passing `type: "buffer"`. A
-`Blob` can be created by using the constructor:
+`XLSX.write` can generate `Uint8Array` results by passing `type: "buffer"`.
+
+A `Blob` can be created by using the constructor:
```js
const u8 = XLSX.write(workbook, { type: "buffer", bookType: "xlsx" });
@@ -78,6 +123,17 @@ _Writing Files_
XLSX.writeFile(wb, "SheetJS.xlsx");
```
+:::caution Web Workers
+
+`XLSX.writeFile` requires DOM access and will not work in a Web Worker!
+
+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](./worker#creating-a-local-file).
+
+:::
+
## File API
_Reading Files_
@@ -93,7 +149,7 @@ async function handleFileAsync(e) {
/* data is an ArrayBuffer */
const workbook = XLSX.read(data);
/* do something with the workbook here */
- console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]))
+ console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]));
}
input_dom_element.addEventListener("change", handleFileAsync, false);
```
@@ -105,8 +161,12 @@ _Reading Files_
The `dataTransfer` property of the `drop` event holds a list of files:
```js
+/* suppress default behavior for drag and drop events */
+function suppress(e) { e.stopPropagation(); e.preventDefault(); }
+
+/* handle data from drop event */
async function handleDropAsync(e) {
- e.stopPropagation(); e.preventDefault();
+ suppress(e);
/* get first file */
const f = e.dataTransfer.files[0];
/* get raw data */
@@ -114,9 +174,12 @@ async function handleDropAsync(e) {
/* data is an ArrayBuffer */
const wb = XLSX.read(data);
/* do something with the workbook here */
- console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]))
+ console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]));
}
+
drop_dom_element.addEventListener("drop", handleDropAsync, false);
+drop_dom_element.addEventListener("dragover", suppress, false);
+drop_dom_element.addEventListener("dragenter", suppress, false);
```
## File System Access API
@@ -128,6 +191,45 @@ the feature in version 86. Safari did not support File System Access API.
:::
+Live Example (click to show)
+
+This live example reads a file then tries to save as XLSX.
+
+```jsx live
+function SheetJSRoundTripFileSystemAPI() { return ( ) }
+```
+
+
+
_Reading Files_
`window.showOpenFilePicker` shows a file picker and resolves to an array of
@@ -182,47 +284,6 @@ wstream.write(XLSX.write(wb, { bookType: ext, type: "buffer" }))
wstream.close();
```
-### Demo
-
-Live Example (click to show)
-
-This live example reads a file then tries to save as XLSX.
-
-```jsx live
-function SheetJSRoundTripFileSystemAPI() { return ( ) }
-```
-
-
-
## File and Directory Entries API
:::caution Deprecated
@@ -263,7 +324,8 @@ Internet Explorer offered proprietary APIs that were not adopted by Chromium.
_Writing Files_
-IE10 and IE11 support `navigator.msSaveBlob`. `writeFile` will use the method.
+IE10 and IE11 support `navigator.msSaveBlob`. `XLSX.writeFile` will use this
+method if it is available.
#### VBScript
@@ -304,8 +366,8 @@ import { readFile, writeFile, set_fs } from 'xlsx';
import * as fs from 'fs';
set_fs(fs);
-var wb = XLSX.readFile("sheetjs.numbers");
-XLSX.writeFile(wb, "sheetjs.xlsx");
+var wb = readFile("sheetjs.numbers");
+writeFile(wb, "sheetjs.xlsx");
```
### ExtendScript
@@ -322,8 +384,7 @@ XLSX.writeFile(wb, "sheetjs.csv");
### Deno
-`Deno.readFileSync` and `Deno.writeFileSync` are supported by `readFile` and
-`writeFile` out of the box:
+`readFile` uses `Deno.readFileSync` and `writeFile` uses `Deno.writeFileSync`:
```js
// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts"
@@ -333,11 +394,11 @@ const wb = XLSX.readFile("sheetjs.numbers");
XLSX.writeFile(wb, "sheetjs.xlsx");
```
-:::note
+:::caution Deno entitlements
-Any script using `XLSX.readFile` requires the `--allow-read` permission.
+Any Deno script using `XLSX.readFile` requires the `--allow-read` entitlement.
-Any script using `XLSX.writeFile` requires the `--allow-write` permission.
+Any Deno script using `XLSX.writeFile` requires the `--allow-write` entitlement.
:::
@@ -346,12 +407,12 @@ Any script using `XLSX.writeFile` requires the `--allow-write` permission.
Bun requires the `fs` module:
```js
-import * as XLSX from 'xlsx';
+import { readFile, writeFile, set_fs } from 'xlsx';
import * as fs from 'fs';
-XLSX.set_fs(fs);
+set_fs(fs);
-var wb = XLSX.readFile("sheetjs.numbers");
-XLSX.writeFile(wb, "sheetjs.xlsx");
+var wb = readFile("sheetjs.numbers");
+writeFile(wb, "sheetjs.xlsx");
```
### Apps