@rowsncolumns/toolkit 24.4.2 → 24.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/cjs/excel-parser/cfb-decryptor.d.ts +6 -0
  2. package/dist/cjs/excel-parser/cfb-decryptor.d.ts.map +1 -1
  3. package/dist/cjs/excel-parser/cfb-decryptor.js +6 -0
  4. package/dist/cjs/excel-parser/helpers.d.ts +9 -1
  5. package/dist/cjs/excel-parser/helpers.d.ts.map +1 -1
  6. package/dist/cjs/excel-parser/helpers.js +37 -0
  7. package/dist/cjs/excel-parser/interface.d.ts +15 -2
  8. package/dist/cjs/excel-parser/interface.d.ts.map +1 -1
  9. package/dist/cjs/excel-parser/plugins/base/index.d.ts +2 -0
  10. package/dist/cjs/excel-parser/plugins/base/index.d.ts.map +1 -1
  11. package/dist/cjs/excel-parser/plugins/base/index.js +3 -0
  12. package/dist/cjs/excel-parser/plugins/ods/index.d.ts +19 -0
  13. package/dist/cjs/excel-parser/plugins/ods/index.d.ts.map +1 -1
  14. package/dist/cjs/excel-parser/plugins/ods/index.js +676 -304
  15. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts +43 -1
  16. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  17. package/dist/cjs/excel-parser/plugins/ods/styles.js +343 -45
  18. package/dist/cjs/excel-parser/plugins/xls/index.d.ts +55 -1
  19. package/dist/cjs/excel-parser/plugins/xls/index.d.ts.map +1 -1
  20. package/dist/cjs/excel-parser/plugins/xls/index.js +518 -6
  21. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts +4 -0
  22. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  23. package/dist/cjs/excel-parser/plugins/xlsb/index.js +33 -14
  24. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  25. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  26. package/dist/cjs/excel-parser/plugins/xlsx/chartex.js +244 -0
  27. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts +10 -0
  28. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  29. package/dist/cjs/excel-parser/plugins/xlsx/charts.js +68 -9
  30. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
  31. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  32. package/dist/cjs/excel-parser/plugins/xlsx/drawing.js +155 -20
  33. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  34. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  35. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.js +295 -0
  36. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +35 -2
  37. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  38. package/dist/cjs/excel-parser/plugins/xlsx/index.js +737 -257
  39. package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  40. package/dist/cjs/excel-parser/plugins/xlsx/pivots.js +125 -37
  41. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
  42. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
  43. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.js +4 -1
  44. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  45. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  46. package/dist/cjs/excel-parser/plugins/xlsx/styles.js +102 -6
  47. package/dist/cjs/excel-parser/registry.d.ts +7 -0
  48. package/dist/cjs/excel-parser/registry.d.ts.map +1 -1
  49. package/dist/cjs/excel-parser/registry.js +29 -0
  50. package/dist/cjs/excel-parser/types.d.ts +17 -2
  51. package/dist/cjs/excel-parser/types.d.ts.map +1 -1
  52. package/dist/cjs/excel-parser/workbook.d.ts +3 -0
  53. package/dist/cjs/excel-parser/workbook.d.ts.map +1 -1
  54. package/dist/cjs/excel-parser/workbook.js +24 -14
  55. package/dist/cjs/excel-parser/worker.js +131 -131
  56. package/dist/cjs/exporter/ods/ods-export.d.ts.map +1 -1
  57. package/dist/cjs/exporter/ods/ods-export.js +432 -175
  58. package/dist/cjs/exporter/xlsx/chart-builder.d.ts.map +1 -1
  59. package/dist/cjs/exporter/xlsx/chart-builder.js +215 -39
  60. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts +36 -0
  61. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  62. package/dist/cjs/exporter/xlsx/chartex-builder.js +109 -0
  63. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts +61 -0
  64. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  65. package/dist/cjs/exporter/xlsx/form-controls-builder.js +197 -0
  66. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts +8 -0
  67. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  68. package/dist/cjs/exporter/xlsx/pivot-builder.js +141 -42
  69. package/dist/cjs/exporter/xlsx/style-builder.js +9 -3
  70. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
  71. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
  72. package/dist/cjs/exporter/xlsx/threaded-comments-builder.js +15 -3
  73. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts +11 -2
  74. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  75. package/dist/cjs/exporter/xlsx/xlsx-export.js +991 -297
  76. package/dist/cjs/helpers/implicit-intersection.d.ts +16 -0
  77. package/dist/cjs/helpers/implicit-intersection.d.ts.map +1 -0
  78. package/dist/cjs/helpers/implicit-intersection.js +197 -0
  79. package/dist/cjs/print-settings.d.ts +105 -0
  80. package/dist/cjs/print-settings.d.ts.map +1 -0
  81. package/dist/cjs/print-settings.js +494 -0
  82. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  83. package/dist/esm/excel-parser/cfb-decryptor.d.ts +6 -0
  84. package/dist/esm/excel-parser/cfb-decryptor.d.ts.map +1 -1
  85. package/dist/esm/excel-parser/cfb-decryptor.js +6 -0
  86. package/dist/esm/excel-parser/helpers.d.ts +9 -1
  87. package/dist/esm/excel-parser/helpers.d.ts.map +1 -1
  88. package/dist/esm/excel-parser/helpers.js +34 -0
  89. package/dist/esm/excel-parser/interface.d.ts +15 -2
  90. package/dist/esm/excel-parser/interface.d.ts.map +1 -1
  91. package/dist/esm/excel-parser/plugins/base/index.d.ts +2 -0
  92. package/dist/esm/excel-parser/plugins/base/index.d.ts.map +1 -1
  93. package/dist/esm/excel-parser/plugins/base/index.js +3 -0
  94. package/dist/esm/excel-parser/plugins/ods/index.d.ts +19 -0
  95. package/dist/esm/excel-parser/plugins/ods/index.d.ts.map +1 -1
  96. package/dist/esm/excel-parser/plugins/ods/index.js +347 -33
  97. package/dist/esm/excel-parser/plugins/ods/styles.d.ts +43 -1
  98. package/dist/esm/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  99. package/dist/esm/excel-parser/plugins/ods/styles.js +276 -2
  100. package/dist/esm/excel-parser/plugins/xls/index.d.ts +55 -1
  101. package/dist/esm/excel-parser/plugins/xls/index.d.ts.map +1 -1
  102. package/dist/esm/excel-parser/plugins/xls/index.js +441 -3
  103. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts +4 -0
  104. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  105. package/dist/esm/excel-parser/plugins/xlsb/index.js +30 -9
  106. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  107. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  108. package/dist/esm/excel-parser/plugins/xlsx/chartex.js +199 -0
  109. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts +10 -0
  110. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  111. package/dist/esm/excel-parser/plugins/xlsx/charts.js +69 -6
  112. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
  113. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  114. package/dist/esm/excel-parser/plugins/xlsx/drawing.js +99 -0
  115. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  116. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  117. package/dist/esm/excel-parser/plugins/xlsx/form-controls.js +246 -0
  118. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +35 -2
  119. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  120. package/dist/esm/excel-parser/plugins/xlsx/index.js +454 -32
  121. package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  122. package/dist/esm/excel-parser/plugins/xlsx/pivots.js +86 -6
  123. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
  124. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
  125. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.js +2 -0
  126. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  127. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  128. package/dist/esm/excel-parser/plugins/xlsx/styles.js +92 -2
  129. package/dist/esm/excel-parser/registry.d.ts +7 -0
  130. package/dist/esm/excel-parser/registry.d.ts.map +1 -1
  131. package/dist/esm/excel-parser/registry.js +19 -0
  132. package/dist/esm/excel-parser/types.d.ts +17 -2
  133. package/dist/esm/excel-parser/types.d.ts.map +1 -1
  134. package/dist/esm/excel-parser/workbook.d.ts +3 -0
  135. package/dist/esm/excel-parser/workbook.d.ts.map +1 -1
  136. package/dist/esm/excel-parser/workbook.js +19 -10
  137. package/dist/esm/excel-parser/worker.js +12 -18
  138. package/dist/esm/exporter/ods/ods-export.d.ts.map +1 -1
  139. package/dist/esm/exporter/ods/ods-export.js +306 -35
  140. package/dist/esm/exporter/xlsx/chart-builder.d.ts.map +1 -1
  141. package/dist/esm/exporter/xlsx/chart-builder.js +161 -28
  142. package/dist/esm/exporter/xlsx/chartex-builder.d.ts +36 -0
  143. package/dist/esm/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  144. package/dist/esm/exporter/xlsx/chartex-builder.js +97 -0
  145. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts +61 -0
  146. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  147. package/dist/esm/exporter/xlsx/form-controls-builder.js +173 -0
  148. package/dist/esm/exporter/xlsx/pivot-builder.d.ts +8 -0
  149. package/dist/esm/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  150. package/dist/esm/exporter/xlsx/pivot-builder.js +104 -19
  151. package/dist/esm/exporter/xlsx/style-builder.js +9 -3
  152. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
  153. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
  154. package/dist/esm/exporter/xlsx/threaded-comments-builder.js +15 -3
  155. package/dist/esm/exporter/xlsx/xlsx-export.d.ts +11 -2
  156. package/dist/esm/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  157. package/dist/esm/exporter/xlsx/xlsx-export.js +675 -64
  158. package/dist/esm/helpers/implicit-intersection.d.ts +16 -0
  159. package/dist/esm/helpers/implicit-intersection.d.ts.map +1 -0
  160. package/dist/esm/helpers/implicit-intersection.js +184 -0
  161. package/dist/esm/print-settings.d.ts +105 -0
  162. package/dist/esm/print-settings.d.ts.map +1 -0
  163. package/dist/esm/print-settings.js +422 -0
  164. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  165. package/package.json +3 -3
  166. package/xlsx.d.ts +14 -0
@@ -2,9 +2,10 @@ import { addressToCell, addressToSelection, alpha2number, checkIfStringIsReferen
2
2
  import { XMLParser } from "fast-xml-parser";
3
3
  import { get } from "lodash-es";
4
4
  import { Parser as HtmlParser } from "htmlparser2";
5
- import { createFilterSpecsFromAutoFilter, excelColumnWidthToPixels, findMax, getRangeFromAddressRef, } from "../../helpers";
5
+ import { createFilterSpecsFromAutoFilter, excelColumnWidthToPixels, findMax, getRangeFromAddressRef, parseTableColumnTotals, } from "../../helpers";
6
6
  import { defaultSpreadsheetTheme } from "../../theme-default";
7
7
  import { Unescape } from "../../utils";
8
+ import { compactPrintSettings, isBuiltinPrintName, isDefaultPageMargins, parsePrintAreaFormula, parsePrintTitlesFormula, PRINT_AREA_NAME, } from "../../../print-settings";
8
9
  import { StreamingZipParser } from "../../zip-parser-streaming";
9
10
  import { SheetDataValidationStamper } from "../../dv-cell-stamp";
10
11
  import { BaseWorkbookPlugin } from "../base/index";
@@ -12,12 +13,14 @@ import { processChart } from "./charts";
12
13
  import { customFiltersToCondition, dynamicFilterToCondition, } from "../../../autofilter-condition";
13
14
  import { getConditionalFormattingFromSheet } from "./conditional-formatting";
14
15
  import { getDataValidationsForSheet as parseDataValidationsFromSheetData } from "./data-validations";
15
- import { processAnchors } from "./drawing";
16
+ import { anchorsInDocumentOrder, processAnchors, } from "./drawing";
16
17
  import { getRelationsById } from "./relationships";
17
18
  import { hasPowerQueryParts, } from "../../../power-query";
18
19
  import { extractSheetViewProperties } from "./sheet-views";
19
20
  import { EMPTY_SHEET_THREADED_COMMENTS, parsePersons, parseThreadedComments, } from "./threaded-comments";
20
- import { extractColor, fontNodeToTextFormat, getCellDataForStyleIndex, getCellValueAndFormat, } from "./styles";
21
+ import { getChartExReferenceFromAnchor, processChartEx } from "./chartex";
22
+ import { buildFormControlEmbeds, parseFormControlPr, parseVmlControlCaptions, readLegacyDrawingRelId, readWorksheetControls, } from "./form-controls";
23
+ import { extractColor, fontNodeToTextFormat, getCellDataForStyleIndex, getCellValueAndFormat, resolveNamedCellStyles, } from "./styles";
21
24
  import { extractThemeColors, extractThemeFonts, generateDarkThemeColors, } from "./theme";
22
25
  export const XMLTagProcessor = (name, value) => Unescape(value);
23
26
  function getWithFallback(source, paths) {
@@ -739,6 +742,18 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
739
742
  * `getDataValidations()` aggregates these per-sheet caches, keeping ids
740
743
  * stable across per-sheet and workbook-wide callers.
741
744
  */
745
+ /**
746
+ * `<protectedRanges>` per sheet, populated while `getSheets` builds each
747
+ * `Sheet` (the element sits after `<sheetData>` in the worksheet part, so it
748
+ * rides the same geometry pass). Read back via `getProtectedRanges`.
749
+ */
750
+ protectedRangesBySheet = new Map();
751
+ /**
752
+ * The builtin `_xlnm.Print_Area` / `_xlnm.Print_Titles` defined names,
753
+ * hoisted out of `namedRanges` (they are sheet-scoped facets, not user
754
+ * names) and merged into each sheet's `printSettings` by `getSheets()`.
755
+ */
756
+ printNamesBySheetId = new Map();
742
757
  dataValidationsBySheetCache = new Map();
743
758
  /** Per-sheet memo for conditional formatting, mirroring the DV cache. */
744
759
  conditionalFormattingBySheetCache = new Map();
@@ -784,6 +799,26 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
784
799
  let paneAttrs;
785
800
  let tabColor;
786
801
  let autoFilterRef;
802
+ // `<sheetProtection>` + `<protectedRanges>/<protectedRange>` — the sheet's
803
+ // protection facets, read here because both sit after `<sheetData>`.
804
+ let sheetProtection;
805
+ const protectedRangeEntries = [];
806
+ // Print facets (`CT_Worksheet` tail: printOptions / pageMargins /
807
+ // pageSetup / headerFooter / rowBreaks / colBreaks) plus the
808
+ // `<sheetPr><pageSetUpPr fitToPage>` flag. `_xlnm.Print_Area` /
809
+ // `_xlnm.Print_Titles` come from the workbook's defined names and are
810
+ // merged in by `getSheets()`.
811
+ let pageSetup;
812
+ let pageMargins;
813
+ let printOptions;
814
+ let fitToPage = false;
815
+ let headerFooter;
816
+ // The `<oddHeader>`-style element whose text is streaming in.
817
+ let headerFooterTextTarget;
818
+ const rowBreaks = [];
819
+ const columnBreaks = [];
820
+ // Inside `<rowBreaks>` ("row") / `<colBreaks>` ("column"); routes `<brk>`.
821
+ let breakAxis;
787
822
  const filterColumns = new Map();
788
823
  const getOrCreateFilterColumn = (colId) => {
789
824
  let entry = filterColumns.get(colId);
@@ -800,10 +835,21 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
800
835
  // r-less sheets still report real extents instead of 0.
801
836
  let lastScannedRowIndex = 0;
802
837
  let scanSeqColIndex = 1;
838
+ // `<customSheetViews>` (Excel's View → Custom Views) carry their own
839
+ // pane / selection / autoFilter / print setup / breaks. They describe a
840
+ // saved view, not the sheet, so the whole subtree is skipped — a custom
841
+ // view's `<oddHeader>` or `<brk>` must not become the sheet's.
842
+ let inCustomSheetViews = false;
803
843
  const normalizeTag = (name) => name.includes(":") ? name.split(":")[1] : name;
804
844
  const parser = new HtmlParser({
805
845
  onopentag(tagName, attrs) {
806
846
  const name = normalizeTag(tagName);
847
+ if (name === "customSheetViews") {
848
+ inCustomSheetViews = true;
849
+ return;
850
+ }
851
+ if (inCustomSheetViews)
852
+ return;
807
853
  if (name === "dimension") {
808
854
  const ref = attrs?.ref;
809
855
  if (typeof ref === "string") {
@@ -849,6 +895,50 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
849
895
  if (name === "tabColor") {
850
896
  tabColor = { a$: { ...attrs } };
851
897
  }
898
+ if (name === "sheetProtection") {
899
+ sheetProtection = readSheetProtectionAttrs(attrs);
900
+ }
901
+ if (name === "protectedRange") {
902
+ const sqref = attrs.sqref;
903
+ if (typeof sqref === "string" && sqref) {
904
+ protectedRangeEntries.push({
905
+ sqref,
906
+ name: attrs.name,
907
+ securityDescriptor: attrs.securityDescriptor,
908
+ });
909
+ }
910
+ }
911
+ if (name === "pageSetUpPr") {
912
+ fitToPage = isXmlTrue(attrs?.fitToPage);
913
+ }
914
+ if (name === "pageSetup") {
915
+ pageSetup = readPageSetupAttrs(attrs);
916
+ }
917
+ if (name === "pageMargins") {
918
+ pageMargins = readPageMarginsAttrs(attrs);
919
+ }
920
+ if (name === "printOptions") {
921
+ printOptions = readPrintOptionsAttrs(attrs);
922
+ }
923
+ if (name === "headerFooter") {
924
+ headerFooter = readHeaderFooterAttrs(attrs);
925
+ }
926
+ if (isHeaderFooterTextKey(name)) {
927
+ headerFooterTextTarget = name;
928
+ headerFooter ??= {};
929
+ }
930
+ if (name === "rowBreaks")
931
+ breakAxis = "row";
932
+ if (name === "colBreaks")
933
+ breakAxis = "column";
934
+ if (name === "brk" && breakAxis) {
935
+ // Only manual breaks are user state; Excel drops automatic ones
936
+ // (`man` absent) on save as well.
937
+ const id = parseInt(attrs?.id ?? "", 10);
938
+ if (Number.isFinite(id) && id > 0 && isXmlTrue(attrs?.man)) {
939
+ (breakAxis === "row" ? rowBreaks : columnBreaks).push(id);
940
+ }
941
+ }
852
942
  if (name === "sheetView" && !sheetViewAttrs) {
853
943
  sheetViewAttrs = { ...attrs };
854
944
  }
@@ -1037,11 +1127,29 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
1037
1127
  }
1038
1128
  }
1039
1129
  },
1130
+ ontext(text) {
1131
+ if (headerFooterTextTarget && headerFooter) {
1132
+ headerFooter[headerFooterTextTarget] =
1133
+ `${headerFooter[headerFooterTextTarget] ?? ""}${text}`;
1134
+ }
1135
+ },
1040
1136
  onclosetag(tagName) {
1041
1137
  const name = normalizeTag(tagName);
1138
+ if (name === "customSheetViews") {
1139
+ inCustomSheetViews = false;
1140
+ return;
1141
+ }
1142
+ if (inCustomSheetViews)
1143
+ return;
1042
1144
  if (name === "filterColumn") {
1043
1145
  currentFilterColumn = null;
1044
1146
  }
1147
+ if (isHeaderFooterTextKey(name)) {
1148
+ headerFooterTextTarget = undefined;
1149
+ }
1150
+ if (name === "rowBreaks" || name === "colBreaks") {
1151
+ breakAxis = undefined;
1152
+ }
1045
1153
  },
1046
1154
  onerror(err) {
1047
1155
  console.error("Streaming sheet metadata parse error", err);
@@ -1114,6 +1222,18 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
1114
1222
  tablePartIds,
1115
1223
  outlineSummaryBelow,
1116
1224
  outlineSummaryRight,
1225
+ sheetProtection,
1226
+ protectedRangeEntries,
1227
+ printSettings: compactPrintSettings({
1228
+ pageSetup: fitToPage ? { ...pageSetup, fitToPage: true } : pageSetup,
1229
+ // Every Excel worksheet carries `<pageMargins>`; only non-default
1230
+ // margins are user state worth modelling.
1231
+ pageMargins: isDefaultPageMargins(pageMargins) ? undefined : pageMargins,
1232
+ printOptions,
1233
+ headerFooter,
1234
+ rowBreaks,
1235
+ columnBreaks,
1236
+ }),
1117
1237
  };
1118
1238
  }
1119
1239
  /**
@@ -1292,6 +1412,7 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
1292
1412
  conditionalFormatting: false,
1293
1413
  dataValidations: false,
1294
1414
  drawing: false,
1415
+ controls: false,
1295
1416
  };
1296
1417
  const sheetPath = this.resolveSheetPath(relation.target);
1297
1418
  const sheetRelPath = sheetPath.replace("worksheets", "worksheets/_rels") + ".rels";
@@ -1345,6 +1466,9 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
1345
1466
  case "drawing":
1346
1467
  features.drawing = true;
1347
1468
  break;
1469
+ case "controls":
1470
+ features.controls = true;
1471
+ break;
1348
1472
  }
1349
1473
  if (name !== "hyperlink") {
1350
1474
  return;
@@ -1816,6 +1940,7 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
1816
1940
  this.sheetMetadataCache.clear();
1817
1941
  this.dataValidationsBySheetCache.clear();
1818
1942
  this.conditionalFormattingBySheetCache.clear();
1943
+ this.protectedRangesBySheet.clear();
1819
1944
  await this.loadWorkbookXml();
1820
1945
  this.relations = await this.getRelations();
1821
1946
  this.workbookStyles = await WorkbookStyles.load(this.zipParser, this.xmlParser);
@@ -1835,6 +1960,7 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
1835
1960
  this.sheetMetadataCache.clear();
1836
1961
  this.dataValidationsBySheetCache.clear();
1837
1962
  this.conditionalFormattingBySheetCache.clear();
1963
+ this.protectedRangesBySheet.clear();
1838
1964
  this.worksheetBySheetId.clear();
1839
1965
  }
1840
1966
  clearSharedFormula() {
@@ -1924,7 +2050,10 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
1924
2050
  : [];
1925
2051
  const columns = columnDefsArray.map((colDef) => {
1926
2052
  const name = colDef.a$.name || "";
1927
- const columnObj = { name };
2053
+ const columnObj = {
2054
+ name,
2055
+ ...parseTableColumnTotals(colDef),
2056
+ };
1928
2057
  // Check for calculated column
1929
2058
  // Handle both with and without namespace prefix
1930
2059
  const calculatedColumnFormula = get(colDef, "calculatedColumnFormula") ||
@@ -2798,6 +2927,19 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
2798
2927
  for (const anchor of anchors) {
2799
2928
  const chartRef = getChartReferenceFromAnchor(anchor);
2800
2929
  if (!chartRef) {
2930
+ // Excel 2016+ chartex (treemap / sunburst / histogram …) anchors
2931
+ // carry `<cx:chart r:id>` inside an mc:AlternateContent choice.
2932
+ const chartExRef = getChartExReferenceFromAnchor(anchor);
2933
+ const chartExRId = get(chartExRef, "a$.r:id") || get(chartExRef, "a$.id");
2934
+ const chartExRel = chartExRId
2935
+ ? drawingRelsArray.find((rel) => get(rel, "a$.Id") === chartExRId ||
2936
+ get(rel, "a$.id") === chartExRId)
2937
+ : undefined;
2938
+ if (chartExRel) {
2939
+ const chartEx = await processChartEx(chartExRel.a$.Target, drawingPath, anchor, sheetId, this.zipParser, this.xmlParser, sheetDimensions, resolveSheetId);
2940
+ if (chartEx)
2941
+ charts.push(chartEx);
2942
+ }
2801
2943
  continue;
2802
2944
  }
2803
2945
  const chartRId = get(chartRef, "a$.r:id") ||
@@ -2878,28 +3020,17 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
2878
3020
  ? drawingPath.substring(1)
2879
3021
  : `xl/${drawingPath}`;
2880
3022
  }
2881
- const drawingContent = await this.zipParser.getText(drawingPath);
3023
+ const drawingContent = (await this.zipParser.getText(drawingPath)) ?? "";
2882
3024
  // Parse drawing XML
2883
- const drawing = this.xmlParser.parse(drawingContent ?? "");
2884
- // Extract image anchors - both absolute and cell anchors
2885
- // Handle different XML namespaces that might be used
2886
- const twoCellAnchors = get(drawing, "xdr:wsDr.xdr:twoCellAnchor") ||
2887
- get(drawing, "wsDr.twoCellAnchor");
2888
- const oneCellAnchors = get(drawing, "xdr:wsDr.xdr:oneCellAnchor") ||
2889
- get(drawing, "wsDr.oneCellAnchor");
2890
- const absoluteAnchors = get(drawing, "xdr:wsDr.xdr:absoluteAnchor") ||
2891
- get(drawing, "wsDr.absoluteAnchor");
2892
- // One cell
2893
- for (const image of await processAnchors(oneCellAnchors, "oneCellAnchor", drawingPath, sheetId, this.zipParser, this.xmlParser)) {
2894
- images.push(image);
2895
- }
2896
- // Two cell
2897
- for (const image of await processAnchors(twoCellAnchors, "twoCellAnchors", drawingPath, sheetId, this.zipParser, this.xmlParser)) {
2898
- images.push(image);
2899
- }
2900
- // absoluteAnchors
2901
- for (const image of await processAnchors(absoluteAnchors, "absoluteAnchors", drawingPath, sheetId, this.zipParser, this.xmlParser)) {
2902
- images.push(image);
3025
+ const drawing = this.xmlParser.parse(drawingContent);
3026
+ // Anchor order in the drawing part is Excel's z-order (first = back).
3027
+ // The parse groups anchors by element name, so the document order
3028
+ // across `oneCellAnchor` / `twoCellAnchor` / `absoluteAnchor` is
3029
+ // recovered from the raw part and each anchor processed in that order.
3030
+ for (const anchor of anchorsInDocumentOrder(drawing, drawingContent)) {
3031
+ for (const image of await processAnchors(anchor.node, anchor.kind, drawingPath, sheetId, this.zipParser, this.xmlParser)) {
3032
+ images.push(image);
3033
+ }
2903
3034
  }
2904
3035
  }
2905
3036
  }
@@ -2924,6 +3055,10 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
2924
3055
  getTheme() {
2925
3056
  return this.theme ?? defaultSpreadsheetTheme;
2926
3057
  }
3058
+ /** `<cellStyles>` resolved to cell formats (toolbar "Workbook styles" gallery). */
3059
+ getNamedCellStyles() {
3060
+ return resolveNamedCellStyles(this.workbookStyles);
3061
+ }
2927
3062
  /**
2928
3063
  * The workbook default font — styles.xml fonts[0], the font every cell
2929
3064
  * without an explicit font inherits. Exporters pass this through so the
@@ -2949,7 +3084,43 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
2949
3084
  _getSheets() {
2950
3085
  return this.workSheets;
2951
3086
  }
3087
+ /**
3088
+ * Resolve a builtin print name to its sheet (`localSheetId` indexes the
3089
+ * `<sheets>` order; a name without scope falls back to the sheet named in
3090
+ * the formula) and record the parsed print area / titles for `getSheets()`.
3091
+ */
3092
+ stashBuiltinPrintName(name, expression, localSheetId, sheetIdBySheetName) {
3093
+ if (!expression || expression.includes("#REF!"))
3094
+ return;
3095
+ const parsed = name === PRINT_AREA_NAME
3096
+ ? parsePrintAreaFormula(expression)
3097
+ : parsePrintTitlesFormula(expression);
3098
+ if (!parsed)
3099
+ return;
3100
+ let sheetId;
3101
+ if (localSheetId !== undefined) {
3102
+ const index = parseInt(localSheetId, 10);
3103
+ const sheetEl = this._getSheets()[index];
3104
+ const id = Number(sheetEl?.a$?.sheetId);
3105
+ if (Number.isFinite(id))
3106
+ sheetId = id;
3107
+ }
3108
+ if (sheetId === undefined && parsed.sheetName) {
3109
+ sheetId = sheetIdBySheetName[parsed.sheetName];
3110
+ }
3111
+ if (sheetId === undefined)
3112
+ return;
3113
+ const entry = this.printNamesBySheetId.get(sheetId) ?? {};
3114
+ if ("ranges" in parsed) {
3115
+ entry.printArea = parsed.ranges;
3116
+ }
3117
+ else {
3118
+ entry.printTitles = parsed.titles;
3119
+ }
3120
+ this.printNamesBySheetId.set(sheetId, entry);
3121
+ }
2952
3122
  _getNamedRanges() {
3123
+ this.printNamesBySheetId.clear();
2953
3124
  const xml = this.workbookXml;
2954
3125
  const sheetIdBySheetName = this._getSheets().reduce((acc, element) => {
2955
3126
  if (element) {
@@ -2971,6 +3142,14 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
2971
3142
  const name = defined_name.a$?.name;
2972
3143
  const expression = defined_name.t$ || "";
2973
3144
  const hidden = defined_name.a$.hidden === "1";
3145
+ // `_xlnm.Print_Area` / `_xlnm.Print_Titles` are sheet-scoped print
3146
+ // facets, not user names: they land on `sheet.printSettings` (see
3147
+ // `getSheets()`), never in `namedRanges` — a global copy would make
3148
+ // Excel repair the file on the next export.
3149
+ if (isBuiltinPrintName(name)) {
3150
+ this.stashBuiltinPrintName(name, typeof expression === "string" ? expression : "", defined_name.a$?.localSheetId, sheetIdBySheetName);
3151
+ continue;
3152
+ }
2974
3153
  // Empty defined names are noise; nothing useful to round-trip.
2975
3154
  // Hidden defined names ARE preserved — Excel uses them as scratch
2976
3155
  // names for features like print areas and add-ins, and dropping
@@ -3162,7 +3341,21 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
3162
3341
  sheet.visibility = visibility;
3163
3342
  }
3164
3343
  const metadata = await this.getSheetMetadata(rid);
3165
- const { merges, rowEntries, columnMetadata, maxRowIndex, maxColumnIndex, autoFilterRange, filterSpecs, sheetViewData, tabColor, sheetHasFilterMode, zeroHeight, defaultRowHeightPx, defaultColumnWidthPx, tablePartIds, outlineSummaryBelow, outlineSummaryRight, } = metadata;
3344
+ const { merges, rowEntries, columnMetadata, maxRowIndex, maxColumnIndex, autoFilterRange, filterSpecs, sheetViewData, tabColor, sheetHasFilterMode, zeroHeight, defaultRowHeightPx, defaultColumnWidthPx, tablePartIds, outlineSummaryBelow, outlineSummaryRight, sheetProtection, protectedRangeEntries, printSettings, } = metadata;
3345
+ if (sheetProtection) {
3346
+ sheet.sheetProtection = sheetProtection;
3347
+ }
3348
+ {
3349
+ const printNames = this.printNamesBySheetId.get(sheetId);
3350
+ const merged = compactPrintSettings({
3351
+ ...printSettings,
3352
+ printArea: printNames?.printArea,
3353
+ printTitles: printNames?.printTitles,
3354
+ });
3355
+ if (merged)
3356
+ sheet.printSettings = merged;
3357
+ }
3358
+ this.protectedRangesBySheet.set(sheetId, protectedRangesFromEntries(sheetId, protectedRangeEntries));
3166
3359
  if (defaultRowHeightPx !== undefined) {
3167
3360
  sheet.defaultRowHeight = defaultRowHeightPx;
3168
3361
  }
@@ -3203,7 +3396,7 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
3203
3396
  // counts
3204
3397
  let columnCount = 0;
3205
3398
  // gridlines / headers / zeros / zoom
3206
- const { frozenRowCount, frozenColumnCount, paneTopLeftCell, showGridLines, showRowColHeaders, showZeros, zoomScale, } = extractSheetViewProperties(sheetViewData);
3399
+ const { frozenRowCount, frozenColumnCount, paneTopLeftCell, showGridLines, showRowColHeaders, showZeros, zoomScale, rightToLeft, } = extractSheetViewProperties(sheetViewData);
3207
3400
  sheet.frozenRowCount = frozenRowCount;
3208
3401
  sheet.frozenColumnCount = frozenColumnCount;
3209
3402
  if (paneTopLeftCell) {
@@ -3219,6 +3412,8 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
3219
3412
  if (zoomScale !== undefined && zoomScale !== 100) {
3220
3413
  sheet.zoomScale = zoomScale;
3221
3414
  }
3415
+ if (rightToLeft)
3416
+ sheet.rightToLeft = true;
3222
3417
  // tab color
3223
3418
  if (tabColor) {
3224
3419
  sheet.tabColor = extractColor(tabColor, this.workbookStyles.indexedColors);
@@ -3833,18 +4028,81 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
3833
4028
  for (const element of workSheets) {
3834
4029
  const sheetId = Number(element.a$.sheetId);
3835
4030
  const rid = element.a$["r:id"];
3836
- // Drawings are referenced from a worksheet-level <drawing> element;
3837
- // skip the full-DOM parse when the SAX pass saw none.
4031
+ // Drawings are referenced from a worksheet-level <drawing> element and
4032
+ // form controls from <controls>; skip the full-DOM parse when the SAX
4033
+ // pass saw neither.
3838
4034
  const features = this.sheetFeatures.get(rid);
3839
- if (features && !features.drawing) {
4035
+ if (features && !features.drawing && !features.controls) {
3840
4036
  continue;
3841
4037
  }
3842
4038
  const sheet_data = await this.getSheetData(rid);
3843
- const drawings = await this._getDrawings(rid, sheetId, sheet_data);
3844
- allDrawings.push(...drawings);
4039
+ if (!features || features.drawing) {
4040
+ const drawings = await this._getDrawings(rid, sheetId, sheet_data);
4041
+ allDrawings.push(...drawings);
4042
+ }
4043
+ if (!features || features.controls) {
4044
+ allDrawings.push(...(await this._getFormControls(rid, sheetId, sheet_data)));
4045
+ }
3845
4046
  }
3846
4047
  return allDrawings;
3847
4048
  }
4049
+ /**
4050
+ * Form controls: `<controls><control r:id>` → `xl/ctrlProps/ctrlPropN.xml`
4051
+ * (+ the caption from the sheet's legacy VML part), as `formControl`
4052
+ * embeds. Nothing is rendered interactively — they round-trip.
4053
+ */
4054
+ async _getFormControls(rid, sheetId, sheetData) {
4055
+ const controls = readWorksheetControls(sheetData);
4056
+ if (!controls.length)
4057
+ return [];
4058
+ const target = this.relations[rid].target;
4059
+ const sheetPath = target.startsWith("/xl")
4060
+ ? target.replace(/^\//gi, "")
4061
+ : `xl/${target}`;
4062
+ const sheetRelPath = sheetPath.replace("worksheets", "worksheets/_rels") + ".rels";
4063
+ const relTargets = new Map();
4064
+ try {
4065
+ const sheetRels = this.xmlParser.parse(await this.zipParser.getText(sheetRelPath));
4066
+ const list = get(sheetRels, "Relationships.Relationship");
4067
+ for (const rel of Array.isArray(list) ? list : list ? [list] : []) {
4068
+ const id = rel?.a$?.Id;
4069
+ const relTarget = rel?.a$?.Target;
4070
+ if (typeof id === "string" && typeof relTarget === "string") {
4071
+ relTargets.set(id, relTarget);
4072
+ }
4073
+ }
4074
+ }
4075
+ catch {
4076
+ return [];
4077
+ }
4078
+ const ctrlProps = new Map();
4079
+ for (const control of controls) {
4080
+ if (!control.relId || ctrlProps.has(control.relId))
4081
+ continue;
4082
+ const relTarget = relTargets.get(control.relId);
4083
+ if (!relTarget)
4084
+ continue;
4085
+ try {
4086
+ const xml = await this.zipParser.getText(this.resolveRelationshipTarget(sheetPath, relTarget));
4087
+ ctrlProps.set(control.relId, parseFormControlPr(this.xmlPreserveValueParser.parse(xml)));
4088
+ }
4089
+ catch {
4090
+ // Missing ctrlProp part — the control is skipped below.
4091
+ }
4092
+ }
4093
+ let captions = new Map();
4094
+ const legacyRelId = readLegacyDrawingRelId(sheetData);
4095
+ const vmlTarget = legacyRelId ? relTargets.get(legacyRelId) : undefined;
4096
+ if (vmlTarget) {
4097
+ try {
4098
+ captions = parseVmlControlCaptions(await this.zipParser.getText(this.resolveRelationshipTarget(sheetPath, vmlTarget)));
4099
+ }
4100
+ catch {
4101
+ // No VML part — controls import without captions.
4102
+ }
4103
+ }
4104
+ return buildFormControlEmbeds({ controls, sheetId, ctrlProps, captions });
4105
+ }
3848
4106
  async getCharts() {
3849
4107
  const allCharts = [];
3850
4108
  const workSheets = this._getSheets();
@@ -4117,6 +4375,18 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
4117
4375
  const sheet_data = await this.getSheetData(rid);
4118
4376
  return parseDataValidationsFromSheetData(this, sheetId, sheet_data, sheetName);
4119
4377
  }
4378
+ /**
4379
+ * Allow-edit ranges (`<protectedRanges>/<protectedRange>`) in the model the
4380
+ * `protect-range` command writes: `protectedRangeId` = the source `name`,
4381
+ * `range` = the first `sqref` area plus `sheetId`. Available after
4382
+ * `getSheets()`; sheet-level `<sheetProtection>` rides `Sheet.sheetProtection`.
4383
+ */
4384
+ getProtectedRanges(sheetId) {
4385
+ if (sheetId !== undefined) {
4386
+ return this.protectedRangesBySheet.get(sheetId) ?? [];
4387
+ }
4388
+ return Array.from(this.protectedRangesBySheet.values()).flat();
4389
+ }
4120
4390
  getNamedRanges() {
4121
4391
  return this.namedRanges;
4122
4392
  }
@@ -4652,3 +4922,155 @@ export class XlsxPlugin extends BaseWorkbookPlugin {
4652
4922
  return externalLinks;
4653
4923
  }
4654
4924
  }
4925
+ /** `CT_SheetProtection` boolean attributes, in OOXML order (camelCase = model key). */
4926
+ const SHEET_PROTECTION_FLAGS = [
4927
+ "sheet",
4928
+ "objects",
4929
+ "scenarios",
4930
+ "formatCells",
4931
+ "formatColumns",
4932
+ "formatRows",
4933
+ "insertColumns",
4934
+ "insertRows",
4935
+ "insertHyperlinks",
4936
+ "deleteColumns",
4937
+ "deleteRows",
4938
+ "selectLockedCells",
4939
+ "sort",
4940
+ "autoFilter",
4941
+ "pivotTables",
4942
+ "selectUnlockedCells",
4943
+ ];
4944
+ /**
4945
+ * `<sheetProtection …>` attributes → `Sheet.sheetProtection`. Only attributes
4946
+ * present in the source are set (`"1"|"true"` → true, anything else → false),
4947
+ * so an explicit flag round-trips without inventing schema defaults; the
4948
+ * password hash (legacy `password` or the agile quartet) rides along verbatim.
4949
+ * Mirrors `rnc-import`'s `read_sheet_protection`.
4950
+ */
4951
+ const readSheetProtectionAttrs = (attrs) => {
4952
+ const protection = {};
4953
+ for (const flag of SHEET_PROTECTION_FLAGS) {
4954
+ const value = attrs[flag];
4955
+ if (value !== undefined) {
4956
+ protection[flag] = value === "1" || value === "true";
4957
+ }
4958
+ }
4959
+ if (attrs.password)
4960
+ protection.password = attrs.password;
4961
+ if (attrs.algorithmName)
4962
+ protection.algorithmName = attrs.algorithmName;
4963
+ if (attrs.hashValue)
4964
+ protection.hashValue = attrs.hashValue;
4965
+ if (attrs.saltValue)
4966
+ protection.saltValue = attrs.saltValue;
4967
+ if (attrs.spinCount !== undefined) {
4968
+ const spinCount = parseInt(attrs.spinCount, 10);
4969
+ if (Number.isFinite(spinCount))
4970
+ protection.spinCount = spinCount;
4971
+ }
4972
+ return protection;
4973
+ };
4974
+ /**
4975
+ * `<protectedRange sqref name>` entries → `ProtectedRange[]` for one sheet. The
4976
+ * `name` becomes the `protectedRangeId` so it keys the stored facet and
4977
+ * re-exports under the same name; only the first `sqref` area is modeled
4978
+ * (Excel writes one per element in practice).
4979
+ */
4980
+ const protectedRangesFromEntries = (sheetId, entries) => {
4981
+ const ranges = [];
4982
+ for (const entry of entries) {
4983
+ const first = entry.sqref.trim().split(/\s+/)[0];
4984
+ const range = first ? getRangeFromAddressRef(first) : undefined;
4985
+ if (!range)
4986
+ continue;
4987
+ const protectedRange = {
4988
+ range: { sheetId, ...range },
4989
+ };
4990
+ if (entry.name)
4991
+ protectedRange.protectedRangeId = entry.name;
4992
+ if (entry.securityDescriptor) {
4993
+ protectedRange.securityDescriptor = entry.securityDescriptor;
4994
+ }
4995
+ ranges.push(protectedRange);
4996
+ }
4997
+ return ranges;
4998
+ };
4999
+ const isXmlTrue = (value) => value === "1" || value === "true";
5000
+ /** `"1"|"true"|"0"|"false"` → boolean; absent stays undefined. */
5001
+ const xmlBoolOpt = (value) => value === undefined ? undefined : isXmlTrue(value);
5002
+ const xmlIntOpt = (value) => {
5003
+ if (value === undefined)
5004
+ return undefined;
5005
+ const n = parseInt(value, 10);
5006
+ return Number.isFinite(n) ? n : undefined;
5007
+ };
5008
+ const xmlFloatOpt = (value) => {
5009
+ if (value === undefined)
5010
+ return undefined;
5011
+ const n = parseFloat(value);
5012
+ return Number.isFinite(n) ? n : undefined;
5013
+ };
5014
+ const stripUndefined = (value) => {
5015
+ for (const key of Object.keys(value)) {
5016
+ if (value[key] === undefined)
5017
+ delete value[key];
5018
+ }
5019
+ return value;
5020
+ };
5021
+ /** `<headerFooter>` children whose text is a header/footer code string. */
5022
+ const HEADER_FOOTER_TEXT_ELEMENTS = [
5023
+ "oddHeader",
5024
+ "oddFooter",
5025
+ "evenHeader",
5026
+ "evenFooter",
5027
+ "firstHeader",
5028
+ "firstFooter",
5029
+ ];
5030
+ const isHeaderFooterTextKey = (name) => HEADER_FOOTER_TEXT_ELEMENTS.includes(name);
5031
+ /**
5032
+ * `<pageSetup …>` → `PageSetup` (present attributes only; `fitToPage` is
5033
+ * filled from `<sheetPr><pageSetUpPr>` by the caller). Mirrors
5034
+ * `rnc-import`'s `read_page_setup`.
5035
+ */
5036
+ const readPageSetupAttrs = (attrs) => {
5037
+ const orientation = attrs.orientation;
5038
+ const pageOrder = attrs.pageOrder;
5039
+ return stripUndefined({
5040
+ orientation: orientation === "landscape" || orientation === "portrait"
5041
+ ? orientation
5042
+ : undefined,
5043
+ paperSize: xmlIntOpt(attrs.paperSize),
5044
+ scale: xmlIntOpt(attrs.scale),
5045
+ fitToWidth: xmlIntOpt(attrs.fitToWidth),
5046
+ fitToHeight: xmlIntOpt(attrs.fitToHeight),
5047
+ firstPageNumber: xmlIntOpt(attrs.firstPageNumber),
5048
+ useFirstPageNumber: xmlBoolOpt(attrs.useFirstPageNumber),
5049
+ pageOrder: pageOrder === "overThenDown" || pageOrder === "downThenOver"
5050
+ ? pageOrder
5051
+ : undefined,
5052
+ blackAndWhite: xmlBoolOpt(attrs.blackAndWhite),
5053
+ draft: xmlBoolOpt(attrs.draft),
5054
+ });
5055
+ };
5056
+ const readPageMarginsAttrs = (attrs) => stripUndefined({
5057
+ left: xmlFloatOpt(attrs.left),
5058
+ right: xmlFloatOpt(attrs.right),
5059
+ top: xmlFloatOpt(attrs.top),
5060
+ bottom: xmlFloatOpt(attrs.bottom),
5061
+ header: xmlFloatOpt(attrs.header),
5062
+ footer: xmlFloatOpt(attrs.footer),
5063
+ });
5064
+ const readPrintOptionsAttrs = (attrs) => stripUndefined({
5065
+ gridLines: xmlBoolOpt(attrs.gridLines),
5066
+ headings: xmlBoolOpt(attrs.headings),
5067
+ horizontalCentered: xmlBoolOpt(attrs.horizontalCentered),
5068
+ verticalCentered: xmlBoolOpt(attrs.verticalCentered),
5069
+ });
5070
+ /** `<headerFooter …>` attributes; the child texts stream in via `ontext`. */
5071
+ const readHeaderFooterAttrs = (attrs) => stripUndefined({
5072
+ differentOddEven: xmlBoolOpt(attrs.differentOddEven),
5073
+ differentFirst: xmlBoolOpt(attrs.differentFirst),
5074
+ scaleWithDoc: xmlBoolOpt(attrs.scaleWithDoc),
5075
+ alignWithMargins: xmlBoolOpt(attrs.alignWithMargins),
5076
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"pivots.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/pivots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AASrE,KAAK,aAAa,GAAG;IACnB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA6OF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GACnC,SAAS;IACP,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,mEAAmE;IACnE,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,kDAAkD;IAClD,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,cAAc,EAAE,MAAM,CAAC;CACxB,KACA,OAAO,CAAC,UAAU,EAAE,CAoEtB,CAAC"}
1
+ {"version":3,"file":"pivots.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/pivots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAEV,UAAU,EAGX,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAoErE,KAAK,aAAa,GAAG;IACnB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAkQF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GACnC,SAAS;IACP,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,mEAAmE;IACnE,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,kDAAkD;IAClD,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,cAAc,EAAE,MAAM,CAAC;CACxB,KACA,OAAO,CAAC,UAAU,EAAE,CAsEtB,CAAC"}