| 
									
										
										
										
											2023-09-20 21:53:18 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: Row Properties | 
					
						
							|  |  |  | sidebar_position: 8 | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 04:47:04 +00:00
										 |  |  | <details> | 
					
						
							|  |  |  |   <summary><b>File Format Support</b> (click to show)</summary> | 
					
						
							| 
									
										
										
										
											2023-09-20 21:53:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-12 01:04:37 +00:00
										 |  |  | <table> | 
					
						
							|  |  |  |   <thead><tr><th>Excel for Windows</th><th>Excel for Mac</th></tr></thead> | 
					
						
							|  |  |  |   <tbody><tr><td> | 
					
						
							| 
									
										
										
										
											2023-09-20 21:53:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </td><td> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </td></tr></tbody></table> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 04:47:04 +00:00
										 |  |  | <details> | 
					
						
							|  |  |  |   <summary><b>Export Demo</b> (click to show)</summary> | 
					
						
							| 
									
										
										
										
											2023-09-20 21:53:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 04:47:04 +00:00
										 |  |  | <details> | 
					
						
							|  |  |  |   <summary><b>Details</b> (click to show)</summary> | 
					
						
							| 
									
										
										
										
											2023-09-20 21:53:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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> |