11 KiB
title | sidebar_position |
---|---|
Row Properties | 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 Windows | Excel for Mac |
---|---|
Export Demo (click to show)
The table lists the assigned heights, outline levels and visibility settings.
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}}/>
</> );
}
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
accept an options argument. The
cellStyles
option must be set to true
to generate row properties:
var wb = XLSX.read(data, {/* ... other options , */ cellStyles: true});
Writing Files
write
and writeFile
accept an options argument.
The cellStyles
option must be set to true
to export row properties:
XLSX.writeFile(wb, "SheetJSRowProps.xlsx", {/* ...opts , */ cellStyles: true});
Importing HTML Tables
table_to_book
and table_to_sheet
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:
/* 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:
/* 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
and
sheet_to_json
accept options. If the
skipHidden
option is set to true, hidden rows will not be exported:
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", 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:
/* 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:
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:
/* 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:
/* 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:
/* 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:
/* 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:
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:
-
use
hpx
pixel height if available -
use
hpt
point height if available