row-col
This commit is contained in:
parent
7a1b75d50b
commit
8e39ab8f33
@ -37,7 +37,7 @@ The ["Demo"](#demo) creates an app that looks like the screenshots below:
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
### Integration Details
|
||||
## Integration Details
|
||||
|
||||
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
|
||||
from the main entrypoint or any script in the project.
|
||||
@ -91,7 +91,7 @@ async function updateFile(v) { try {
|
||||
} catch(e) { console.log(e); } }
|
||||
```
|
||||
|
||||
#### Writing data
|
||||
### Writing data
|
||||
|
||||
Starting from an array of objects, the SheetJS `json_to_sheet` method[^5]
|
||||
generates a SheetJS worksheet object. The `book_append_sheet` and `book_new`
|
||||
@ -141,7 +141,7 @@ window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
|
||||
});
|
||||
```
|
||||
|
||||
### Demo
|
||||
## Demo
|
||||
|
||||
:::note
|
||||
|
||||
|
@ -179,14 +179,11 @@ ws["!margins"]={left:0.25,right:0.25,top:0.75,bottom:0.75,header:0.3,footer:0.3}
|
||||
|
||||
In addition to the aforementioned sheet keys, worksheets also add:
|
||||
|
||||
- `ws['!cols']`: array of column properties objects. Column widths are actually
|
||||
stored in files in a normalized manner, measured in terms of the "Maximum
|
||||
Digit Width" (the largest width of the rendered digits 0-9, in pixels). When
|
||||
parsed, the column objects store the pixel width in the `wpx` field, character
|
||||
width in the `wch` field, and the maximum digit width in the `MDW` field.
|
||||
- `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 properties objects as explained later in the docs.
|
||||
Each row object encodes properties including row height and visibility.
|
||||
- `ws['!rows']`: [array of row objects](/docs/csf/features/rowprops).
|
||||
Each row object encodes properties including level, height and visibility.
|
||||
|
||||
- `ws['!merges']`: array of range objects corresponding to the merged cells in
|
||||
the worksheet. Plain text formats do not support merge cells. CSV export
|
||||
|
361
docz/docs/07-csf/07-features/08-rowprops.md
Normal file
361
docz/docs/07-csf/07-features/08-rowprops.md
Normal file
@ -0,0 +1,361 @@
|
||||
---
|
||||
title: Row Properties
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
By default, all rows in a workbook are "Visible" and have a standard height.
|
||||
|
||||
| Formats | Height | Hidden Rows | Outline Level |
|
||||
|:-----------------|:------:|:-----------:|:-------------:|
|
||||
| XLSX/XLSM | ✔ | ✔ | ✔ |
|
||||
| XLSB | ✔ | ✔ | ✔ |
|
||||
| XLML | ✔ | ✔ | ✕ |
|
||||
| BIFF8 XLS | R | R | R |
|
||||
| BIFF5 XLS | R | R | R |
|
||||
| SYLK | ✔ | * | ✕ |
|
||||
| ODS / FODS / UOS | + | + | + |
|
||||
|
||||
Asterisks (*) mark formats that represent hidden rows with zero height. For
|
||||
example, there is no way to specify a custom row height and mark that the row is
|
||||
hidden in the SYLK format.
|
||||
|
||||
Plus (+) marks formats with limited support. ODS supports specifying row heights
|
||||
in many units of measure. SheetJS supports some but not all ODS units.
|
||||
|
||||
X (✕) marks features that are not supported by the file formats. For example,
|
||||
the SpreadsheetML 2003 (XLML) file format does not support outline levels.
|
||||
|
||||
</details>
|
||||
|
||||
Many spreadsheet tools support adjusting row heights to accommodate multiple
|
||||
lines of data or varying text sizes.
|
||||
|
||||
Some tools additionally support row grouping or "outlining". Excel displays row
|
||||
outline levels to the left of the grid.
|
||||
|
||||
SheetJS worksheet objects store row properties in the `!rows` field. It is
|
||||
expected to be an array of row metadata objects.
|
||||
|
||||
## Demo
|
||||
|
||||
This example creates a workbook that includes custom row heights, hidden rows,
|
||||
and row outline levels.
|
||||
|
||||
<table><thead><tr>
|
||||
<th>Excel for Windows</th>
|
||||
<th>Excel for Mac</th>
|
||||
</tr></thead><tbody><tr><td>
|
||||
|
||||
![Excel for Windows](pathname:///rowprops/win.png)
|
||||
|
||||
</td><td>
|
||||
|
||||
![Excel for Mac](pathname:///rowprops/mac.png)
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
<details><summary><b>Export Demo</b> (click to show)</summary>
|
||||
|
||||
The table lists the assigned heights, outline levels and visibility settings.
|
||||
|
||||
```jsx live
|
||||
function SheetJSRowProps() {
|
||||
const [ws, setWS] = React.useState();
|
||||
const [__html, setHTML] = React.useState("");
|
||||
const fmt = React.useRef(null);
|
||||
|
||||
/* when the page is loaded, create worksheet and show table */
|
||||
React.useEffect(() => {
|
||||
/* Create worksheet from simple data */
|
||||
const data = [
|
||||
{ Height: 20, Unit: "px", Level: 0 }, { Height: 25, Unit: "pt", Level: 1 },
|
||||
{ Height: 30, Unit: "px", Level: 2 }, { Height: 35, Unit: "pt", Level: 3 },
|
||||
{ Height: 25, Unit: "pt", Level: 3 }, { Height: 15, Unit: "px", Level: 1 },
|
||||
{ Height: 10, Unit: "pt", Level: 0 }, { Hidden: true }
|
||||
];
|
||||
const ws = XLSX.utils.json_to_sheet(data);
|
||||
/* set row metadata */
|
||||
ws["!rows"] = [];
|
||||
data.forEach((row, i) => {
|
||||
const r = {};
|
||||
if(row.Level) (ws["!rows"][i+1] = r).level = row.Level;
|
||||
if(row.Unit == "px") (ws["!rows"][i+1] = r).hpx = row.Height || 0;
|
||||
if(row.Unit == "pt") (ws["!rows"][i+1] = r).hpt = row.Height || 0;
|
||||
if(row.Hidden) (ws["!rows"][i+1] = r).hidden = true;
|
||||
});
|
||||
|
||||
/* save worksheet object for the export */
|
||||
setWS(ws);
|
||||
/* generate the HTML table */
|
||||
setHTML(XLSX.utils.sheet_to_html(ws));
|
||||
}, []);
|
||||
|
||||
const xport = (fmt) => {
|
||||
/* Export to file (start a download) */
|
||||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "Formats");
|
||||
XLSX.writeFile(wb, `SheetJSRowProps.${fmt}`, {cellStyles: true});
|
||||
};
|
||||
|
||||
const fmts = ["xlsx", "xlsb", "xls", "slk", "ods"];
|
||||
return ( <>
|
||||
<b>File format: </b>
|
||||
<select ref={fmt}>{fmts.map(f=>(<option value={f}>{f}</option>))}</select>
|
||||
<br/><button onClick={()=>xport(fmt.current.value)}><b>Export!</b></button>
|
||||
<div dangerouslySetInnerHTML={{__html}}/>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Functions
|
||||
|
||||
:::caution pass
|
||||
|
||||
**Row processing must be explicitly enabled!**
|
||||
|
||||
:::
|
||||
|
||||
Functions creating worksheet objects are not guaranteed to generate the `!rows`
|
||||
array. Writers are not guaranteed to export row metadata.
|
||||
|
||||
#### Reading Files
|
||||
|
||||
[`read` and `readFile`](/docs/api/parse-options) accept an options argument. The
|
||||
`cellStyles` option must be set to `true` to generate row properties:
|
||||
|
||||
```js
|
||||
var wb = XLSX.read(data, {/* ... other options , */ cellStyles: true});
|
||||
```
|
||||
|
||||
#### Writing Files
|
||||
|
||||
[`write` and `writeFile`](/docs/api/write-options) accept an options argument.
|
||||
The `cellStyles` option must be set to `true` to export row properties:
|
||||
|
||||
```js
|
||||
XLSX.writeFile(wb, "SheetJSRowProps.xlsx", {/* ...opts , */ cellStyles: true});
|
||||
```
|
||||
|
||||
#### Importing HTML Tables
|
||||
|
||||
[`table_to_book` and `table_to_sheet`](/docs/api/utilities/html#html-table-input)
|
||||
process HTML DOM TABLE elements.
|
||||
|
||||
Individual table rows (`TR` elements) can be marked as hidden by setting the CSS
|
||||
`display` property to `none`.
|
||||
|
||||
By default, hidden rows are imported and appropriately marked as hidden:
|
||||
|
||||
```js
|
||||
/* generate worksheet from first table, preserving hidden rows */
|
||||
var tbl = document.getElementsByTagName("TABLE")[0];
|
||||
var ws = XLSX.utils.table_to_sheet(tbl);
|
||||
```
|
||||
|
||||
If the `display` option is set to `true`, hidden rows will be skipped:
|
||||
|
||||
```js
|
||||
/* generate worksheet from first table, omitting hidden rows */
|
||||
var tbl = document.getElementsByTagName("TABLE")[0];
|
||||
var ws = XLSX.utils.table_to_sheet(tbl, {display: true})
|
||||
```
|
||||
|
||||
#### Exporting Data
|
||||
|
||||
[`sheet_to_csv`](/docs/api/utilities/csv#delimiter-separated-output) and
|
||||
[`sheet_to_json`](/docs/api/utilities/array#array-output) accept options. If the
|
||||
`skipHidden` option is set to true, hidden rows will not be exported:
|
||||
|
||||
```js
|
||||
var ws = wb.Sheets[wb.SheetNames[0]]; // first worksheet
|
||||
var csv = XLSX.utils.sheet_to_csv(ws, {/* ...opts, */ skipHidden: true});
|
||||
```
|
||||
|
||||
## Storage
|
||||
|
||||
The `!rows` property in a sheet object stores row-level metadata. If present, it
|
||||
is expected to be an array of row objects.
|
||||
|
||||
:::info pass
|
||||
|
||||
As explained in ["Addresses and Ranges"](/docs/csf/general#rows), SheetJS uses
|
||||
zero-indexed rows. The row metadata for Excel row 20 is stored at index 19 of
|
||||
the `!rows` array.
|
||||
|
||||
:::
|
||||
|
||||
When performing operations, it is strongly recommended to test for the existence
|
||||
of the row structure.
|
||||
|
||||
This snippet checks the `!rows` array and the specific row object, creating them
|
||||
if they do not exist, before setting the `hidden` property of the third row:
|
||||
|
||||
```js
|
||||
/* Excel third row -> SheetJS row index 3 - 1 = 2 */
|
||||
var ROW_INDEX = 2;
|
||||
|
||||
/* create !rows array if it does not exist */
|
||||
if(!ws["!rows"]) ws["!rows"] = [];
|
||||
|
||||
/* create row metadata object if it does not exist */
|
||||
if(!ws["!rows"][ROW_INDEX]) ws["!rows"][ROW_INDEX] = {hpx: 20};
|
||||
|
||||
/* set row to hidden */
|
||||
ws["!rows"][ROW_INDEX].hidden = true;
|
||||
```
|
||||
|
||||
### Row Heights
|
||||
|
||||
Row heights can be specified in two ways:
|
||||
|
||||
| Property | Description |
|
||||
|:---------|:------------------------|
|
||||
| `hpx` | Height in screen pixels |
|
||||
| `hpt` | Height in points |
|
||||
|
||||
The following snippet sets the height of the third row to 50 pixels:
|
||||
|
||||
```js
|
||||
const ROW_HEIGHT = 50;
|
||||
|
||||
/* Excel third row -> SheetJS row index 3 - 1 = 2 */
|
||||
const ROW_INDEX = 2;
|
||||
|
||||
/* create !rows array if it does not exist */
|
||||
if(!ws["!rows"]) ws["!rows"] = [];
|
||||
|
||||
/* create row metadata object if it does not exist */
|
||||
if(!ws["!rows"][ROW_INDEX]) ws["!rows"][ROW_INDEX] = {hpx: ROW_HEIGHT};
|
||||
|
||||
/* set row height */
|
||||
ws["!rows"][ROW_INDEX].hpx = ROW_HEIGHT;
|
||||
```
|
||||
|
||||
### Row Visibility
|
||||
|
||||
The `hidden` property controls visibility.
|
||||
|
||||
The following snippet hides the fourth row:
|
||||
|
||||
```js
|
||||
/* Excel fourth row -> SheetJS row index 4 - 1 = 3 */
|
||||
var ROW_INDEX = 3;
|
||||
|
||||
/* create !rows array if it does not exist */
|
||||
if(!ws["!rows"]) ws["!rows"] = [];
|
||||
|
||||
/* create row metadata object if it does not exist */
|
||||
if(!ws["!rows"][ROW_INDEX]) ws["!rows"][ROW_INDEX] = {hpx: 20};
|
||||
|
||||
/* set row to hidden */
|
||||
ws["!rows"][ROW_INDEX].hidden = true;
|
||||
```
|
||||
|
||||
### Outline Levels
|
||||
|
||||
The `level` property controls outline level / grouping. It is expected to be a
|
||||
number between `0` and `7` inclusive.
|
||||
|
||||
:::note pass
|
||||
|
||||
The Excel UI displays outline levels next to the column labels. The base level
|
||||
shown in the application is `1`.
|
||||
|
||||
SheetJS is zero-indexed: the default (base) level is `0`.
|
||||
|
||||
:::
|
||||
|
||||
The following snippet sets the level of the sixth row to Excel 2 / SheetJS 1:
|
||||
|
||||
```js
|
||||
/* Excel level 2 -> SheetJS level 2 - 1 = 1 */
|
||||
var LEVEL = 1;
|
||||
|
||||
/* Excel sixth row -> SheetJS row index 6 - 1 = 5 */
|
||||
var ROW_INDEX = 2;
|
||||
|
||||
/* create !rows array if it does not exist */
|
||||
if(!ws["!rows"]) ws["!rows"] = [];
|
||||
|
||||
/* create row metadata object if it does not exist */
|
||||
if(!ws["!rows"][ROW_INDEX]) ws["!rows"][ROW_INDEX] = {hpx: 20};
|
||||
|
||||
/* set level */
|
||||
ws["!rows"][ROW_INDEX].level = LEVEL;
|
||||
```
|
||||
|
||||
### Grouping Rows
|
||||
|
||||
Applications treat consecutive rows with the same level as part of a "group".
|
||||
|
||||
The "Group" command typically increments the level of each row in the range:
|
||||
|
||||
```js
|
||||
/* start_row and end_row are SheetJS 0-indexed row indices */
|
||||
function gruppieren(ws, start_row, end_row) {
|
||||
/* create !rows array if it does not exist */
|
||||
if(!ws["!rows"]) ws["!rows"] = [];
|
||||
/* loop over every row index */
|
||||
for(var i = start_row; i <= end_row; ++i) {
|
||||
/* create row metadata object if it does not exist */
|
||||
if(!ws["!rows"][i]) ws["!rows"][i] = {hpx: 20};
|
||||
/* increment level */
|
||||
ws["!rows"][i].level = 1 + (ws["!rows"][i].level || 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The "Ungroup" command typically decrements the level of each row in the range:
|
||||
|
||||
```js
|
||||
/* start_row and end_row are SheetJS 0-indexed row indices */
|
||||
function dissocier(ws, start_row, end_row) {
|
||||
/* create !rows array if it does not exist */
|
||||
if(!ws["!rows"]) ws["!rows"] = [];
|
||||
/* loop over every row index */
|
||||
for(var i = start_row; i <= end_row; ++i) {
|
||||
/* if row metadata does not exist, the level is zero -> skip */
|
||||
if(!ws["!rows"][i]) continue;
|
||||
/* if row level is not specified, the level is zero -> skip */
|
||||
if(!ws["!rows"][i].level) continue;
|
||||
/* decrement level */
|
||||
--ws["!rows"][i].level;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Grouping Symbol
|
||||
|
||||
By default, Excel displays the group collapse button on the row after the data.
|
||||
In the UI, this is adjusted by the option "Summary rows below detail".
|
||||
|
||||
SheetJS exposes this option in the `above` property of the `"!outline"` property
|
||||
of worksheet objects. Setting this property to `true` effectively "unchecks" the
|
||||
"Summary rows below detail" option in Excel:
|
||||
|
||||
```js
|
||||
if(!ws["outline"]) ws["!outline"] = {};
|
||||
ws["!outline"].above = true; // show summary rows above detail
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
<details><summary><b>Details</b> (click to show)</summary>
|
||||
|
||||
Excel internally stores row heights in points. The default resolution is 72 DPI
|
||||
or 96 PPI, so the pixel and point size should agree. For different resolutions
|
||||
they may not agree, so the library separates the concepts.
|
||||
|
||||
Even though all of the information is made available, writers are expected to
|
||||
follow the priority order:
|
||||
|
||||
1) use `hpx` pixel height if available
|
||||
|
||||
2) use `hpt` point height if available
|
||||
|
||||
</details>
|
418
docz/docs/07-csf/07-features/09-colprops.md
Normal file
418
docz/docs/07-csf/07-features/09-colprops.md
Normal file
@ -0,0 +1,418 @@
|
||||
---
|
||||
title: Column Properties
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
By default, all columns in a workbook are "Visible" and have a standard width.
|
||||
|
||||
| Formats | Width | Hidden Cols | Outline Level |
|
||||
|:-----------------|:-----:|:-----------:|:-------------:|
|
||||
| XLSX/XLSM | ✔ | ✔ | ✔ |
|
||||
| XLSB | ✔ | ✔ | ✔ |
|
||||
| XLML | ✔ | ✔ | ✕ |
|
||||
| BIFF8 XLS | ✔ | ✔ | ✔ |
|
||||
| BIFF5 XLS | R | R | R |
|
||||
| SYLK | ✔ | * | ✕ |
|
||||
|
||||
Asterisks (*) mark formats that represent hidden columns with zero width. For
|
||||
example, there is no way to specify a custom column width and mark the column as
|
||||
hidden in the SYLK format.
|
||||
|
||||
X (✕) marks features that are not supported by the file formats. For example,
|
||||
the SpreadsheetML 2003 (XLML) file format does not support outline levels.
|
||||
|
||||
</details>
|
||||
|
||||
Many spreadsheet tools support adjusting column widths to accommodate longer
|
||||
formatted data or varying text sizes.
|
||||
|
||||
Some tools additionally support column grouping or "outlining". Excel displays
|
||||
outline levels above the grid.
|
||||
|
||||
SheetJS worksheet objects store column properties in the `!cols` field. It is
|
||||
expected to be an array of column metadata objects.
|
||||
|
||||
:::warning Excel Bugs
|
||||
|
||||
For most common formats (XLSX, XLS), widths are tied to font metrics, which are
|
||||
tied to Windows Scaling settings. In Windows 11, the Scale factor settings are
|
||||
found in "System" > "Display" > "Scale"
|
||||
|
||||
**Column widths may appear different on other machines due to scaling.**
|
||||
|
||||
**This is an issue with Excel.**
|
||||
|
||||
:::
|
||||
|
||||
## Demo
|
||||
|
||||
This example creates a workbook that includes custom column widths, hidden
|
||||
columns, and column outline levels.
|
||||
|
||||
<table><thead><tr>
|
||||
<th>Excel for Windows</th>
|
||||
<th>Excel for Mac</th>
|
||||
</tr></thead><tbody><tr><td>
|
||||
|
||||
![Excel for Windows](pathname:///colprops/win.png)
|
||||
|
||||
</td><td>
|
||||
|
||||
![Excel for Mac](pathname:///colprops/mac.png)
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
<details><summary><b>Export Demo</b> (click to show)</summary>
|
||||
|
||||
The table lists the assigned widths, outline levels and visibility settings.
|
||||
|
||||
```jsx live
|
||||
function SheetJColProps() {
|
||||
const [ws, setWS] = React.useState();
|
||||
const [__html, setHTML] = React.useState("");
|
||||
const fmt = React.useRef(null);
|
||||
|
||||
/* when the page is loaded, create worksheet and show table */
|
||||
React.useEffect(() => {
|
||||
/* Create worksheet from simple data */
|
||||
const data = [
|
||||
[ "Width" , 10, 20, 30, 40, 50, 20, 20, ],
|
||||
[ "Level" , 0, 1, 2, 3, 3, 1, 0, ],
|
||||
[ "Hidden" , 0, 0, 0, 0, 0, 0, 0, 1 ]
|
||||
];
|
||||
const ws = XLSX.utils.aoa_to_sheet(data);
|
||||
/* set column metadata */
|
||||
ws["!cols"] = [];
|
||||
for(let i = 1; i <= 8; ++i) {
|
||||
const r = {};
|
||||
if(data[0][i] != null) (ws["!cols"][i] = r).wpx = data[0][i];
|
||||
if(data[1][i] != null) (ws["!cols"][i] = r).level = data[1][i];
|
||||
if(data[2][i] != null) (ws["!cols"][i] = r).hidden = data[2][i];
|
||||
}
|
||||
|
||||
/* save worksheet object for the export */
|
||||
setWS(ws);
|
||||
/* generate the HTML table */
|
||||
setHTML(XLSX.utils.sheet_to_html(ws));
|
||||
}, []);
|
||||
|
||||
const xport = (fmt) => {
|
||||
/* Export to file (start a download) */
|
||||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "Formats");
|
||||
XLSX.writeFile(wb, `SheetJSColProps.${fmt}`, {cellStyles: true});
|
||||
};
|
||||
|
||||
const fmts = ["xlsx", "xlsb", "xls", "slk"];
|
||||
return ( <>
|
||||
<b>File format: </b>
|
||||
<select ref={fmt}>{fmts.map(f=>(<option value={f}>{f}</option>))}</select>
|
||||
<br/><button onClick={()=>xport(fmt.current.value)}><b>Export!</b></button>
|
||||
<div dangerouslySetInnerHTML={{__html}}/>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Functions
|
||||
|
||||
:::caution pass
|
||||
|
||||
**Column processing must be explicitly enabled!**
|
||||
|
||||
:::
|
||||
|
||||
Functions creating worksheet objects are not guaranteed to generate the `!cols`
|
||||
array. Writers are not guaranteed to export column metadata.
|
||||
|
||||
#### Reading Files
|
||||
|
||||
[`read` and `readFile`](/docs/api/parse-options) accept an options argument. The
|
||||
`cellStyles` option must be set to `true` to generate column properties:
|
||||
|
||||
```js
|
||||
var wb = XLSX.read(data, {/* ... other options , */ cellStyles: true});
|
||||
```
|
||||
|
||||
#### Writing Files
|
||||
|
||||
[`write` and `writeFile`](/docs/api/write-options) accept an options argument.
|
||||
The `cellStyles` option must be set to `true` to export column properties:
|
||||
|
||||
```js
|
||||
XLSX.writeFile(wb, "SheetSColProps.xlsx", {/* ...opts , */ cellStyles: true});
|
||||
```
|
||||
|
||||
#### Exporting Data
|
||||
|
||||
[`sheet_to_csv`](/docs/api/utilities/csv#delimiter-separated-output) and
|
||||
[`sheet_to_json`](/docs/api/utilities/array#array-output) accept options. If the
|
||||
`skipHidden` option is set to true, hidden columns will not be exported:
|
||||
|
||||
```js
|
||||
var ws = wb.Sheets[wb.SheetNames[0]]; // first worksheet
|
||||
var csv = XLSX.utils.sheet_to_csv(ws, {/* ...opts, */ skipHidden: true});
|
||||
```
|
||||
|
||||
## Storage
|
||||
|
||||
The `!cols` property in a sheet object stores column-level metadata. If present,
|
||||
it is expected to be an array of column objects.
|
||||
|
||||
:::info pass
|
||||
|
||||
As explained in ["Addresses and Ranges"](/docs/csf/general#columns), SheetJS uses
|
||||
zero-indexed columns. The column metadata for Excel column "T" is stored at index
|
||||
19 of the `!cols` array.
|
||||
|
||||
:::
|
||||
|
||||
When performing operations, it is strongly recommended to test for the existence
|
||||
of the column structure.
|
||||
|
||||
This snippet checks the `!cols` array and the specific column object, creating
|
||||
them if they do not exist, before setting the `hidden` property of column "C":
|
||||
|
||||
```js
|
||||
/* Excel column "C" -> SheetJS column index 2 == XLSX.utils.decode_col("C") */
|
||||
var COL_INDEX = 2;
|
||||
|
||||
/* create !cols array if it does not exist */
|
||||
if(!ws["!cols"]) ws["!cols"] = [];
|
||||
|
||||
/* create column metadata object if it does not exist */
|
||||
if(!ws["!cols"][COL_INDEX]) ws["!cols"][COL_INDEX] = {wch: 8};
|
||||
|
||||
/* set column to hidden */
|
||||
ws["!cols"][COL_INDEX].hidden = true;
|
||||
```
|
||||
|
||||
### Column Widths
|
||||
|
||||
Column widths can be specified in three ways:
|
||||
|
||||
| Property | Description | Excel UI |
|
||||
|:---------|:------------------------|:---------|
|
||||
| `wpx` | Width in screen pixels | Pixels |
|
||||
| `wch` | "inner width" in MDW ** | Width |
|
||||
| `width` | "outer width" in MDW ** | |
|
||||
|
||||
:::note pass
|
||||
|
||||
When resizing a column, Excel will show a tooltip:
|
||||
|
||||
![Resize tooltip](pathname:///colprops/xlwidth.png)
|
||||
|
||||
`wpx` stores the "pixels" field (`65` in the diagram) for certain computer and
|
||||
font settings.
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>MDW (Max Digit Width)</b> (click to show)</summary>
|
||||
|
||||
**`MDW`**
|
||||
|
||||
"MDW" stands for "Max Digit Width", the maximum width of the numeric characters
|
||||
(`0`, `1`, ..., `9`) using the first font specified in the file. For most common
|
||||
fonts and text scaling settings, this is the width of `0` measured in pixels.
|
||||
|
||||
Parsers will save the estimated pixel width of the `0` digit to the `MDW`
|
||||
property of the column object. It is always a positive integer.
|
||||
|
||||
**`width`**
|
||||
|
||||
`width` is the distance from "gridline before the current column" to "gridline
|
||||
before the next column" divided by MDW and rounded to the nearest `1/256`.
|
||||
|
||||
**`wch`**
|
||||
|
||||
Table cells in Excel include 2 pixels of padding on each side. The vertical
|
||||
gridline is one pixel wide. In total, the `width` includes 5 pixels of padding.
|
||||
|
||||
`wch` is the "inner width", calculated by subtracting the 5 pixels from `width`.
|
||||
`wch` is also measured in MDW units rounded to the nearest `1/256`.
|
||||
|
||||
**Diagram**
|
||||
|
||||
The following diagram depicts the Excel box model and the relationship between
|
||||
`width`, `wpx`, `MDW` and the displayed grid:
|
||||
|
||||
![Box diagram](pathname:///colprops/xlbox.png)
|
||||
|
||||
The distance between the two red lines is `width * MDW = 15` pixels. That span
|
||||
includes one gridline width (1 pixel) and two padding blocks (2 pixels each).
|
||||
|
||||
The space available for content is `wch * MDW = 15 - 5 = 10` pixels.
|
||||
|
||||
</details>
|
||||
|
||||
The following snippet sets the width of column "C" to 50 pixels:
|
||||
|
||||
```js
|
||||
const COL_WIDTH = 50;
|
||||
|
||||
/* Excel column "C" -> SheetJS column index 2 == XLSX.utils.decode_col("C") */
|
||||
var COL_INDEX = 2;
|
||||
|
||||
/* create !cols array if it does not exist */
|
||||
if(!ws["!cols"]) ws["!cols"] = [];
|
||||
|
||||
/* create column metadata object if it does not exist */
|
||||
if(!ws["!cols"][COL_INDEX]) ws["!cols"][COL_INDEX] = {wch: 8};
|
||||
|
||||
/* set column width */
|
||||
ws["!cols"][COL_INDEX].wpx = COL_WIDTH;
|
||||
```
|
||||
|
||||
### Column Visibility
|
||||
|
||||
The `hidden` property controls visibility.
|
||||
|
||||
The following snippet hides column "D":
|
||||
|
||||
```js
|
||||
/* Excel column "D" -> SheetJS column index 3 == XLSX.utils.decode_col("D") */
|
||||
var COL_INDEX = 3;
|
||||
|
||||
/* create !cols array if it does not exist */
|
||||
if(!ws["!cols"]) ws["!cols"] = [];
|
||||
|
||||
/* create column metadata object if it does not exist */
|
||||
if(!ws["!cols"][COL_INDEX]) ws["!cols"][COL_INDEX] = {wch: 8};
|
||||
|
||||
/* set column to hidden */
|
||||
ws["!cols"][COL_INDEX].hidden = true;
|
||||
```
|
||||
|
||||
### Outline Levels
|
||||
|
||||
The `level` property controls outline level / grouping. It is expected to be a
|
||||
number between `0` and `7` inclusive.
|
||||
|
||||
:::note pass
|
||||
|
||||
The Excel UI displays outline levels above the row labels. The base level
|
||||
shown in the application is `1`.
|
||||
|
||||
SheetJS is zero-indexed: the default (base) level is `0`.
|
||||
|
||||
:::
|
||||
|
||||
The following snippet sets the level of column "F" to Excel 2 / SheetJS 1:
|
||||
|
||||
```js
|
||||
/* Excel level 2 -> SheetJS level 2 - 1 = 1 */
|
||||
var LEVEL = 1;
|
||||
|
||||
/* Excel column "F" -> SheetJS column index 5 == XLSX.utils.decode_col("F") */
|
||||
var COL_INDEX = 5;
|
||||
|
||||
/* create !cols array if it does not exist */
|
||||
if(!ws["!cols"]) ws["!cols"] = [];
|
||||
|
||||
/* create column metadata object if it does not exist */
|
||||
if(!ws["!cols"][COL_INDEX]) ws["!cols"][COL_INDEX] = {wch: 8};
|
||||
|
||||
/* set level */
|
||||
ws["!cols"][COL_INDEX].level = LEVEL;
|
||||
```
|
||||
|
||||
### Grouping Columns
|
||||
|
||||
Applications treat consecutive columns with the same level as part of a "group".
|
||||
|
||||
The "Group" command typically increments the level of each column in the range:
|
||||
|
||||
```js
|
||||
/* start_col and end_col are SheetJS 0-indexed column indices */
|
||||
function grouper(ws, start_col, end_col) {
|
||||
/* create !cols array if it does not exist */
|
||||
if(!ws["!cols"]) ws["!cols"] = [];
|
||||
/* loop over every column index */
|
||||
for(var i = start_col; i <= end_col; ++i) {
|
||||
/* create column metadata object if it does not exist */
|
||||
if(!ws["!cols"][i]) ws["!cols"][i] = {wch: 8};
|
||||
/* increment level */
|
||||
ws["!cols"][i].level = 1 + (ws["!cols"][i].level || 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The "Ungroup" command typically decrements the level of each column in the range:
|
||||
|
||||
```js
|
||||
/* start_col and end_col are SheetJS 0-indexed column indices */
|
||||
function aufheben(ws, start_col, end_col) {
|
||||
/* create !cols array if it does not exist */
|
||||
if(!ws["!cols"]) ws["!cols"] = [];
|
||||
/* loop over every column index */
|
||||
for(var i = start_col; i <= end_col; ++i) {
|
||||
/* if column metadata does not exist, the level is zero -> skip */
|
||||
if(!ws["!cols"][i]) continue;
|
||||
/* if column level is not specified, the level is zero -> skip */
|
||||
if(!ws["!cols"][i].level) continue;
|
||||
/* decrement level */
|
||||
--ws["!cols"][i].level;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Grouping Symbol
|
||||
|
||||
By default, Excel displays the group collapse button on the column after the
|
||||
data. In the UI, this option is named "Summary columns to right of detail".
|
||||
|
||||
SheetJS exposes this option in the `left` property of the `"!outline"` property
|
||||
of worksheet objects. Setting this property to `true` effectively "unchecks" the
|
||||
"Summary columns to right of detail" option in Excel:
|
||||
|
||||
```js
|
||||
if(!ws["outline"]) ws["!outline"] = {};
|
||||
ws["!outline"].left = true; // show summary to left of detail
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
<details><summary><b>Details</b> (click to show)</summary>
|
||||
|
||||
**Three Width Types**
|
||||
|
||||
There are three different width types corresponding to the three different ways
|
||||
spreadsheets store column widths:
|
||||
|
||||
SYLK and other plain text formats use raw character count. Contemporaneous tools
|
||||
like Visicalc and Multiplan were character based. Since the characters had the
|
||||
same width, it sufficed to store a count. This tradition was continued into the
|
||||
BIFF formats.
|
||||
|
||||
SpreadsheetML (2003) tried to align with HTML by standardizing on screen pixel
|
||||
count throughout the file. Column widths, row heights, and other measures use
|
||||
pixels. When the pixel and character counts do not align, Excel rounds values.
|
||||
|
||||
XLSX internally stores column widths in a nebulous "Max Digit Width" form. The
|
||||
Max Digit Width is the width of the largest digit when rendered (generally the
|
||||
"0" character is the widest). The internal width must be an integer multiple of
|
||||
the width divided by 256. ECMA-376 describes a formula for converting between
|
||||
pixels and the internal width. This represents a hybrid approach.
|
||||
|
||||
Read functions attempt to populate all three properties. Write functions will
|
||||
try to cycle specified values to the desired type. In order to avoid potential
|
||||
conflicts, manipulation should delete the other properties first. For example,
|
||||
when changing the pixel width, delete the `wch` and `width` properties.
|
||||
|
||||
**Column Width Priority**
|
||||
|
||||
Even though all of the information is made available, writers are expected to
|
||||
follow the priority order:
|
||||
|
||||
1) use `width` field if available
|
||||
|
||||
2) use `wpx` pixel width if available
|
||||
|
||||
3) use `wch` character count if available
|
||||
|
||||
</details>
|
@ -17,124 +17,3 @@ The following topics are covered in sub-pages:
|
||||
<a href={item.href}>{item.label}</a>{cP?.summary && (" - " + cP.summary)}
|
||||
</li> );
|
||||
})}</ul>
|
||||
|
||||
## Row and Column Properties
|
||||
|
||||
<details>
|
||||
<summary><b>Format Support</b> (click to show)</summary>
|
||||
|
||||
**Row Properties**: XLSX/M, XLSB, BIFF8 XLS, XLML, SYLK, DOM, ODS
|
||||
|
||||
**Column Properties**: XLSX/M, XLSB, BIFF8 XLS, XLML, SYLK, DOM
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
Row and Column properties are not extracted by default when reading from a file
|
||||
and are not persisted by default when writing to a file. The option
|
||||
`cellStyles: true` must be passed to the relevant read or write function.
|
||||
|
||||
_Column Properties_
|
||||
|
||||
The `!cols` array in each worksheet, if present, is a collection of `ColInfo`
|
||||
objects which have the following properties:
|
||||
|
||||
```typescript
|
||||
type ColInfo = {
|
||||
/* visibility */
|
||||
hidden?: boolean; // if true, the column is hidden
|
||||
|
||||
/* column width is specified in one of the following ways: */
|
||||
wpx?: number; // width in screen pixels
|
||||
width?: number; // width in Excel "Max Digit Width", width*256 is integral
|
||||
wch?: number; // width in characters
|
||||
|
||||
/* other fields for preserving features from files */
|
||||
level?: number; // 0-indexed outline / group level
|
||||
MDW?: number; // Excel "Max Digit Width" unit, always integral
|
||||
};
|
||||
```
|
||||
|
||||
_Row Properties_
|
||||
|
||||
The `!rows` array in each worksheet, if present, is a collection of `RowInfo`
|
||||
objects which have the following properties:
|
||||
|
||||
```typescript
|
||||
type RowInfo = {
|
||||
/* visibility */
|
||||
hidden?: boolean; // if true, the row is hidden
|
||||
|
||||
/* row height is specified in one of the following ways: */
|
||||
hpx?: number; // height in screen pixels
|
||||
hpt?: number; // height in points
|
||||
|
||||
level?: number; // 0-indexed outline / group level
|
||||
};
|
||||
```
|
||||
|
||||
_Outline / Group Levels Convention_
|
||||
|
||||
The Excel UI displays the base outline level as `1` and the max level as `8`.
|
||||
Following JS conventions, SheetJS uses 0-indexed outline levels wherein the base
|
||||
outline level is `0` and the max level is `7`.
|
||||
|
||||
<details>
|
||||
<summary><b>Why are there three width types?</b> (click to show)</summary>
|
||||
|
||||
There are three different width types corresponding to the three different ways
|
||||
spreadsheets store column widths:
|
||||
|
||||
SYLK and other plain text formats use raw character count. Contemporaneous tools
|
||||
like Visicalc and Multiplan were character based. Since the characters had the
|
||||
same width, it sufficed to store a count. This tradition was continued into the
|
||||
BIFF formats.
|
||||
|
||||
SpreadsheetML (2003) tried to align with HTML by standardizing on screen pixel
|
||||
count throughout the file. Column widths, row heights, and other measures use
|
||||
pixels. When the pixel and character counts do not align, Excel rounds values.
|
||||
|
||||
XLSX internally stores column widths in a nebulous "Max Digit Width" form. The
|
||||
Max Digit Width is the width of the largest digit when rendered (generally the
|
||||
"0" character is the widest). The internal width must be an integer multiple of
|
||||
the width divided by 256. ECMA-376 describes a formula for converting between
|
||||
pixels and the internal width. This represents a hybrid approach.
|
||||
|
||||
Read functions attempt to populate all three properties. Write functions will
|
||||
try to cycle specified values to the desired type. In order to avoid potential
|
||||
conflicts, manipulation should delete the other properties first. For example,
|
||||
when changing the pixel width, delete the `wch` and `width` properties.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Implementation details</b> (click to show)</summary>
|
||||
|
||||
_Row Heights_
|
||||
|
||||
Excel internally stores row heights in points. The default resolution is 72 DPI
|
||||
or 96 PPI, so the pixel and point size should agree. For different resolutions
|
||||
they may not agree, so the library separates the concepts.
|
||||
|
||||
Even though all of the information is made available, writers are expected to
|
||||
follow the priority order:
|
||||
|
||||
1) use `hpx` pixel height if available
|
||||
2) use `hpt` point height if available
|
||||
|
||||
_Column Widths_
|
||||
|
||||
Given the constraints, it is possible to determine the `MDW` without actually
|
||||
inspecting the font! The parsers guess the pixel width by converting from width
|
||||
to pixels and back, repeating for all possible `MDW` and selecting the value
|
||||
that minimizes the error. XLML actually stores the pixel width, so the guess
|
||||
works in the opposite direction.
|
||||
|
||||
Even though all of the information is made available, writers are expected to
|
||||
follow the priority order:
|
||||
|
||||
1) use `width` field if available
|
||||
2) use `wpx` pixel width if available
|
||||
3) use `wch` character count if available
|
||||
|
||||
</details>
|
||||
|
@ -141,6 +141,7 @@ 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 |
|
||||
|`UTC` | false | If true, dates are interpreted using UTC methods ** |
|
||||
|`dense` | false | Emit [dense sheet object](docs/csf/sheet#dense-mode) |
|
||||
|
||||
[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option)
|
||||
|
||||
@ -279,6 +280,7 @@ default column order is determined by the first appearance of the field using
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|
||||
|`UTC` | false | If true, dates are interpreted using UTC methods ** |
|
||||
|`dense` | false | Emit [dense sheet object](docs/csf/sheet#dense-mode) |
|
||||
|
||||
[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option)
|
||||
|
||||
@ -524,6 +526,7 @@ an options argument:
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`defval` | | Use specified value in place of null or undefined |
|
||||
|`blankrows` | ** | Include blank lines in the output ** |
|
||||
|`skipHidden` | false | Do not generate objects for hidden rows/columns |
|
||||
|`UTC` | false | If true, dates will be correct in UTC ** |
|
||||
|
||||
- `raw` only affects cells which have a format code (`.z`) field or a formatted
|
||||
|
BIN
docz/static/colprops/mac.png
Normal file
BIN
docz/static/colprops/mac.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
docz/static/colprops/win.png
Normal file
BIN
docz/static/colprops/win.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
docz/static/colprops/xlbox.png
Normal file
BIN
docz/static/colprops/xlbox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
BIN
docz/static/colprops/xlwidth.png
Normal file
BIN
docz/static/colprops/xlwidth.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
docz/static/rowprops/mac.png
Normal file
BIN
docz/static/rowprops/mac.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
BIN
docz/static/rowprops/win.png
Normal file
BIN
docz/static/rowprops/win.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Loading…
Reference in New Issue
Block a user