2022-05-16 03:26:04 +00:00
|
|
|
---
|
2022-06-01 22:59:29 +00:00
|
|
|
sidebar_position: 3
|
2022-05-16 03:26:04 +00:00
|
|
|
---
|
|
|
|
|
2023-06-13 17:49:52 +00:00
|
|
|
import Tabs from '@theme/Tabs';
|
|
|
|
import TabItem from '@theme/TabItem';
|
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
# Sheet Objects
|
|
|
|
|
|
|
|
Excel supports 4 different types of "sheets":
|
|
|
|
- "worksheets": normal sheets
|
|
|
|
- "chartsheets": full-tab charts
|
|
|
|
- "macrosheets": legacy (pre-VBA) macros
|
2022-08-25 08:22:28 +00:00
|
|
|
- "dialogsheets": legacy (pre-VBA) dialog windows
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
## Generic Sheet Object
|
|
|
|
|
|
|
|
Generic sheets are plain JavaScript objects. Each key that does not start with
|
|
|
|
`!` is an `A1`-style address whose corresponding value is a cell object.
|
|
|
|
|
2022-10-24 01:28:03 +00:00
|
|
|
### Cell Storage
|
|
|
|
|
|
|
|
By default, the parsers and utility functions generate "sparse-mode" worksheet
|
|
|
|
objects. `sheet[address]` returns the cell object for the specified address.
|
|
|
|
|
2022-10-24 16:49:28 +00:00
|
|
|
#### Dense Mode
|
|
|
|
|
2022-10-24 01:28:03 +00:00
|
|
|
When the option `dense: true` is passed, parsers will generate a "dense-mode"
|
|
|
|
worksheet where cells are stored in an array of arrays. `sheet["!data"][R][C]`
|
|
|
|
returns the cell object at row `R` and column `C` (zero-indexed values).
|
|
|
|
|
|
|
|
When processing small worksheets in older environments, sparse worksheets are
|
|
|
|
more efficient than dense worksheets. In newer browsers, when dealing with very
|
|
|
|
large worksheets, dense sheets use less memory and tend to be more efficient.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
2024-04-08 04:47:04 +00:00
|
|
|
<details>
|
|
|
|
<summary><b>Migrating to Dense Mode</b> (click to show)</summary>
|
2022-10-24 16:49:28 +00:00
|
|
|
|
|
|
|
`read`, `readFile`, `write`, `writeFile`, and the various API functions support
|
|
|
|
sparse and dense worksheets. Functions that accept worksheet or workbook objects
|
|
|
|
(e.g. `writeFile` and `sheet_to_json`) will detect dense sheets.
|
|
|
|
|
2023-06-13 17:49:52 +00:00
|
|
|
The option `dense: true` should be used when creating worksheet or book objects.
|
|
|
|
|
|
|
|
**Update code that manually searches for cells** (adding dense mode support):
|
|
|
|
|
|
|
|
_Addressing Cells_
|
|
|
|
|
|
|
|
<Tabs>
|
|
|
|
<TabItem value="es3" label="Works everywhere">
|
2022-10-24 16:49:28 +00:00
|
|
|
|
|
|
|
```diff
|
2023-06-13 17:49:52 +00:00
|
|
|
-var cell = sheet["B7"];
|
|
|
|
+var cell = sheet["!data"] != null ? (sheet["!data"][6]||[])[1] : sheet["B3"];
|
|
|
|
```
|
2022-10-24 16:49:28 +00:00
|
|
|
|
2023-06-13 17:49:52 +00:00
|
|
|
</TabItem>
|
|
|
|
<TabItem value="es2020" label="New in 2020">
|
2022-10-24 16:49:28 +00:00
|
|
|
|
2023-06-13 17:49:52 +00:00
|
|
|
```diff
|
|
|
|
-var cell = sheet["B7"];
|
|
|
|
+var cell = sheet["!data"] != null ? sheet["!data"]?.[6]?.[1] : sheet["B3"];
|
|
|
|
```
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
</Tabs>
|
|
|
|
|
|
|
|
The row and column can be calculated using `XLSX.utils.decode_cell`:
|
|
|
|
|
|
|
|
```diff
|
|
|
|
var addr = "B7";
|
|
|
|
-var cell = sheet[addr];
|
|
|
|
+var _addr = XLSX.utils.decode_cell(addr);
|
|
|
|
+var cell = sheet["!data"] != null ? sheet["!data"]?.[_addr.r]?.[_addr.c] : sheet[addr];
|
2022-10-24 16:49:28 +00:00
|
|
|
```
|
|
|
|
|
2023-06-13 17:49:52 +00:00
|
|
|
`XLSX.utils.encode_cell` will be using the desired row and column indices:
|
|
|
|
|
|
|
|
```diff
|
|
|
|
-var cell = sheet[XLSX.utils.encode_cell({r:R, c:C})];
|
|
|
|
+var cell = sheet["!data"] != null ? sheet["!data"]?.[R]?.[C] : sheet[XLSX.utils.encode_cell({r:R, c:C})];
|
|
|
|
```
|
|
|
|
|
|
|
|
_Looping across a Worksheet_
|
|
|
|
|
2022-10-24 16:49:28 +00:00
|
|
|
Code that manually loops over worksheet objects should test for `"!data"` key:
|
|
|
|
|
|
|
|
```js
|
|
|
|
const { decode_range, encode_cell } = XLSX.utils;
|
|
|
|
|
|
|
|
function log_all_cells(ws) {
|
|
|
|
var range = decode_range(ws["!ref"]);
|
|
|
|
// highlight-next-line
|
|
|
|
var dense = ws["!data"] != null; // test if sheet is dense
|
|
|
|
for(var R = 0; R <= range.e.r; ++R) {
|
|
|
|
for(var C = 0; C <= range.e.c; ++C) {
|
|
|
|
// highlight-next-line
|
|
|
|
var cell = dense ? ws["!data"]?.[R]?.[C] : ws[encode_cell({r:R, c:C})];
|
|
|
|
console.log(R, C, cell);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2023-06-13 17:49:52 +00:00
|
|
|
**Update workbook and worksheet generation code**
|
|
|
|
|
|
|
|
_`read`_
|
|
|
|
```diff
|
|
|
|
-var workbook = XLSX.read(data, {...opts});
|
|
|
|
+var workbook = XLSX.read(data, {...opts, dense: true});
|
|
|
|
```
|
|
|
|
|
|
|
|
_`readFile`_
|
|
|
|
```diff
|
|
|
|
-var workbook = XLSX.readFile(data, {...opts});
|
|
|
|
+var workbook = XLSX.readFile(data, {...opts, dense: true});
|
|
|
|
```
|
|
|
|
|
|
|
|
_`aoa_to_sheet`_
|
|
|
|
```diff
|
|
|
|
-var sheet = XLSX.utils.aoa_to_sheet([[1,2,3],[4,5,6]], {...opts});
|
|
|
|
+var sheet = XLSX.utils.aoa_to_sheet([[1,2,3],[4,5,6]], {...opts, dense: true});
|
|
|
|
```
|
|
|
|
|
|
|
|
_`json_to_sheet`_
|
|
|
|
```diff
|
|
|
|
-var sheet = XLSX.utils.json_to_sheet([{x:1,y:2}], {...opts});
|
|
|
|
+var sheet = XLSX.utils.json_to_sheet([{x:1,y:2}], {...opts, dense: true});
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-24 16:49:28 +00:00
|
|
|
</details>
|
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
### Sheet Properties
|
|
|
|
|
|
|
|
Each key starts with `!`. The properties are accessible as `sheet[key]`.
|
|
|
|
|
|
|
|
- `sheet['!ref']`: A-1 based range representing the sheet range. Functions that
|
|
|
|
work with sheets should use this parameter to determine the range. Cells that
|
|
|
|
are assigned outside of the range are not processed. In particular, when
|
|
|
|
writing a sheet by hand, cells outside of the range are not included
|
|
|
|
|
|
|
|
Functions that handle sheets should test for the presence of `!ref` field.
|
|
|
|
If the `!ref` is omitted or is not a valid range, functions are free to treat
|
|
|
|
the sheet as empty or attempt to guess the range. The standard utilities that
|
|
|
|
ship with this library treat sheets as empty (for example, the CSV output is
|
|
|
|
empty string).
|
|
|
|
|
|
|
|
When reading a worksheet with the `sheetRows` property set, the ref parameter
|
|
|
|
will use the restricted range. The original range is set at `ws['!fullref']`
|
|
|
|
|
|
|
|
- `sheet['!margins']`: Object representing the page margins. The default values
|
|
|
|
follow Excel's "normal" preset. Excel also has a "wide" and a "narrow" preset
|
|
|
|
but they are stored as raw measurements. The main properties are listed below:
|
|
|
|
|
|
|
|
<details>
|
|
|
|
<summary><b>Page margin details</b> (click to show)</summary>
|
|
|
|
|
|
|
|
| key | description | "normal" | "wide" | "narrow" |
|
|
|
|
|----------|------------------------|:---------|:-------|:-------- |
|
|
|
|
| `left` | left margin (inches) | `0.7` | `1.0` | `0.25` |
|
|
|
|
| `right` | right margin (inches) | `0.7` | `1.0` | `0.25` |
|
|
|
|
| `top` | top margin (inches) | `0.75` | `1.0` | `0.75` |
|
|
|
|
| `bottom` | bottom margin (inches) | `0.75` | `1.0` | `0.75` |
|
|
|
|
| `header` | header margin (inches) | `0.3` | `0.5` | `0.3` |
|
|
|
|
| `footer` | footer margin (inches) | `0.3` | `0.5` | `0.3` |
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* Set worksheet sheet to "normal" */
|
|
|
|
ws["!margins"]={left:0.7, right:0.7, top:0.75,bottom:0.75,header:0.3,footer:0.3}
|
|
|
|
/* Set worksheet sheet to "wide" */
|
|
|
|
ws["!margins"]={left:1.0, right:1.0, top:1.0, bottom:1.0, header:0.5,footer:0.5}
|
|
|
|
/* Set worksheet sheet to "narrow" */
|
|
|
|
ws["!margins"]={left:0.25,right:0.25,top:0.75,bottom:0.75,header:0.3,footer:0.3}
|
|
|
|
```
|
|
|
|
</details>
|
|
|
|
|
|
|
|
## Worksheet Object
|
|
|
|
|
|
|
|
In addition to the aforementioned sheet keys, worksheets also add:
|
|
|
|
|
2023-09-20 21:53:18 +00:00
|
|
|
- `ws['!cols']`: [array of column objects](/docs/csf/features/colprops).
|
|
|
|
Each column object encodes properties including level, width and visibility.
|
|
|
|
|
|
|
|
- `ws['!rows']`: [array of row objects](/docs/csf/features/rowprops).
|
|
|
|
Each row object encodes properties including level, height and visibility.
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
- `ws['!merges']`: array of range objects corresponding to the merged cells in
|
|
|
|
the worksheet. Plain text formats do not support merge cells. CSV export
|
|
|
|
will write all cells in the merge range if they exist, so be sure that only
|
|
|
|
the first cell (upper-left) in the range is set.
|
|
|
|
|
|
|
|
- `ws['!outline']`: configure how outlines should behave. Options default to
|
|
|
|
the default settings in Excel 2019:
|
|
|
|
|
|
|
|
| key | Excel feature | default |
|
|
|
|
|:----------|:----------------------------------------------|:--------|
|
2022-08-24 00:51:18 +00:00
|
|
|
| `above` | Disable "Summary rows below detail" | `false` |
|
|
|
|
| `left` | Disable "Summary rows to the right of detail" | `false` |
|
2022-05-16 03:26:04 +00:00
|
|
|
|
|
|
|
- `ws['!protect']`: object of write sheet protection properties. The `password`
|
|
|
|
key specifies the password for formats that support password-protected sheets
|
|
|
|
(XLSX/XLSB/XLS). The writer uses the XOR obfuscation method. The following
|
|
|
|
keys control the sheet protection -- set to `false` to enable a feature when
|
|
|
|
sheet is locked or set to `true` to disable a feature:
|
|
|
|
|
|
|
|
<details>
|
|
|
|
<summary><b>Worksheet Protection Details</b> (click to show)</summary>
|
|
|
|
|
|
|
|
| key | feature (true=disabled / false=enabled) | default |
|
|
|
|
|:----------------------|:----------------------------------------|:-----------|
|
|
|
|
| `selectLockedCells` | Select locked cells | enabled |
|
|
|
|
| `selectUnlockedCells` | Select unlocked cells | enabled |
|
|
|
|
| `formatCells` | Format cells | disabled |
|
|
|
|
| `formatColumns` | Format columns | disabled |
|
|
|
|
| `formatRows` | Format rows | disabled |
|
|
|
|
| `insertColumns` | Insert columns | disabled |
|
|
|
|
| `insertRows` | Insert rows | disabled |
|
|
|
|
| `insertHyperlinks` | Insert hyperlinks | disabled |
|
|
|
|
| `deleteColumns` | Delete columns | disabled |
|
|
|
|
| `deleteRows` | Delete rows | disabled |
|
|
|
|
| `sort` | Sort | disabled |
|
|
|
|
| `autoFilter` | Filter | disabled |
|
|
|
|
| `pivotTables` | Use PivotTable reports | disabled |
|
|
|
|
| `objects` | Edit objects | enabled |
|
|
|
|
| `scenarios` | Edit scenarios | enabled |
|
2022-10-04 20:37:38 +00:00
|
|
|
|
2022-05-16 03:26:04 +00:00
|
|
|
</details>
|
|
|
|
|
|
|
|
- `ws['!autofilter']`: AutoFilter object following the schema:
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
type AutoFilter = {
|
|
|
|
ref:string; // A-1 based range representing the AutoFilter table range
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Other Sheet Types
|
|
|
|
|
|
|
|
### Chartsheet Object
|
|
|
|
|
|
|
|
Chartsheets are represented as standard sheets. They are distinguished with the
|
|
|
|
`!type` property set to `"chart"`.
|
|
|
|
|
|
|
|
The underlying data and `!ref` refer to the cached data in the chartsheet. The
|
|
|
|
first row of the chartsheet is the underlying header.
|
|
|
|
|
|
|
|
### Macrosheet Object
|
|
|
|
|
|
|
|
Macrosheets are represented as standard sheets. They are distinguished with the
|
|
|
|
`!type` property set to `"macro"`.
|
|
|
|
|
|
|
|
### Dialogsheet Object
|
|
|
|
|
|
|
|
Dialogsheets are represented as standard sheets. They are distinguished with the
|
|
|
|
`!type` property set to `"dialog"`.
|