This commit is contained in:
SheetJS 2023-06-14 15:32:34 -04:00
parent 21e8d777ed
commit efc57df123
7 changed files with 296 additions and 58 deletions

@ -7,17 +7,22 @@ sidebar_custom_props:
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
# Frameworks and Bundlers
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Each standalone release package is available at <https://cdn.sheetjs.com/>. The
NodeJS package is designed to be used with frameworks and bundlers. It is a
proper ECMAScript Module release which can be optimized with developer tools.
<p><a href={`https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}>https://cdn.sheetjs.com/xlsx-{current}/xlsx-{current}.tgz</a> is the URL for version {current}</p>
## Installation
Tarballs can be directly installed using a package manager:
<Tabs groupId="pm">
<TabItem value="npm" label="npm">
<CodeBlock language="bash">{`\
@ -42,8 +47,7 @@ Once installed, the library can be imported under the name `xlsx`:
import { read, writeFileXLSX } from "xlsx";
```
The ["Bundlers" demo](/docs/demos/bundler) includes examples for specific
bundler tools.
The ["Bundlers" demo](/docs/demos/bundler) includes examples for specific tools.
:::info
@ -100,6 +104,62 @@ in `package.json` can control module resolution:
:::
### Vendoring
For general stability, "vendoring" modules is the recommended approach:
<p>1) Download the tarball (<code parentName="pre">xlsx-{current}.tgz</code>) for the desired version. The current
version is available at <a href={`https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}>https://cdn.sheetjs.com/xlsx-{current}/xlsx-{current}.tgz</a></p>
2) Create a `vendor` subfolder at the root of your project and move the tarball
to that folder. Add it to your project repository.
3) Install the tarball using a package manager:
<Tabs groupId="pm">
<TabItem value="npm" label="npm">
<CodeBlock language="bash">{`\
npm i --save file:vendor/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="pnpm" label="pnpm">
<CodeBlock language="bash">{`\
pnpm install file:vendor/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="yarn" label="Yarn" default>
<CodeBlock language="bash">{`\
yarn add file:vendor/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
</Tabs>
The package will be installed and accessible as `xlsx`.
## Usage
With most frameworks and bundler tools, named imports are recommended:
```js
import { read, utils } from 'xlsx';
```
Some legacy bundlers require the glob import:
```js
import * as XLSX from 'xlsx';
const { read, utils } = XLSX;
```
For legacy bundlers that support CommonJS, `require` will work:
```js
var XLSX = require("xlsx");
var read = XLSX.read, utils = XLSX.utils;
```
The ["Bundlers" demo](/docs/demos/bundler) includes examples for specific tools.
## Encoding support
If Encoding support is required, `cpexcel.full.mjs` must be manually imported:

@ -336,7 +336,7 @@ npx http-server dist/
The terminal will display a URL ( `http://127.0.0.1:8080` ). Access that page
with a web browser.
11) To confirm that only the raw data is present in the page, view the page
11) To confirm that the object data is not present in the page, view the page
source. The code will reference some script like `/assets/index-HASH.js`.
Open that script. Searching for `Bill Clinton` should yield no results.
Searching for `BESSELJ` should match the code:

@ -7,17 +7,18 @@ sidebar_position: 2
<details>
<summary><b>File Format Support</b> (click to show)</summary>
| Formats | Link | Tooltip | Storage Representation |
|:------------------|:-----:|:-------:|:-----------------------|
| XLSX / XLSM | ✔ | ✔ | Cell Link + Tooltip |
| XLSB | ✔ | ✔ | Cell Link + Tooltip |
| XLS (BIFF8) | ✔ | ✔ | Cell Link + Tooltip |
| XLML | ✔ | ✔ | Cell Link + Tooltip |
| ODS / FODS / UOS | ✔ | | Span Link + Tooltip |
| HTML | ✔ | * | Span Link |
| NUMBERS | | * | Span Link ** |
| Formats | Link | Tooltip | Link Type |
|:------------------|:-----:|:-------:|:----------|
| XLSX / XLSM | ✔ | ✔ | Cell Link |
| XLSB | ✔ | ✔ | Cell Link |
| XLS (BIFF8) | ✔ | ✔ | Cell Link |
| XLML | ✔ | ✔ | Cell Link |
| ODS / FODS / UOS | ✔ | | Span Link |
| HTML | ✔ | ✕ | Span Link |
| NUMBERS | ✔ | ✕ | Span Link |
Asterisks (*) mark features that are not supported by the file formats.
X (✕) marks features that are not supported by the file formats. For example,
the NUMBERS file format does not support custom tooltips.
For "Span Link" formats, parsers apply the first hyperlink to the entire cell
and writers apply the hyperlink to the entire cell text.

@ -20,7 +20,7 @@ allow users to "reply". The original "Comments" were renamed to "Notes".
|:------------------|:-----:|:-------:|:--------:|
| XLSX / XLSM | ✕ | ✔ | ✔ |
| XLSB | ✕ | R | R |
| NUMBERS | ✕ | ✕ | R |
| NUMBERS | ✕ | ✕ | |
| XLS (BIFF8) | ✕ | ✔ | ✕ |
| XLML | ✕ | ✔ | ✕ |
| ODS / FODS / UOS | ✕ | ✔ | ✕ |
@ -54,7 +54,9 @@ field is the plain text representation.
For example, the following snippet appends a cell comment into cell `A1`:
```js
/* get cell A1, creating an empty cell if necessary */
var cell = ws["A1"];
if(!ws["A1"]) ws["A1"] = { t: "z" };
/* create comment array if it does not exist */
if(!cell.c) cell.c = [];
@ -137,7 +139,8 @@ function SheetJSParseComments(props) {
## Visibility
To mark a comment as normally hidden, set the `hidden` property:
The `hidden` property of the comment block indicates comment visibility. If set
to `true`, the comment will not be visible until users hover over the comment.
```js
if(!cell.c) cell.c = [];
@ -171,8 +174,8 @@ function SheetJSComments2() {
## Threaded Comments
Introduced in Excel 365, threaded comments are plain text comment snippets with
author metadata and parent references. They are supported in XLSX and XLSB.
Threaded comments are plain text comment snippets with author metadata and
parent references. They are supported in XLSX, XLSB, and NUMBERS files.
To mark a comment as threaded, each comment part must have a true `T` property:
@ -202,16 +205,15 @@ There is no Active Directory or Office 365 metadata associated with authors.
```jsx live
function SheetJSComments2() {
return (<button onClick={() => {
return ( <button onClick={() => {
var ws = XLSX.utils.aoa_to_sheet([["SheetJS"], [5433795]]);
/* normal comment */
if(!ws.A1.c) ws.A1.c = [];
ws.A1.c.push({a:"SheetJS", t:"This is not threaded"});
/* hidden threaded comment */
/* threaded comment */
if(!ws.A2.c) ws.A2.c = [];
ws.A2.c.hidden = true;
/* add parts */
ws.A2.c.push({a:"SheetJS", t:"This is threaded", T: true});
@ -222,9 +224,8 @@ function SheetJSComments2() {
/* create workbook and export */
var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "SheetJSThreadedComments.xlsx");
}}>Click me to generate a sample file</button>);
}}>Click me to generate a sample file</button> );
}
```
</details>

@ -19,10 +19,10 @@ Defined names have evolved over the decades, with new features added over time:
| XLSB | ✔ | ✔ | ✔ |
| XLS | ✔ | ✔ | ✔ |
| XLML | ✔ | ✔ | |
| SYLK | ✔ | * | |
| SYLK | ✔ | | |
| ODS / FODS / UOS | ✔ | ✔ | |
Asterisks (*) mark features that are not supported by the file formats. There is
X (✕) marks features that are not supported by the file formats. There is
no way to specify a Unicode defined name in the SYLK format.
</details>

@ -18,11 +18,11 @@ identical to XLSX and supports macros.
| Formats | Basic | Storage Representation |
|:--------|:-----:|:-----------------------------------|
| XLSM | ✔ | `vbaProject.bin` file in container |
| XLSX | * | Not supported in format (use XLSM) |
| XLSX | | Not supported in format (use XLSM) |
| XLSB | ✔ | `vbaProject.bin` file in container |
| XLS | ✔ | Intercalated in CFB container |
Asterisks (*) mark features that are not supported by the file formats. There is
X (✕) marks features that are not supported by the file formats. There is
no way to embed VBA in the XLSX format.
</details>

@ -6,14 +6,101 @@ title: Arrays of Data
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
export const r = {style: {backgroundColor:"red"}};
export const b = {style: {backgroundColor:"blue"}};
export const g = {style: {backgroundColor:"green"}};
export const y = {style: {backgroundColor:"yellow"}};
Arrays of objects are a common data format in JavaScript database connectors
and other general data sources.
Numeric datasets commonly use arrays of arrays of numbers.
The ["Data Storage"](#data-storage) section gives a general overview of common
array formats in JavaScript.
The ["Functions"](#functions) section describes the related functions.
## Data Storage
### Array of Arrays
The spiritual equivalent of the grid in JavaScript is an array of arrays:
<table><thead><tr><th>Spreadsheet</th><th>Array of Arrays</th></tr></thead><tbody><tr><td>
![`pres.xlsx` data](pathname:///pres.png)
</td><td>
```js
[
["Name", "Index"],
["Bill Clinton", 42],
["GeorgeW Bush", 43],
["Barack Obama", 44],
["Donald Trump", 45],
["Joseph Biden", 46]
]
```
</td></tr></tbody></table>
Each array within the structure corresponds to one row. Individual data points
can be read by indexing by row index and by column index:
```js
var aoa = [
["Name", "Index"],
["Bill Clinton", 42],
["GeorgeW Bush", 43],
["Barack Obama", 44],
["Donald Trump", 45],
["Joseph Biden", 46]
];
var value_at_B4 = aoa[3][1]; // 44
var value_at_A2 = aoa[1][0]; // Bill Clinton
```
### Arrays of Objects
Arrays of objects are commonly used to represent rows from a database:
<table><thead><tr><th>Spreadsheet</th><th>Array of Objects</th></tr></thead><tbody><tr><td>
![`pres.xlsx` data](pathname:///pres.png)
</td><td>
```js
[
{ Name: "Bill Clinton", Index: 42 },
{ Name: "GeorgeW Bush", Index: 43 },
{ Name: "Barack Obama", Index: 44 },
{ Name: "Donald Trump", Index: 45 },
{ Name: "Joseph Biden", Index: 46 }
]
```
</td></tr></tbody></table>
Each object within the structure corresponds to one data row. The first row of
the spreadsheet is interpreted as the header row.
## Functions
The "Input" subsections describe functions that generate SheetJS worksheet
objects from arrays of data.
The ["Array Output"](#array-output) subsection defines functions that extract
data from SheetJS worksheet objects.
#### Example Sheet
:::note
The examples are based on the following worksheet:
The live examples are based on the following worksheet:
<table>
<tr><td>S</td><td>h</td><td>e</td><td>e</td><td>t</td><td>J</td><td>S</td></tr>
@ -23,9 +110,12 @@ The examples are based on the following worksheet:
<tr><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>0</td></tr>
</table>
This table includes duplicate column labels ("e" and "S" appear twice in the
first row) and gaps (three data rows have missing fields).
:::
## Array of Arrays Input
### Array of Arrays Input
**Create a worksheet from an array of arrays**
@ -51,16 +141,27 @@ The function takes an options argument:
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
The example worksheet can be generated with:
The following live example reproduces the [example worksheet](#example-sheet):
```js
var ws = XLSX.utils.aoa_to_sheet([
["S", "h", "e", "e", "t", "J", "S"],
[ 1, 2, , , 5, 6, 7],
[ 2, 3, , , 6, 7, 8],
[ 3, 4, , , 7, 8, 9],
[ 4, 5, 6, 7, 8, 9, 0]
]);
```jsx live
function SheetJSExportAOA() {
/* array of arrays of data */
var aoa = [
["S", "h", "e", "e", "t", "J", "S"],
[ 1, 2, , , 5, 6, 7],
[ 2, 3, , , 6, 7, 8],
[ 3, 4, , , 7, 8, 9],
[ 4, 5, 6, 7, 8, 9, 0]
];
return ( <button onClick={() => {
/* create worksheet */
var ws = XLSX.utils.aoa_to_sheet(aoa);
/* create workbook and export */
var wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "SheetJSExportAOA.xlsx");
}}>Click to export Array of Arrays</button> );
}
```
**Add data from an array of arrays to an existing worksheet**
@ -92,7 +193,29 @@ accepts an options argument:
| (default) | Start from cell `A1` |
The example worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`:
The [example worksheet](#example-sheet) can be built up in the following order:
<table><thead><tr><th>Spreadsheet</th><th>Operations</th></tr></thead><tbody><tr><td>
<table>
<tr {...r}><td>S</td><td>h</td><td>e</td><td>e</td><td>t</td><td>J</td><td>S</td></tr>
<tr><td {...b}>1</td><td {...b}>2</td><td> </td><td> </td><td {...g}>5</td><td {...g}>6</td><td {...g}>7</td></tr>
<tr><td {...b}>2</td><td {...b}>3</td><td> </td><td> </td><td {...g}>6</td><td {...g}>7</td><td {...g}>8</td></tr>
<tr><td {...b}>3</td><td {...b}>4</td><td> </td><td> </td><td {...g}>7</td><td {...g}>8</td><td {...g}>9</td></tr>
<tr {...y}><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>0</td></tr>
</table>
</td><td>
1) `aoa_to_sheet` writes `A1:G1` (red)
2) `sheet_add_aoa` writes `A2:B4` (blue)
3) `sheet_add_aoa` writes `E2:G4` (green)
4) `sheet_add_aoa` writes `A5:G5` (yellow)
</td></tr></tbody></table>
```js
/* Initial row */
@ -108,7 +231,28 @@ XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1});
```
## Array of Objects Input
```jsx live
function SheetJSAddAOA() { return ( <button onClick={() => {
/* Initial row */
var ws = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]);
/* Write data starting at A2 */
XLSX.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"});
/* Write data starting at E2 */
XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
/* Append row */
XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1});
/* create workbook and export */
var wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "SheetJSAddAOA.xlsx");
}}>Click to export Array of Arrays</button> ); }
```
### Array of Objects Input
**Create a worksheet from an array of objects**
@ -163,29 +307,61 @@ const aoo = data.map(obj => Object.fromEntries(Object.entries(obj).filter(r => h
- Null values will be skipped by default. If `nullError` is true, an error cell
corresponding to `#NULL!` will be written to the worksheet.
The example sheet cannot be reproduced using plain objects since JS object keys
must be unique. After replacing the second `e` and `S` with `e_1` and `S_1`:
```jsx live
function SheetJSExportAOO() {
/* array of arrays of data */
var aoo = [
{ Name: "Bill Clinton", Index: 42 },
{ Name: "GeorgeW Bush", Index: 43 },
{ Name: "Barack Obama", Index: 44 },
{ Name: "Donald Trump", Index: 45 },
{ Name: "Joseph Biden", Index: 46 }
];
return ( <button onClick={() => {
/* create worksheet */
var ws = XLSX.utils.json_to_sheet(aoo);
/* create workbook and export */
var wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "SheetJSExportAOO.xlsx");
}}>Click to export Array of Objects</button> );
}
```
:::info
The [example sheet](#example-sheet) cannot be reproduced using plain objects
since JS object keys must be unique.
Typically the original data source will have different column names. After
writing with `json_to_sheet`, the `aoa_to_sheet` method can rewrite the headers:
```js
var ws = XLSX.utils.json_to_sheet([
/* original array of objects */
var data = [
{ S:1, h:2, t:5, J:6, S_1:7 },
{ S:2, h:3, t:6, J:7, S_1:8 },
{ S:3, h:4, t:7, J:8, S_1:9 },
{ S:4, h:5, e:6, e_1:7, t:8, J:9, S_1:0 },
], {header:["S","h","e","e_1","t","J","S_1"]});
];
/* column order for the generated worksheet */
// | A | B | C | D | E | F | G |
var data_headers = [ "S", "h", "e", "e_1", "t", "J", "S_1" ];
/* new headers for the first row of the worksheet */
// | A | B | C | D | E | F | G |
var new_headers = [ "S", "h", "e", "e", "t", "J", "S" ];
/* write data with using data headers */
var ws = XLSX.utils.json_to_sheet(data, { header: data_headers });
/* replace first row */
XLSX.utils.sheet_add_aoa(worksheet, [new_headers], { origin: "A1" });
```
Alternatively, a different set of unique headers can be used with `skipHeader`:
```js
var ws = XLSX.utils.json_to_sheet([
{ A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" },
{ A: 1, B: 2, E: 5, F: 6, G: 7 },
{ A: 2, B: 3, E: 6, F: 7, G: 8 },
{ A: 3, B: 4, E: 7, F: 8, G: 9 },
{ A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 },
], {header:["A","B","C","D","E","F","G"], skipHeader:true});
```
:::
**Add data from an array of objects to an existing worksheet**
@ -275,7 +451,7 @@ function SheetJSHeaderOrder() {
:::
## Array Output
### Array Output
<Tabs>
<TabItem name="JS" value="JavaScript">