This commit is contained in:
SheetJS 2022-08-24 19:48:22 -04:00
parent 734f70e6d9
commit 4c92216ebe
15 changed files with 278 additions and 39 deletions

@ -1,4 +1,6 @@
---
pagination_prev: getting-started/index
pagination_next: getting-started/example
sidebar_position: 1
sidebar_custom_props:
summary: Classic pages with simple <script> tags

@ -1,4 +1,6 @@
---
pagination_prev: getting-started/index
pagination_next: getting-started/example
sidebar_position: 2
sidebar_custom_props:
summary: Angular, React, VueJS, Webpack, etc.

@ -1,4 +1,6 @@
---
pagination_prev: getting-started/index
pagination_next: getting-started/example
sidebar_position: 3
sidebar_custom_props:
summary: Import ECMAScript Modules and TypeScript definitions

@ -1,4 +1,6 @@
---
pagination_prev: getting-started/index
pagination_next: getting-started/example
sidebar_position: 4
sidebar_custom_props:
summary: Server-side and other frameworks using NodeJS modules

@ -1,4 +1,6 @@
---
pagination_prev: getting-started/index
pagination_next: getting-started/example
sidebar_position: 5
sidebar_custom_props:
summary: Photoshop, InDesign, and other Creative Cloud apps

@ -1,4 +1,6 @@
---
pagination_prev: getting-started/index
pagination_next: getting-started/example
sidebar_position: 6
sidebar_custom_props:
summary: NetSuite, SAP UI5, RequireJS

@ -1,4 +1,6 @@
---
pagination_prev: getting-started/index
pagination_next: getting-started/example
sidebar_position: 7
sidebar_custom_props:
summary: Download and Import ECMAScript Modules

@ -1,4 +1,5 @@
---
pagination_prev: getting-started/index
sidebar_position: 2
---

@ -1,5 +1,6 @@
---
hide_table_of_contents: true
pagination_next: getting-started/example
---
# Getting Started

@ -27,12 +27,6 @@ suitable for a number of libraries. When more advanced shapes are needed,
it is easier to munge the output of an array of arrays.
### Tabulator
[Tabulator](http://tabulator.info/docs/5.3/download#xlsx) includes deep support
through a special Export button. It handles the SheetJS-related operations.
### x-spreadsheet
With a familiar UI, [`x-spreadsheet`](https://myliang.github.io/x-spreadsheet/)
@ -206,6 +200,13 @@ many additional features including massive data streaming, sorting and styling.
</details>
### Tabulator
[Tabulator](http://tabulator.info/docs/5.3/download#xlsx) includes deep support
through a special Export button. It handles the SheetJS-related operations.
### Angular UI Grid
:::warning

@ -414,4 +414,144 @@ The response should show the data in CSV rows.
It should prompt to download `SheetJSNest.xlsx`
</details>
</details>
### Fastify
:::note
This demo was verified on 2022 August 24 using `fastify@4.5.2`
:::
_Reading Data_
`@fastify/multipart`, which uses `busbuy` under the hood, can be registered:
```js
/* load SheetJS Library */
const XLSX = require("xlsx");
/* load fastify and enable body parsing */
const fastify = require('fastify')({logger: true});
// highlight-next-line
fastify.register(require('@fastify/multipart'), { attachFieldsToBody: true });
```
Once registered with the option `attachFieldsToBody`, route handlers can use
`req.body` directly:
```js
/* POST / reads submitted file and exports to requested format */
fastify.post('/', async(req, reply) => {
/* "file" is the name of the field in the HTML form*/
const file = req.body.upload;
/* toBuffer returns a promise that resolves to a Buffer */
// highlight-next-line
const buf = await file.toBuffer();
/* `XLSX.read` can read the Buffer */
const wb = XLSX.read(buf);
/* reply with a CSV */
reply.send(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
});
```
:::caution
Out of the box, Fastify will return an error `FST_ERR_CTP_BODY_TOO_LARGE` when
processing large spreadsheets (`statusCode 413`). This is a Fastify issue.
[`bodyLimit`](https://www.fastify.io/docs/latest/Reference/Server/#bodylimit)
in the docs explains the setting. It can be overridden during server creation:
```js
/* increase request body size limit to 5MB = 5 * 1024 * 1024 bytes */
const fastify = require('fastify')({bodyLimit: 5 * 1024 * 1024});
```
:::
_Writing Data_
The `Content-Disposition` header must be set manually:
```js
/* GET / returns a workbook */
fastify.get('/', (req, reply) => {
/* make a workbook */
var wb = XLSX.read("S,h,e,e,t,J,S\n5,4,3,3,7,9,5", {type: "binary"});
/* write to Buffer */
const buf = XLSX.write(wb, {type:"buffer", bookType: "xlsx"});
/* set Content-Disposition header and send data */
// highlight-next-line
reply.header('Content-Disposition', 'attachment; filename="SheetJSFastify.xlsx"').send(buf);
});
```
<details><summary><b>Testing</b> (click to show)</summary>
0) Save the following snippet to `SheetJSFastify.js`:
```js
/* load SheetJS Library */
const XLSX = require("xlsx");
/* load fastify and enable body parsing */
const fastify = require('fastify')({logger: true});
fastify.register(require('@fastify/multipart'), { attachFieldsToBody: true });
/* GET / returns a workbook */
fastify.get('/', (req, reply) => {
/* make a workbook */
var wb = XLSX.read("S,h,e,e,t,J,S\n5,4,3,3,7,9,5", {type: "binary"});
/* write to Buffer */
const buf = XLSX.write(wb, {type:"buffer", bookType: "xlsx"});
/* set Content-Disposition header and send data */
reply.header('Content-Disposition', 'attachment; filename="SheetJSFastify.xlsx"').send(buf);
});
/* POST / reads submitted file and exports to requested format */
fastify.post('/', async(req, reply) => {
/* "file" is the name of the field in the HTML form*/
const file = req.body.upload;
/* toBuffer returns a promise that resolves to a Buffer */
const wb = XLSX.read(await file.toBuffer());
/* send back a CSV */
reply.send(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
});
/* start */
fastify.listen({port: process.env.PORT || 3000}, (err, addr) => { if(err) throw err; });
```
1) Install dependencies:
```bash
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz fastify @fastify/multipart
```
2) Start server
```bash
node SheetJSFastify.js
```
3) Test POST requests using <https://sheetjs.com/pres.numbers>:
```bash
curl -LO https://sheetjs.com/pres.numbers
curl -X POST -F upload=@pres.numbers http://localhost:3000/
```
The response should show the data in CSV rows.
4) Test GET requests by opening http://localhost:3000/ in your browser.
It should prompt to download `SheetJSFastify.xlsx`
</details>

@ -1,4 +1,5 @@
---
pagination_prev: getting-started/index
sidebar_position: 1
hide_table_of_contents: true
---
@ -19,7 +20,7 @@ The demo projects include small runnable examples and short explainers.
### Frameworks
- [`Angular 2+ and Ionic`](./angular)
- [`Angular`](./angular)
- [`React`](./react)
- [`VueJS`](./vue)
- [`Angular.JS`](./legacy#angularjs)

@ -8,9 +8,57 @@ The ["Common Spreadsheet Format"](../csf/general) is a simple object
representation of the core concepts of a workbook. The utility functions work
with the object representation and are intended to handle common use cases.
## Modifying Workbook Structure
The [Data Input](./input) and [Data Output](./output) sections cover how to
read from data sources and write to data sources.
#### API
## Workbook
### Worksheets
:::note
Worksheet names are case-sensitive.
:::
_List the Worksheet names in tab order_
```js
var wsnames = workbook.SheetNames;
```
The `SheetNames` property of the workbook object is a list of the worksheet
names in "tab order". API functions will look at this array.
_Access a Worksheet by name_
```js
var worksheet = workbook.Sheets[sheet_name];
```
The workbook object's `Sheets` property is an object whose keys are sheet names
and whose values are worksheet objects.
_Access the first Worksheet_
```js
var first_ws = workbook.Sheets[workbook.SheetNames[0]];
```
Combining the previous examples, `workbook.Sheets[workbook.SheetNames[n]]` is
the `n`-th worksheet if it exists in the workbook.
_Replace a Worksheet in place_
```js
workbook.Sheets[sheet_name] = new_worksheet;
```
The `Sheets` property of the workbook object is an object whose keys are names
and whose values are worksheet objects. By reassigning to a property of the
`Sheets` object, the worksheet object can be changed without disrupting the
rest of the worksheet structure.
_Append a Worksheet to a Workbook_
@ -40,30 +88,8 @@ XLSX.utils.book_append_sheet(workbook, sheetC, "Sheet2", true); // Sheet4
XLSX.utils.book_append_sheet(workbook, sheetD, "Sheet2", true); // Sheet5
```
_List the Worksheet names in tab order_
```js
var wsnames = workbook.SheetNames;
```
The `SheetNames` property of the workbook object is a list of the worksheet
names in "tab order". API functions will look at this array.
_Replace a Worksheet in place_
```js
workbook.Sheets[sheet_name] = new_worksheet;
```
The `Sheets` property of the workbook object is an object whose keys are names
and whose values are worksheet objects. By reassigning to a property of the
`Sheets` object, the worksheet object can be changed without disrupting the
rest of the worksheet structure.
#### Examples
This example uses [`XLSX.utils.aoa_to_sheet`](../api/utilities#array-of-arrays-input).
```js
var ws_name = "SheetJS";
@ -74,21 +100,53 @@ var ws_data = [
];
var ws = XLSX.utils.aoa_to_sheet(ws_data);
/* Create workbook */
var wb = XLSX.utils.book_new();
/* Add the worksheet to the workbook */
// highlight-next-line
XLSX.utils.book_append_sheet(wb, ws, ws_name);
/* Write to file */
XLSX.writeFile(wb, "SheetJS.xlsx");
```
## Modifying Cell Values
### Other Properties
#### API
_Add a Defined Name_
_Modify a single cell value in a worksheet_
```js
if(!workbook.Workbook) workbook.Workbook = {};
if(!workbook.Workbook.Names) workbook.Workbook.Names = [];
workbook.Workbook.Names.push({
Name: "SourceData",
Ref: "Sheet1!A1:D12"
});
```
This is described in more detail in ["Workbook Object"](../csf/book#defined-names).
_Set Workbook Properties_
```js
if(!wb.Props) wb.Props = {};
wb.Props["Company"] = "SheetJS LLC";
```
The full set of property names, and their mapping to the Excel UI, is included
in ["File Properties"](../csf/book#file-properties)
## Worksheet
### Cells
_Modify a single cell value in a Worksheet_
```js
XLSX.utils.sheet_add_aoa(worksheet, [[new_value]], { origin: address });
```
_Modify multiple cell values in a worksheet_
_Modify multiple cell values in a Worksheet_
```js
XLSX.utils.sheet_add_aoa(worksheet, aoa, opts);
@ -122,8 +180,29 @@ XLSX.utils.sheet_add_aoa(worksheet, [
], { origin: -1 });
```
## Modifying Other Worksheet / Workbook / Cell Properties
### Other Properties
The ["Common Spreadsheet Format"](../csf/general) section describes
the object structures in greater detail.
_Merge a group of cells_
```js
if(!worksheet["!merges"]) worksheet["!merges"] = [];
worksheet["!merges"].push(XLSX.utils.decode_range("A1:E1"));
```
The `!merges` property of a worksheet object is a list of [Cell Ranges](../csf/general#cell-ranges).
The data for the cell will be taken from the top-left cell.
A range can be created with `decode_range` or specified manually:
```js
worksheet["!merges"].push({
s: { r: 2, c: 1 }, // s ("start"): c = 1 r = 2 -> "B3"
e: { r: 3, c: 4 } // e ("end"): c = 4 r = 3 -> "E4"
});
```
:::caution
This approach does not verify if two merged ranges intersect.
:::

@ -1,4 +1,5 @@
---
pagination_next: api/index
hide_table_of_contents: true
title: Common Spreadsheet Format
---

@ -1,4 +1,5 @@
---
pagination_prev: csf/index
sidebar_position: 5
title: API Reference
---