diff --git a/docz/docs/03-demos/05-mobile/03-quasar.md b/docz/docs/03-demos/05-mobile/03-quasar.md index 18c1c2c..48a47e3 100644 --- a/docz/docs/03-demos/05-mobile/03-quasar.md +++ b/docz/docs/03-demos/05-mobile/03-quasar.md @@ -37,7 +37,7 @@ The ["Demo"](#demo) creates an app that looks like the screenshots below: -### 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 diff --git a/docz/docs/07-csf/03-sheet.md b/docz/docs/07-csf/03-sheet.md index 8008ce9..f37c152 100644 --- a/docz/docs/07-csf/03-sheet.md +++ b/docz/docs/07-csf/03-sheet.md @@ -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 diff --git a/docz/docs/07-csf/07-features/08-rowprops.md b/docz/docs/07-csf/07-features/08-rowprops.md new file mode 100644 index 0000000..cb8cb50 --- /dev/null +++ b/docz/docs/07-csf/07-features/08-rowprops.md @@ -0,0 +1,361 @@ +--- +title: Row Properties +sidebar_position: 8 +--- + +
+ File Format Support (click to show) + +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. + +
+ +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. + + + + +
Excel for WindowsExcel for Mac
+ +![Excel for Windows](pathname:///rowprops/win.png) + + + +![Excel for Mac](pathname:///rowprops/mac.png) + +
+ +
Export Demo (click to show) + +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 ( <> + File format: + +
+
+ ); +} +``` + +
+ +## 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 (click to show) + +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 + +
diff --git a/docz/docs/07-csf/07-features/09-colprops.md b/docz/docs/07-csf/07-features/09-colprops.md new file mode 100644 index 0000000..b4e9362 --- /dev/null +++ b/docz/docs/07-csf/07-features/09-colprops.md @@ -0,0 +1,418 @@ +--- +title: Column Properties +sidebar_position: 9 +--- + +
+ File Format Support (click to show) + +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. + +
+ +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. + + + + +
Excel for WindowsExcel for Mac
+ +![Excel for Windows](pathname:///colprops/win.png) + + + +![Excel for Mac](pathname:///colprops/mac.png) + +
+ +
Export Demo (click to show) + +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 ( <> + File format: + +
+
+ ); +} +``` + +
+ +## 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. + +::: + +
MDW (Max Digit Width) (click to show) + +**`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. + +
+ +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 (click to show) + +**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 + +
diff --git a/docz/docs/07-csf/07-features/index.md b/docz/docs/07-csf/07-features/index.md index d969e29..ca9633a 100644 --- a/docz/docs/07-csf/07-features/index.md +++ b/docz/docs/07-csf/07-features/index.md @@ -17,124 +17,3 @@ The following topics are covered in sub-pages: {item.label}{cP?.summary && (" - " + cP.summary)} ); })} - -## Row and Column Properties - -
- Format Support (click to show) - -**Row Properties**: XLSX/M, XLSB, BIFF8 XLS, XLML, SYLK, DOM, ODS - -**Column Properties**: XLSX/M, XLSB, BIFF8 XLS, XLML, SYLK, DOM - -
- - -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`. - -
- Why are there three width types? (click to show) - -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. - -
- -
- Implementation details (click to show) - -_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 - -
diff --git a/docz/docs/08-api/07-utilities/01-array.md b/docz/docs/08-api/07-utilities/01-array.md index b7e3ce5..a27c0b1 100644 --- a/docz/docs/08-api/07-utilities/01-array.md +++ b/docz/docs/08-api/07-utilities/01-array.md @@ -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 diff --git a/docz/static/colprops/mac.png b/docz/static/colprops/mac.png new file mode 100644 index 0000000..3a160f0 Binary files /dev/null and b/docz/static/colprops/mac.png differ diff --git a/docz/static/colprops/win.png b/docz/static/colprops/win.png new file mode 100644 index 0000000..ce1b42e Binary files /dev/null and b/docz/static/colprops/win.png differ diff --git a/docz/static/colprops/xlbox.png b/docz/static/colprops/xlbox.png new file mode 100644 index 0000000..f4cdeeb Binary files /dev/null and b/docz/static/colprops/xlbox.png differ diff --git a/docz/static/colprops/xlwidth.png b/docz/static/colprops/xlwidth.png new file mode 100644 index 0000000..0067512 Binary files /dev/null and b/docz/static/colprops/xlwidth.png differ diff --git a/docz/static/rowprops/mac.png b/docz/static/rowprops/mac.png new file mode 100644 index 0000000..97976bb Binary files /dev/null and b/docz/static/rowprops/mac.png differ diff --git a/docz/static/rowprops/win.png b/docz/static/rowprops/win.png new file mode 100644 index 0000000..ce5386f Binary files /dev/null and b/docz/static/rowprops/win.png differ