docs.sheetjs.com/docz/docs/06-solutions/05-output.md

925 lines
28 KiB
Markdown
Raw Normal View History

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");
```
2022-08-04 03:00:20 +00:00
Electron APIs have changed over time. The [`electron` demo](../getting-started/demos/desktop#electron)
2022-06-21 12:26:53 +00:00
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)
2022-08-06 22:59:58 +00:00
The `base64` encoding accepts Base64 strings compatible with the `binary` type:
2022-06-21 12:26:53 +00:00
```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");
2022-08-06 22:59:58 +00:00
```
- [`expo-file-system`](https://www.npmjs.com/package/expo-file-system)
The `FileSystem.EncodingType.Base64` encoding accepts Base64 strings:
```js
import * as XLSX from "xlsx";
import * as FileSystem from 'expo-file-system';
const DDP = FileSystem.documentDirectory;
const b64 = XLSX.write(workbook, {type:'base64', bookType:"xlsx"});
/* b64 is a base64 string */
await FileSystem.writeAsStringAsync(DDP + "sheetjs.xlsx", b64, { encoding: FileSystem.EncodingType.Base64 });
2022-06-21 12:26:53 +00:00
```
</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-08-05 05:10:11 +00:00
A complete example using XHR is [included in the XHR demo](../getting-started/demos/network), along
2022-06-21 12:26:53 +00:00
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) {
2022-08-08 06:59:57 +00:00
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;
2022-07-31 23:45:34 +00:00
}
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.