2022-05-16 03:26:04 +00:00
|
|
|
---
|
|
|
|
sidebar_position: 5
|
|
|
|
---
|
|
|
|
|
|
|
|
# Data Export
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
import current from '/version.js';
|
|
|
|
import Tabs from '@theme/Tabs';
|
|
|
|
import TabItem from '@theme/TabItem';
|
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
## Writing Workbooks
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
### API
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
_Generate spreadsheet bytes (file) from data_
|
|
|
|
|
|
|
|
```js
|
|
|
|
var data = XLSX.write(workbook, opts);
|
|
|
|
```
|
|
|
|
|
|
|
|
The `write` method attempts to package data from the workbook into a file in
|
|
|
|
memory. By default, XLSX files are generated, but that can be controlled with
|
|
|
|
the `bookType` property of the `opts` argument. Based on the `type` option,
|
|
|
|
the data can be stored as a "binary string", JS string, `Uint8Array` or Buffer.
|
|
|
|
|
|
|
|
The second `opts` argument is required. ["Writing Options"](../api/write-options)
|
|
|
|
covers the supported properties and behaviors.
|
|
|
|
|
|
|
|
_Generate and attempt to save file_
|
|
|
|
|
|
|
|
```js
|
|
|
|
XLSX.writeFile(workbook, filename, opts);
|
|
|
|
```
|
|
|
|
|
|
|
|
The `writeFile` method packages the data and attempts to save the new file. The
|
|
|
|
export file format is determined by the extension of `filename` (`SheetJS.xlsx`
|
|
|
|
signals XLSX export, `SheetJS.xlsb` signals XLSB export, etc).
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
The second `opts` argument is optional. ["Writing Options"](../api/write-options)
|
|
|
|
covers the supported properties and behaviors.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
_Generate and attempt to save an XLSX file_
|
|
|
|
|
|
|
|
```js
|
|
|
|
XLSX.writeFileXLSX(workbook, filename, opts);
|
|
|
|
```
|
|
|
|
|
|
|
|
The `writeFile` method embeds a number of different export functions. This is
|
|
|
|
great for developer experience but not amenable to tree shaking using the
|
|
|
|
current developer tools. When only XLSX exports are needed, this method avoids
|
|
|
|
referencing the other export functions.
|
|
|
|
|
|
|
|
The second `opts` argument is optional. ["Writing Options"](../api/write-options)
|
|
|
|
covers the supported properties and behaviors.
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
:::note
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
The `writeFile` and `writeFileXLSX` methods uses platform-specific APIs to save
|
|
|
|
files. The APIs do not generally provide feedback on whether files were created.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
:::
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
#### Examples
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
Here are a few common scenarios (click on each subtitle to see the code).
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
The [demos](../getting-started/demos) cover special deployments in more detail.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
### Example: Local File
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
`XLSX.writeFile` supports writing local files in platforms like NodeJS. In other
|
|
|
|
platforms like React Native, `XLSX.write` should be called with file data.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
<Tabs>
|
|
|
|
<TabItem value="browser" label="Browser">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
`XLSX.writeFile` wraps a few techniques for triggering a file save:
|
|
|
|
|
|
|
|
- `URL` browser API creates an object URL for the file, which the library uses
|
|
|
|
by creating a link and forcing a click. It is supported in modern browsers.
|
|
|
|
- `msSaveBlob` is an IE10+ API for triggering a file save.
|
|
|
|
- `IE_FileSave` uses VBScript and ActiveX to write a file in IE6+ for Windows
|
|
|
|
XP and Windows 7. The shim must be included in the containing HTML page.
|
|
|
|
|
|
|
|
There is no standard way to determine if the actual file has been downloaded.
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* output format determined by filename */
|
|
|
|
XLSX.writeFile(workbook, "out.xlsb");
|
|
|
|
/* at this point, out.xlsb will have been downloaded */
|
|
|
|
```
|
|
|
|
|
2022-07-17 03:47:27 +00:00
|
|
|
:::caution Web Workers
|
|
|
|
|
|
|
|
None of the file writing APIs work from Web Workers. To generate a file:
|
|
|
|
|
|
|
|
1) use `XLSX.write` with type `array` to generate a `Uint8Array`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// in the web worker, generate the XLSX file as a Uint8Array
|
|
|
|
const u8 = XLSX.write(workbook, { type: "array", bookType: "xlsx" });
|
|
|
|
```
|
|
|
|
|
|
|
|
2) send the data back to the main thread:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// in the web worker, send the generated data back to the main thread
|
|
|
|
postMessage({t: "export", v: u8 });
|
|
|
|
```
|
|
|
|
|
|
|
|
3) from the main thread, add an event listener to write to file:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// in the main page
|
|
|
|
worker.addEventListener('message', function(e) {
|
|
|
|
if(e && e.data && e.data.t == "export") {
|
|
|
|
e.stopPropagation();
|
|
|
|
e.preventDefault();
|
|
|
|
// data will be the Uint8Array from the worker
|
|
|
|
const data = e.data.v;
|
|
|
|
|
|
|
|
var blob = new Blob([data], {type:"application/octet-stream"});
|
|
|
|
var url = URL.createObjectURL(blob);
|
|
|
|
var a = document.createElement("a");
|
|
|
|
a.download = "SheetJSXPort.xlsx";
|
|
|
|
a.href = url;
|
|
|
|
document.body.appendChild(a);
|
|
|
|
a.click();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
<details>
|
2022-06-21 12:26:53 +00:00
|
|
|
<summary><b>SWF workaround for Windows 95+</b> (click to show)</summary>
|
|
|
|
|
|
|
|
:::warning
|
|
|
|
|
|
|
|
Each moving part in this solution has been deprecated years ago:
|
|
|
|
|
|
|
|
- Adobe stopped supporting Flash Player at the end of 2020
|
|
|
|
- Microsoft stopped supporting IE8 in 2019 and stopped supporting IE9 in 2020
|
|
|
|
- `Downloadify` support ended in 2010 and `SWFObject` support ended in 2016
|
|
|
|
|
|
|
|
New projects should strongly consider requiring modern browsers. This info is
|
|
|
|
provided on an "as is" basis and there is no realistic way to provide support
|
|
|
|
given that every related vendor stopped providing support for their software.
|
|
|
|
|
|
|
|
:::
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
`XLSX.writeFile` techniques work for most modern browsers as well as older IE.
|
|
|
|
For much older browsers, there are workarounds implemented by wrapper libraries.
|
|
|
|
|
|
|
|
[`Downloadify`](https://github.com/dcneiner/downloadify) uses a Flash SWF button
|
|
|
|
to generate local files, suitable for environments where ActiveX is unavailable:
|
|
|
|
|
|
|
|
```js
|
|
|
|
Downloadify.create(id,{
|
|
|
|
/* other options are required! read the downloadify docs for more info */
|
|
|
|
filename: "test.xlsx",
|
|
|
|
data: function() { return XLSX.write(wb, {bookType:"xlsx", type:"base64"}); },
|
|
|
|
append: false,
|
|
|
|
dataType: "base64"
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
The [`oldie` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/oldie/) shows an IE-compatible fallback scenario.
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="nodejs" label="NodeJS">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
`writeFile` uses `fs.writeFileSync` under the hood:
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
```js
|
2022-06-21 12:26:53 +00:00
|
|
|
var XLSX = require("xlsx");
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
/* output format determined by filename */
|
|
|
|
XLSX.writeFile(workbook, "out.xlsb");
|
|
|
|
```
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
For Node ESM, `fs` must be loaded manually:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import * as fs from "fs";
|
|
|
|
import { writeFile, set_fs } from "xlsx/xlsx.mjs";
|
2022-07-23 09:06:31 +00:00
|
|
|
set_fs(fs);
|
|
|
|
|
|
|
|
/* output format determined by filename */
|
|
|
|
writeFile(workbook, "out.xlsb");
|
|
|
|
```
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
<TabItem value="bun" label="Bun">
|
|
|
|
|
|
|
|
As with Node ESM, `fs` must be loaded manually:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import * as fs from "fs";
|
|
|
|
import { writeFile, set_fs } from "xlsx/xlsx.mjs";
|
2022-06-21 12:26:53 +00:00
|
|
|
set_fs(fs);
|
|
|
|
|
|
|
|
/* output format determined by filename */
|
|
|
|
writeFile(workbook, "out.xlsb");
|
2022-05-16 03:26:04 +00:00
|
|
|
```
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="deno" label="Deno">
|
|
|
|
|
|
|
|
`writeFile` uses `Deno.writeFileSync` under the hood:
|
|
|
|
|
|
|
|
<pre><code parentName="pre" {...{"className": "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';
|
|
|
|
|
|
|
|
XLSX.writeFile(workbook, "test.xlsx");`}</code></pre>
|
|
|
|
|
2022-07-31 23:45:34 +00:00
|
|
|
:::note
|
|
|
|
|
|
|
|
Applications writing files must be invoked with the `--allow-write` flag.
|
|
|
|
|
|
|
|
:::
|
2022-06-21 12:26:53 +00:00
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
<TabItem value="electron" label="Electron">
|
|
|
|
|
|
|
|
`writeFile` can be used in the renderer process:
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* From the renderer process */
|
|
|
|
var XLSX = require("xlsx");
|
|
|
|
|
|
|
|
XLSX.writeFile(workbook, "out.xlsb");
|
|
|
|
```
|
|
|
|
|
|
|
|
Electron APIs have changed over time. The [`electron` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/electron/)
|
|
|
|
shows a complete example and details the required version-specific settings.
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
<TabItem value="reactnative" label="React Native">
|
|
|
|
|
|
|
|
:::caution
|
|
|
|
|
|
|
|
React Native does not provide a way to write files to the filesystem. A
|
|
|
|
separate third-party library must be used.
|
|
|
|
|
|
|
|
Since React Native internals change between releases, libraries may only work
|
|
|
|
with specific versions of React Native. Project documentation should be
|
|
|
|
consulted before picking a library.
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
The [`react` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/react) includes a sample React Native app.
|
|
|
|
|
|
|
|
The following libraries have been tested:
|
|
|
|
|
|
|
|
- [`react-native-file-access`](https://npm.im/react-native-file-access)
|
|
|
|
|
|
|
|
The `base64` encoding returns strings compatible with the `base64` type:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import * as XLSX from "xlsx";
|
|
|
|
import { Dirs, FileSystem } from "react-native-file-access";
|
|
|
|
const DDP = Dirs.DocumentDir + "/";
|
|
|
|
|
|
|
|
const b64 = XLSX.write(workbook, {type:'base64', bookType:"xlsx"});
|
|
|
|
/* b64 is a base64 string */
|
|
|
|
await FileSystem.writeFile(DDP + "sheetjs.xlsx", b64, "base64");
|
|
|
|
```
|
|
|
|
|
|
|
|
- [`react-native-fs`](https://npm.im/react-native-fs)
|
|
|
|
|
|
|
|
The `ascii` encoding accepts binary strings compatible with the `binary` type:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import * as XLSX from "xlsx";
|
|
|
|
import { writeFile, DocumentDirectoryPath } from "react-native-fs";
|
|
|
|
const DDP = DocumentDirectoryPath + "/";
|
|
|
|
|
|
|
|
const bstr = XLSX.write(workbook, {type:'binary', bookType:"xlsx"});
|
|
|
|
/* bstr is a binary string */
|
|
|
|
await writeFile(DDP + "sheetjs.xlsx", bstr, "ascii");
|
|
|
|
```
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
<TabItem value="extendscript" label="Photoshop">
|
|
|
|
|
|
|
|
`writeFile` wraps the `File` logic in Photoshop and other ExtendScript targets.
|
|
|
|
The specified path should be an absolute path:
|
|
|
|
|
|
|
|
```js
|
|
|
|
#include "xlsx.extendscript.js"
|
|
|
|
|
|
|
|
/* Ask user to select path */
|
|
|
|
var thisFile = File.saveDialog("Select an output file", "*.xlsx;*.xls");
|
|
|
|
/* output format determined by filename */
|
|
|
|
XLSX.writeFile(workbook, thisFile.absoluteURI);
|
|
|
|
```
|
|
|
|
|
|
|
|
The [`extendscript` demo](../getting-started/demos/extendscript) includes a more complex example.
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
<TabItem value="headless" label="Headless">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-07-07 04:05:14 +00:00
|
|
|
The [`headless` demo](../getting-started/demos/headless) includes complete
|
|
|
|
examples of converting HTML TABLE elements to XLSB workbooks using Puppeteer
|
|
|
|
and other headless automation tools.
|
|
|
|
|
|
|
|
Headless browsers may not have access to the filesystem, so `XLSX.writeFile`
|
|
|
|
may fail. It is strongly recommended to generate the file bytes in the browser
|
|
|
|
context, send the bytes to the automation context, and write from automation.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-07-07 04:05:14 +00:00
|
|
|
Puppeteer and Playwright are NodeJS modules that support binary strings:
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
```js
|
2022-07-07 04:05:14 +00:00
|
|
|
/* from the browser context */
|
|
|
|
var bin = XLSX.write(workbook, { type:"binary", bookType: "xlsb" });
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-07-07 04:05:14 +00:00
|
|
|
/* from the automation context */
|
|
|
|
fs.writeFileSync("SheetJSansHead.xlsb", bin, { encoding: "binary" });
|
2022-05-16 03:26:04 +00:00
|
|
|
```
|
|
|
|
|
2022-07-07 04:05:14 +00:00
|
|
|
PhantomJS `fs.write` supports writing files from the main process. The mode
|
|
|
|
`wb` supports binary strings:
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-07-07 04:05:14 +00:00
|
|
|
```js
|
|
|
|
/* from the browser context */
|
|
|
|
var bin = XLSX.write(workbook, { type:"binary", bookType: "xlsb" });
|
|
|
|
|
|
|
|
/* from the automation context */
|
|
|
|
fs.write("SheetJSansHead.xlsb", bin, "wb");
|
|
|
|
```
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
</Tabs>
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
|
2022-07-10 22:17:34 +00:00
|
|
|
### Example: Server Responses
|
|
|
|
|
|
|
|
This example focuses on responses to network requests in a server-side platform
|
|
|
|
like NodeJS. While files can be generated in the web browser, server-side file
|
|
|
|
generation allows for exact audit trails and has better mobile user support.
|
|
|
|
|
|
|
|
:::caution
|
|
|
|
|
|
|
|
Production deployments should use a server framework like ExpressJS. These
|
|
|
|
snippets use low-level APIs for illustration purposes.
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
The `Content-Type` header should be set to `application/vnd.ms-excel` for Excel
|
|
|
|
exports including XLSX. The default `application/octet-stream` can be used, but
|
|
|
|
iOS will not automatically suggest to open files in Numbers or Excel for iOS
|
|
|
|
|
|
|
|
The `Content-Disposition` header instructs browsers to download the response
|
|
|
|
into a file. The header can also include the desired file name.
|
|
|
|
|
|
|
|
<Tabs>
|
|
|
|
<TabItem value="nodejs" label="NodeJS">
|
|
|
|
|
|
|
|
NodeJS `http.ServerResponse#end` can accept `Buffer` objects. `XLSX.write` with
|
|
|
|
`buffer` type returns `Buffer` objects.
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* generate Buffer */
|
|
|
|
const buf = XLSX.write(wb, { type:"buffer", bookType:"xlsx" });
|
|
|
|
|
|
|
|
/* prepare response headers */
|
|
|
|
res.statusCode = 200;
|
|
|
|
res.setHeader('Content-Disposition', 'attachment; filename="SheetJSNode.xlsx"');
|
|
|
|
res.setHeader('Content-Type', 'application/vnd.ms-excel');
|
|
|
|
res.end(buf);
|
|
|
|
```
|
|
|
|
|
|
|
|
<details><summary><b>Complete Example</b> (click to show)</summary>
|
|
|
|
|
|
|
|
Install the library with
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm i https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
|
|
|
|
```
|
|
|
|
|
|
|
|
Save the following script to `node.js` and run with `node node.js`:
|
|
|
|
|
|
|
|
```js title="node.js"
|
|
|
|
const http = require('http');
|
|
|
|
const XLSX = require('xlsx');
|
|
|
|
|
|
|
|
const hostname = '127.0.0.1';
|
|
|
|
const port = 7262;
|
|
|
|
|
|
|
|
/* fixed sample worksheet */
|
|
|
|
const wb = XLSX.utils.book_new();
|
|
|
|
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([
|
|
|
|
["a","b","c"], [1,2,3]
|
|
|
|
]), "Sheet1");
|
|
|
|
|
|
|
|
const server = http.createServer((req, res) => {
|
|
|
|
const buf = XLSX.write(wb, { type:"buffer", bookType:"xlsx" });
|
|
|
|
res.statusCode = 200;
|
|
|
|
res.setHeader('Content-Disposition', 'attachment; filename="SheetJSNode.xlsx"');
|
|
|
|
res.setHeader('Content-Type', 'application/vnd.ms-excel');
|
|
|
|
res.end(buf);
|
|
|
|
});
|
|
|
|
|
|
|
|
server.listen(port, hostname, () => {
|
|
|
|
console.log(`Server running at http://${hostname}:${port}/`);
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
<TabItem value="deno" label="Deno">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
<TabItem value="bun" label="Bun">
|
|
|
|
|
|
|
|
Bun responses are expected to be `Response` objects. `XLSX.write` with `buffer`
|
|
|
|
type returns `Buffer` objects that can be used in the `Response` constructor.
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* generate Buffer */
|
|
|
|
const buf = XLSX.write(wb, { type:"buffer", bookType:"xlsx" });
|
|
|
|
/* return Response */
|
|
|
|
return new Response(buf, {
|
|
|
|
headers: {
|
|
|
|
"Content-Type": "application/vnd.ms-excel",
|
|
|
|
"Content-Disposition": 'attachment; filename="SheetJSBun.xlsx"'
|
|
|
|
}
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
<details><summary><b>Complete Example</b> (click to show)</summary>
|
|
|
|
|
|
|
|
Download [`xlsx.mjs`](https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs).
|
|
|
|
Save the following script to `bun.js` and run with `bun bun.js`. Open a web
|
|
|
|
browser and access <http://localhost:7262> to download the exported workbook.
|
|
|
|
|
|
|
|
```js title="bun.js"
|
|
|
|
import * as XLSX from "./xlsx.mjs";
|
|
|
|
|
|
|
|
/* fixed sample worksheet */
|
|
|
|
const wb = XLSX.utils.book_new();
|
|
|
|
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([
|
|
|
|
["a","b","c"], [1,2,3]
|
|
|
|
]), "Sheet1");
|
|
|
|
|
|
|
|
export default {
|
|
|
|
port: 7262,
|
|
|
|
fetch(request) {
|
|
|
|
/* generate Buffer */
|
|
|
|
const buf = XLSX.write(wb, {type:"buffer", bookType:"xlsx"});
|
|
|
|
/* return Response */
|
|
|
|
return new Response(buf, {
|
|
|
|
headers: {
|
|
|
|
"Content-Type": "application/vnd.ms-excel",
|
|
|
|
"Content-Disposition": 'attachment; filename="SheetJSBun.xlsx"'
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
};
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
2022-07-25 20:48:10 +00:00
|
|
|
</TabItem>
|
2022-07-10 22:17:34 +00:00
|
|
|
</Tabs>
|
|
|
|
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
### Example: Remote File
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
This example focuses on uploading files ("Ajax" in browser parlance) using APIs
|
|
|
|
like `XMLHttpRequest` and `fetch` as well as third-party libraries.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
<Tabs>
|
|
|
|
<TabItem value="browser" label="Browser">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
:::caution
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
Some platforms like Azure and AWS will attempt to parse POST request bodies as
|
|
|
|
UTF-8 strings before user code can see the data. This will result in corrupt
|
|
|
|
data parsed by the server. There are some workarounds, but the safest approach
|
|
|
|
is to adjust the server process or Lambda function to accept Base64 strings.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
:::
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
A complete example using XHR is [included in the XHR demo](https://github.com/SheetJS/SheetJS/tree/master/demos/xhr/), along
|
|
|
|
with examples for fetch and wrapper libraries. This example assumes the server
|
|
|
|
can handle Base64-encoded files (see the demo for a basic nodejs server):
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
```js
|
2022-06-21 12:26:53 +00:00
|
|
|
/* in this example, send a base64 string to the server */
|
|
|
|
var wbout = XLSX.write(workbook, { bookType: "xlsx", type: "base64" });
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
/* prepare data for POST */
|
|
|
|
var formdata = new FormData();
|
|
|
|
formdata.append("file", "test.xlsx"); // <-- server expects `file` to hold name
|
|
|
|
formdata.append("data", wbout); // <-- `data` holds the base64-encoded data
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
/* perform POST request */
|
|
|
|
var req = new XMLHttpRequest();
|
|
|
|
req.open("POST", "/upload", true);
|
|
|
|
req.send(formdata);
|
|
|
|
```
|
|
|
|
|
|
|
|
For servers that do not parse POST request bodies as UTF-8 strings, a `Blob` can
|
|
|
|
be generated from the `array` output:
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
```js
|
2022-06-21 12:26:53 +00:00
|
|
|
/* in this example, send a Blob to the server */
|
|
|
|
var wbout = XLSX.write(workbook, { bookType: "xlsx", type: "array" });
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
/* prepare data for POST */
|
|
|
|
var blob = new Blob([new Uint8Array(wbout)], {type:"application/octet-stream"});
|
|
|
|
var formdata = new FormData();
|
|
|
|
formdata.append("file", blob, "test.xlsx");
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
/* perform POST request */
|
|
|
|
fetch("/upload", { method: 'POST', body: formdata });
|
2022-05-16 03:26:04 +00:00
|
|
|
```
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="nodejs" label="NodeJS">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
`XLSX.write` with `type: "buffer"` will generate a NodeJS `Buffer` which can be
|
|
|
|
used with standard NodeJS approaches for uploading data.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
Node 17.5 and 18.0 have native support for fetch:
|
|
|
|
|
|
|
|
```js
|
|
|
|
const XLSX = require("xlsx");
|
|
|
|
|
|
|
|
const buf = XLSX.write(workbook, { bookType: "xlsx", type: "buffer" });
|
|
|
|
var blob = new Blob([buf], {type:"application/octet-stream"});
|
|
|
|
var formdata = new FormData();
|
|
|
|
formdata.append("file", blob, "test.xlsx");
|
|
|
|
|
|
|
|
/* perform POST request */
|
|
|
|
fetch("https://thisis.a.test/upload", { method: 'POST', body: formdata });
|
|
|
|
```
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
</Tabs>
|
|
|
|
|
|
|
|
## Generating JSON and JS Data
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
JSON and JS data tend to represent single worksheets. The utility functions in
|
|
|
|
this section work with single worksheets.
|
|
|
|
|
|
|
|
The ["Common Spreadsheet Format"](../csf/general) section describes
|
|
|
|
the object structure in more detail. `workbook.SheetNames` is an ordered list
|
|
|
|
of the worksheet names. `workbook.Sheets` is an object whose keys are sheet
|
|
|
|
names and whose values are worksheet objects.
|
|
|
|
|
|
|
|
The "first worksheet" is stored at `workbook.Sheets[workbook.SheetNames[0]]`.
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
### API
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
_Create an array of JS objects from a worksheet_
|
|
|
|
|
|
|
|
```js
|
|
|
|
var jsa = XLSX.utils.sheet_to_json(worksheet, opts);
|
|
|
|
```
|
|
|
|
|
|
|
|
_Create an array of arrays of JS values from a worksheet_
|
|
|
|
|
|
|
|
```js
|
|
|
|
var aoa = XLSX.utils.sheet_to_json(worksheet, {...opts, header: 1});
|
|
|
|
```
|
|
|
|
|
|
|
|
The `sheet_to_json` utility function walks a workbook in row-major order,
|
|
|
|
generating an array of objects. The second `opts` argument controls a number of
|
|
|
|
export decisions including the type of values (JS values or formatted text). The
|
|
|
|
["JSON"](../api/utilities#json) section describes the argument in more detail.
|
|
|
|
|
|
|
|
By default, `sheet_to_json` scans the first row and uses the values as headers.
|
|
|
|
With the `header: 1` option, the function exports an array of arrays of values.
|
|
|
|
|
|
|
|
#### Examples
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
### Example: Data Grids
|
|
|
|
|
|
|
|
<Tabs>
|
|
|
|
<TabItem value="js" label="Vanilla JS">
|
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
[`x-spreadsheet`](https://github.com/myliang/x-spreadsheet) is an interactive
|
|
|
|
data grid for previewing and modifying structured data in the web browser. The
|
2022-06-21 12:26:53 +00:00
|
|
|
[demo](https://github.com/SheetJS/SheetJS/tree/master/demos/xspreadsheet)
|
|
|
|
includes a sample script with the `stox` function for converting from
|
|
|
|
a workbook to x-spreadsheet. Live Demo: <https://oss.sheetjs.com/sheetjs/x-spreadsheet>
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="react" label="React">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-05-30 05:04:05 +00:00
|
|
|
[`react-data-grid`](https://adazzle.github.io/react-data-grid) is a data grid
|
|
|
|
built for React. It uses two properties: `rows` of data objects and `columns`
|
|
|
|
which describe the columns. For the purposes of massaging the data to fit the
|
|
|
|
`react-data-grid` API it is easiest to start from an array of arrays.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
This demo starts by fetching a remote file and using `XLSX.read` to extract:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
import DataGrid from "react-data-grid";
|
|
|
|
import { read, utils } from "xlsx";
|
|
|
|
|
|
|
|
const url = "https://oss.sheetjs.com/test_files/RkNumber.xls";
|
|
|
|
|
|
|
|
export default function App() {
|
|
|
|
const [columns, setColumns] = useState([]);
|
|
|
|
const [rows, setRows] = useState([]);
|
|
|
|
useEffect(() => {(async () => {
|
2022-06-21 12:26:53 +00:00
|
|
|
const wb = read(await (await fetch(url)).arrayBuffer());
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
/* use sheet_to_json with header: 1 to generate an array of arrays */
|
|
|
|
const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { header: 1 });
|
|
|
|
|
|
|
|
/* see react-data-grid docs to understand the shape of the expected data */
|
|
|
|
setColumns(data[0].map((r) => ({ key: r, name: r })));
|
|
|
|
setRows(data.slice(1).map((r) => r.reduce((acc, x, i) => {
|
|
|
|
acc[data[0][i]] = x;
|
|
|
|
return acc;
|
|
|
|
}, {})));
|
|
|
|
})(); });
|
|
|
|
|
|
|
|
return <DataGrid columns={columns} rows={rows} />;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="vue" label="VueJS">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-05-30 05:04:05 +00:00
|
|
|
[`vue3-table-lite`](https://linmasahiro.github.io/vue3-table-lite/dist/) is a
|
|
|
|
simple VueJS 3 data table. It is featured in the
|
|
|
|
[VueJS demo](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/modify/).
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
</Tabs>
|
|
|
|
|
|
|
|
### Example: Data Loading
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-07-08 00:04:16 +00:00
|
|
|
["Typed Arrays and ML"](../getting-started/demos/ml) covers strategies for
|
|
|
|
generating typed arrays and tensors from worksheet data.
|
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Populating a database (SQL or no-SQL)</b> (click to show)</summary>
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
The [`database` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/database/)
|
|
|
|
includes examples of working with databases and query results.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
## Generating HTML Tables
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
#### API
|
|
|
|
|
|
|
|
_Generate HTML Table from Worksheet_
|
|
|
|
|
|
|
|
```js
|
|
|
|
var html = XLSX.utils.sheet_to_html(worksheet);
|
|
|
|
```
|
|
|
|
|
|
|
|
The `sheet_to_html` utility function generates HTML code based on the worksheet
|
|
|
|
data. Each cell in the worksheet is mapped to a `<TD>` element. Merged cells
|
|
|
|
in the worksheet are serialized by setting `colspan` and `rowspan` attributes.
|
|
|
|
|
|
|
|
#### Examples
|
|
|
|
|
|
|
|
The `sheet_to_html` utility function generates HTML code that can be added to
|
|
|
|
any DOM element by setting the `innerHTML`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
var container = document.getElementById("tavolo");
|
|
|
|
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
|
|
|
|
```
|
|
|
|
|
|
|
|
Combining with `fetch`, constructing a site from a workbook is straightforward:
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
<Tabs>
|
|
|
|
<TabItem value="js" label="Vanilla JS">
|
|
|
|
|
|
|
|
This example assigns the `innerHTML` of a DIV element:
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
```html
|
|
|
|
<body>
|
|
|
|
<style>TABLE { border-collapse: collapse; } TD { border: 1px solid; }</style>
|
|
|
|
<div id="tavolo"></div>
|
|
|
|
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
|
|
(async() => {
|
|
|
|
/* fetch and parse workbook -- see the fetch example for details */
|
|
|
|
const workbook = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
|
|
|
|
|
|
|
|
let output = [];
|
|
|
|
/* loop through the worksheet names in order */
|
|
|
|
workbook.SheetNames.forEach(name => {
|
|
|
|
|
|
|
|
/* generate HTML from the corresponding worksheets */
|
|
|
|
const worksheet = workbook.Sheets[name];
|
|
|
|
const html = XLSX.utils.sheet_to_html(worksheet);
|
|
|
|
|
|
|
|
/* add a header with the title name followed by the table */
|
|
|
|
output.push(`<H3>${name}</H3>${html}`);
|
|
|
|
});
|
|
|
|
/* write to the DOM at the end */
|
|
|
|
tavolo.innerHTML = output.join("\n");
|
|
|
|
})();
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
```
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="react" label="React">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
It is generally recommended to use a React-friendly workflow, but it is possible
|
|
|
|
to generate HTML and use it in React with `dangerouslySetInnerHTML`:
|
|
|
|
|
|
|
|
```jsx
|
2022-06-21 12:26:53 +00:00
|
|
|
import * as XLSX from 'xlsx';
|
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
function Tabeller(props) {
|
|
|
|
/* the workbook object is the state */
|
|
|
|
const [workbook, setWorkbook] = React.useState(XLSX.utils.book_new());
|
|
|
|
|
|
|
|
/* fetch and update the workbook with an effect */
|
|
|
|
React.useEffect(() => { (async() => {
|
|
|
|
/* fetch and parse workbook -- see the fetch example for details */
|
|
|
|
const wb = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
|
|
|
|
setWorkbook(wb);
|
|
|
|
})(); });
|
|
|
|
|
|
|
|
return workbook.SheetNames.map(name => (<>
|
|
|
|
<h3>name</h3>
|
|
|
|
<div dangerouslySetInnerHTML={{
|
|
|
|
/* this __html mantra is needed to set the inner HTML */
|
|
|
|
__html: XLSX.utils.sheet_to_html(workbook.Sheets[name])
|
|
|
|
}} />
|
|
|
|
</>));
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The [`react` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/react) includes more React examples.
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="vue" label="VueJS">
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
It is generally recommended to use a VueJS-friendly workflow, but it is possible
|
|
|
|
to generate HTML and use it in VueJS with the `v-html` directive:
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
import { read, utils } from 'xlsx';
|
|
|
|
import { reactive } from 'vue';
|
|
|
|
|
|
|
|
const S5SComponent = {
|
|
|
|
mounted() { (async() => {
|
|
|
|
/* fetch and parse workbook -- see the fetch example for details */
|
|
|
|
const workbook = read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
|
|
|
|
/* loop through the worksheet names in order */
|
|
|
|
workbook.SheetNames.forEach(name => {
|
|
|
|
/* generate HTML from the corresponding worksheets */
|
|
|
|
const html = utils.sheet_to_html(workbook.Sheets[name]);
|
|
|
|
/* add to state */
|
|
|
|
this.wb.wb.push({ name, html });
|
|
|
|
});
|
|
|
|
})(); },
|
|
|
|
/* this state mantra is required for array updates to work */
|
|
|
|
setup() { return { wb: reactive({ wb: [] }) }; },
|
|
|
|
template: `
|
|
|
|
<div v-for="ws in wb.wb" :key="ws.name">
|
|
|
|
<h3>{{ ws.name }}</h3>
|
|
|
|
<div v-html="ws.html"></div>
|
|
|
|
</div>`
|
|
|
|
};
|
|
|
|
```
|
|
|
|
|
|
|
|
The [`vuejs` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/vue) includes more React examples.
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
</TabItem>
|
|
|
|
</Tabs>
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
## Generating Single-Worksheet Snapshots
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
The `sheet_to_*` functions accept a worksheet object.
|
|
|
|
|
|
|
|
#### API
|
|
|
|
|
|
|
|
_Generate a CSV from a single worksheet_
|
|
|
|
|
|
|
|
```js
|
|
|
|
var csv = XLSX.utils.sheet_to_csv(worksheet, opts);
|
|
|
|
```
|
|
|
|
|
|
|
|
This snapshot is designed to replicate the "CSV UTF8 (`.csv`)" output type.
|
|
|
|
["Delimiter-Separated Output"](../api/utilities#delimiter-separated-output) describes the
|
|
|
|
function and the optional `opts` argument in more detail.
|
|
|
|
|
|
|
|
_Generate "Text" from a single worksheet_
|
|
|
|
|
|
|
|
```js
|
|
|
|
var txt = XLSX.utils.sheet_to_txt(worksheet, opts);
|
|
|
|
```
|
|
|
|
|
|
|
|
This snapshot is designed to replicate the "UTF16 Text (`.txt`)" output type.
|
|
|
|
["Delimiter-Separated Output"](../api/utilities#delimiter-separated-output) describes the
|
|
|
|
function and the optional `opts` argument in more detail.
|
|
|
|
|
|
|
|
_Generate a list of formulae from a single worksheet_
|
|
|
|
|
|
|
|
```js
|
|
|
|
var fmla = XLSX.utils.sheet_to_formulae(worksheet);
|
|
|
|
```
|
|
|
|
|
|
|
|
This snapshot generates an array of entries representing the embedded formulae.
|
|
|
|
Array formulae are rendered in the form `range=formula` while plain cells are
|
|
|
|
rendered in the form `cell=formula or value`. String literals are prefixed with
|
|
|
|
an apostrophe `'`, consistent with Excel's formula bar display.
|
|
|
|
|
|
|
|
["Formulae Output"](../api/utilities#formulae-output) describes the function in more detail.
|
2022-06-21 12:26:53 +00:00
|
|
|
|
|
|
|
## Streaming Write
|
|
|
|
|
|
|
|
The streaming write functions are available in the `XLSX.stream` object. They
|
|
|
|
take the same arguments as the normal write functions but return a NodeJS
|
|
|
|
Readable Stream.
|
|
|
|
|
|
|
|
- `XLSX.stream.to_csv` is the streaming version of `XLSX.utils.sheet_to_csv`.
|
|
|
|
- `XLSX.stream.to_html` is the streaming version of `XLSX.utils.sheet_to_html`.
|
|
|
|
- `XLSX.stream.to_json` is the streaming version of `XLSX.utils.sheet_to_json`.
|
|
|
|
|
2022-07-31 23:45:34 +00:00
|
|
|
<Tabs>
|
|
|
|
<TabItem value="nodejs" label="NodeJS">
|
|
|
|
|
|
|
|
In a CommonJS context, NodeJS Streams immediately work with SheetJS. This
|
|
|
|
example reads a worksheet passed as an argument to the script, pulls the first
|
|
|
|
worksheet, converts to CSV and writes to `out.csv`:
|
2022-06-21 12:26:53 +00:00
|
|
|
|
|
|
|
```js
|
2022-07-31 23:45:34 +00:00
|
|
|
const XLSX = require("xlsx");
|
|
|
|
|
|
|
|
const workbook = XLSX.readFile(process.argv[2]);
|
|
|
|
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
|
|
|
|
// highlight-next-line
|
|
|
|
const stream = XLSX.stream.to_csv(worksheet);
|
|
|
|
|
|
|
|
const output_file_name = "out.csv";
|
|
|
|
// highlight-next-line
|
2022-06-21 12:26:53 +00:00
|
|
|
stream.pipe(fs.createWriteStream(output_file_name));
|
|
|
|
```
|
|
|
|
|
2022-07-31 23:45:34 +00:00
|
|
|
`stream.to_json` uses Object-mode streams. A `Transform` stream can be used to
|
|
|
|
generate a normal stream for streaming to a file or the screen:
|
2022-06-21 12:26:53 +00:00
|
|
|
|
|
|
|
```js
|
|
|
|
/* to_json returns an object-mode stream */
|
2022-07-31 23:45:34 +00:00
|
|
|
// highlight-next-line
|
2022-06-21 12:26:53 +00:00
|
|
|
var stream = XLSX.stream.to_json(worksheet, {raw:true});
|
|
|
|
|
2022-07-31 23:45:34 +00:00
|
|
|
/* this Transform stream converts JS objects to text and prints to screen */
|
2022-06-21 12:26:53 +00:00
|
|
|
var conv = new Transform({writableObjectMode:true});
|
|
|
|
conv._transform = function(obj, e, cb){ cb(null, JSON.stringify(obj) + "\n"); };
|
2022-07-31 23:45:34 +00:00
|
|
|
conv.pipe(process.stdout);
|
2022-06-21 12:26:53 +00:00
|
|
|
|
2022-07-31 23:45:34 +00:00
|
|
|
// highlight-next-line
|
|
|
|
stream.pipe(conv);
|
2022-06-21 12:26:53 +00:00
|
|
|
```
|
|
|
|
|
2022-07-31 23:45:34 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="deno" label="Deno">
|
|
|
|
|
|
|
|
Deno does not support NodeJS streams in normal execution, so a wrapper is used.
|
|
|
|
This demo converts a worksheet to CSV and prints each row to the screen:
|
|
|
|
|
|
|
|
```ts
|
|
|
|
// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts"
|
|
|
|
import {utils, stream, set_cptable} from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
|
|
|
|
|
|
|
|
/* `Readable` will be compatible with how SheetJS uses `stream.Readable` */
|
|
|
|
function NodeReadableCB(cb:(d:any)=>void) {
|
|
|
|
var rd = {
|
|
|
|
__done: false,
|
|
|
|
_read: function() {},
|
|
|
|
push: function(d: any) { if(!this.__done) cb(d); if(d == null) this.__done = true; },
|
|
|
|
resume: function pump() {for(var i = 0; i < 10000 && !this.__done; ++i) rd._read(); if(!rd.__done) setTimeout(pump, 0); }
|
|
|
|
};
|
|
|
|
return rd;
|
|
|
|
}
|
|
|
|
function NodeReadable(rd: any) { return function() { return rd; }; }
|
|
|
|
/* The callback gets each CSV row. It will be `null` when the stream is drained */
|
|
|
|
const rt = NodeReadableCB((d: any) => { if(d != null) console.log(d); });
|
|
|
|
const Readable = NodeReadable(rt);
|
|
|
|
stream.set_readable(Readable);
|
|
|
|
|
|
|
|
/* wire up and start the stream */
|
|
|
|
const rd = stream.to_csv(worksheet);
|
|
|
|
rd.resume();
|
|
|
|
```
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
</Tabs>
|
|
|
|
|
2022-06-21 12:26:53 +00:00
|
|
|
|
|
|
|
<https://github.com/sheetjs/sheetaki> pipes write streams to nodejs response.
|