@shbernal/ts-xlsx 2.0.0 → 3.0.0

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 (147) hide show
  1. package/README.md +20 -10
  2. package/dist/bytes.d.ts +24 -0
  3. package/dist/bytes.js +34 -0
  4. package/dist/core/address.d.ts +26 -4
  5. package/dist/core/address.js +21 -9
  6. package/dist/core/autofilter.d.ts +12 -1
  7. package/dist/core/autofilter.js +35 -12
  8. package/dist/core/axis-handle.d.ts +8 -0
  9. package/dist/core/axis-handle.js +14 -0
  10. package/dist/core/cell.d.ts +24 -0
  11. package/dist/core/cell.js +9 -1
  12. package/dist/core/color-resolution.d.ts +1 -1
  13. package/dist/core/color-resolution.js +7 -8
  14. package/dist/core/column.d.ts +4 -1
  15. package/dist/core/column.js +31 -35
  16. package/dist/core/conditional-formatting-overlay.d.ts +5 -0
  17. package/dist/core/conditional-formatting-overlay.js +11 -0
  18. package/dist/core/conditional-formatting.d.ts +45 -5
  19. package/dist/core/conditional-formatting.js +74 -0
  20. package/dist/core/data-validation-overlay.d.ts +11 -0
  21. package/dist/core/data-validation-overlay.js +21 -2
  22. package/dist/core/data-validation.d.ts +9 -2
  23. package/dist/core/data-validation.js +26 -0
  24. package/dist/core/grid-edits.d.ts +16 -0
  25. package/dist/core/grid-edits.js +26 -8
  26. package/dist/core/grid-shift.d.ts +19 -0
  27. package/dist/core/grid-shift.js +8 -0
  28. package/dist/core/image.d.ts +2 -0
  29. package/dist/core/image.js +2 -0
  30. package/dist/core/merge-index.d.ts +31 -0
  31. package/dist/core/merge-index.js +60 -0
  32. package/dist/core/merge.d.ts +12 -11
  33. package/dist/core/merge.js +36 -10
  34. package/dist/core/page-setup.d.ts +86 -2
  35. package/dist/core/page-setup.js +34 -1
  36. package/dist/core/pivot-table.d.ts +2 -0
  37. package/dist/core/pivot-table.js +23 -18
  38. package/dist/core/protection.d.ts +3 -0
  39. package/dist/core/protection.js +20 -14
  40. package/dist/core/row-input.d.ts +7 -0
  41. package/dist/core/row-input.js +10 -8
  42. package/dist/core/row.d.ts +4 -1
  43. package/dist/core/row.js +19 -23
  44. package/dist/core/style.d.ts +78 -7
  45. package/dist/core/style.js +90 -80
  46. package/dist/core/table.d.ts +26 -12
  47. package/dist/core/table.js +67 -33
  48. package/dist/core/theme.d.ts +3 -1
  49. package/dist/core/theme.js +4 -0
  50. package/dist/core/used-extent.d.ts +44 -0
  51. package/dist/core/used-extent.js +102 -0
  52. package/dist/core/workbook.d.ts +2 -2
  53. package/dist/core/worksheet-comments.d.ts +8 -0
  54. package/dist/core/worksheet-comments.js +18 -0
  55. package/dist/core/worksheet.d.ts +31 -7
  56. package/dist/core/worksheet.js +72 -86
  57. package/dist/customui/ribbon.js +23 -24
  58. package/dist/entries/core.d.ts +3 -3
  59. package/dist/entries/csv.d.ts +1 -1
  60. package/dist/entries/node-unavailable.d.ts +15 -0
  61. package/dist/entries/node-unavailable.js +20 -0
  62. package/dist/entries/node.d.ts +1 -0
  63. package/dist/entries/node.js +1 -0
  64. package/dist/entries/xlsx.d.ts +0 -1
  65. package/dist/entries/xlsx.js +0 -1
  66. package/dist/io/csv/read.js +1 -1
  67. package/dist/io/csv/write.d.ts +12 -2
  68. package/dist/io/csv/write.js +17 -2
  69. package/dist/io/opc/inflate.js +3 -13
  70. package/dist/io/opc/part-paths.d.ts +1 -0
  71. package/dist/io/opc/part-paths.js +15 -0
  72. package/dist/io/opc/read-opc.d.ts +22 -3
  73. package/dist/io/opc/read-opc.js +11 -39
  74. package/dist/io/opc/rels.d.ts +12 -6
  75. package/dist/io/opc/rels.js +3 -5
  76. package/dist/io/style/xf-style.d.ts +33 -4
  77. package/dist/io/style/xf-style.js +12 -1
  78. package/dist/io/xlsb/read-styles.js +6 -3
  79. package/dist/io/xlsb/read.d.ts +1 -1
  80. package/dist/io/xlsb/read.js +5 -8
  81. package/dist/io/xlsx/cell-accumulator.d.ts +2 -4
  82. package/dist/io/xlsx/cell-accumulator.js +20 -58
  83. package/dist/io/xlsx/cell-value.d.ts +1 -1
  84. package/dist/io/xlsx/cell-value.js +7 -4
  85. package/dist/io/xlsx/color-xml.d.ts +1 -1
  86. package/dist/io/xlsx/color-xml.js +8 -7
  87. package/dist/io/xlsx/comments.js +6 -3
  88. package/dist/io/xlsx/conditional-formatting.d.ts +4 -3
  89. package/dist/io/xlsx/conditional-formatting.js +81 -65
  90. package/dist/io/xlsx/data-validation.d.ts +10 -8
  91. package/dist/io/xlsx/data-validation.js +44 -41
  92. package/dist/io/xlsx/edit-vba.js +4 -11
  93. package/dist/io/xlsx/hyperlinks.d.ts +4 -2
  94. package/dist/io/xlsx/hyperlinks.js +26 -31
  95. package/dist/io/xlsx/images.js +33 -35
  96. package/dist/io/xlsx/package-plan.d.ts +9 -1
  97. package/dist/io/xlsx/package-plan.js +29 -16
  98. package/dist/io/xlsx/part-names.d.ts +41 -0
  99. package/dist/io/xlsx/part-names.js +46 -0
  100. package/dist/io/xlsx/read-pivot.js +4 -9
  101. package/dist/io/xlsx/read-rows.js +12 -13
  102. package/dist/io/xlsx/read-shared-strings.js +9 -47
  103. package/dist/io/xlsx/read-styles.d.ts +1 -1
  104. package/dist/io/xlsx/read-styles.js +65 -43
  105. package/dist/io/xlsx/read-worksheet.d.ts +10 -1
  106. package/dist/io/xlsx/read-worksheet.js +48 -63
  107. package/dist/io/xlsx/read.d.ts +3 -4
  108. package/dist/io/xlsx/read.js +124 -146
  109. package/dist/io/xlsx/rich-runs.d.ts +41 -7
  110. package/dist/io/xlsx/rich-runs.js +95 -30
  111. package/dist/io/xlsx/sheet-properties.d.ts +1 -1
  112. package/dist/io/xlsx/sheet-properties.js +23 -26
  113. package/dist/io/xlsx/styles.d.ts +3 -15
  114. package/dist/io/xlsx/styles.js +83 -105
  115. package/dist/io/xlsx/tables.js +14 -13
  116. package/dist/io/xlsx/theme-xml.js +8 -5
  117. package/dist/io/xlsx/threaded-comments.js +20 -19
  118. package/dist/io/xlsx/workbook-xml.js +43 -36
  119. package/dist/io/xlsx/worksheet-xml.d.ts +1 -1
  120. package/dist/io/xlsx/worksheet-xml.js +47 -52
  121. package/dist/io/xlsx/write-stream.d.ts +14 -1
  122. package/dist/io/xlsx/write-stream.js +40 -33
  123. package/dist/io/xlsx/write.d.ts +5 -0
  124. package/dist/io/xlsx/write.js +155 -131
  125. package/dist/sha512.d.ts +2 -0
  126. package/dist/sha512.js +146 -0
  127. package/dist/token-set.d.ts +15 -0
  128. package/dist/token-set.js +4 -0
  129. package/dist/vba/bytes.d.ts +1 -2
  130. package/dist/vba/bytes.js +1 -12
  131. package/dist/vba/cfb-format.d.ts +24 -0
  132. package/dist/vba/cfb-format.js +12 -0
  133. package/dist/vba/cfb-writer.js +17 -17
  134. package/dist/vba/cfb.js +1 -7
  135. package/dist/vba/dir-records.d.ts +53 -0
  136. package/dist/vba/dir-records.js +28 -0
  137. package/dist/vba/ms-ovba.js +32 -11
  138. package/dist/vba/project-editor.js +5 -34
  139. package/dist/vba/project.js +15 -31
  140. package/dist/vba/vba-encoding.js +1 -1
  141. package/dist/xml/xml-read.d.ts +117 -72
  142. package/dist/xml/xml-read.js +123 -169
  143. package/dist/xml/xml-scan.d.ts +100 -0
  144. package/dist/xml/xml-scan.js +208 -0
  145. package/dist/xml/xml.d.ts +44 -2
  146. package/dist/xml/xml.js +17 -5
  147. package/package.json +22 -6
@@ -1,9 +1,11 @@
1
- import { isBorderStyle, isFillPatternType, isFontScheme, isFontVerticalAlignment, isHorizontalAlignment, isNamedUnderlineStyle, isVerticalAlignment, } from '../../core/style.js';
2
- import { boolPresent, boolStrict, closeEmptyElements, localName, numFinite, numInteger, openElements, xmlEvents, } from '../../xml/xml-read.js';
3
- import { numFmtCodeFor, resolveStyleTable, } from '../style/xf-style.js';
1
+ import { ALIGNMENT_FACETS, isBorderStyle, isFillPatternType, isFontScheme, isFontVerticalAlignment, isNamedUnderlineStyle, } from '../../core/style.js';
2
+ import { closeEmptyElements, elementSubtrees, openElements, } from '../../xml/xml-read.js';
3
+ import { boolPresent, boolStrict, boolTristate, localName, numFinite, numInteger, xmlEvents, } from '../../xml/xml-scan.js';
4
+ import { NO_PRESERVED_STYLE_TABLES, numFmtCodeFor, resolveStyleTable, } from '../style/xf-style.js';
4
5
  import { parseColor } from './color-xml.js';
5
6
  const BORDER_EDGE_NAMES = ['left', 'right', 'top', 'bottom', 'diagonal'];
6
7
  const BORDER_EDGES = new Set(BORDER_EDGE_NAMES);
8
+ const isBorderEdgeName = (name) => BORDER_EDGES.has(name);
7
9
  const STYLE_EMPTY_CLOSES = new Set([
8
10
  'font',
9
11
  'border',
@@ -14,7 +16,7 @@ const STYLE_EMPTY_CLOSES = new Set([
14
16
  ]);
15
17
  export function parseStyleTable(xml) {
16
18
  if (xml === '')
17
- return { cellXfs: [], namedStyles: [] };
19
+ return { cellXfs: [], namedStyles: [], preserved: NO_PRESERVED_STYLE_TABLES };
18
20
  let fills = [];
19
21
  let fonts = [];
20
22
  let borders = [];
@@ -53,7 +55,17 @@ export function parseStyleTable(xml) {
53
55
  }
54
56
  next = events.next();
55
57
  }
56
- return resolveStyleTable({ directXfs: xfStyles, namedXfs, labels: cellStyleNames, fonts });
58
+ const { fragments, attributes } = elementSubtrees(xml, PRESERVED_SUBTREES);
59
+ const preserved = {
60
+ dxfs: fragments.get('dxfs') ?? [],
61
+ indexedColors: fragments.get('indexedColors') ?? [],
62
+ mruColors: fragments.get('mruColors') ?? [],
63
+ tableStyles: buildTableStyleTable(xml, fragments.get('tableStyles') ?? [], attributes.get('tableStyles')),
64
+ };
65
+ return {
66
+ ...resolveStyleTable({ directXfs: xfStyles, namedXfs, labels: cellStyleNames, fonts }),
67
+ preserved,
68
+ };
57
69
  }
58
70
  function* until(events, container) {
59
71
  let next = events.next();
@@ -192,7 +204,7 @@ function parseBorders(events) {
192
204
  borderDraft.diagonalDown = true;
193
205
  }
194
206
  else if (borderDraft !== null) {
195
- if (BORDER_EDGES.has(local)) {
207
+ if (isBorderEdgeName(local)) {
196
208
  if (attrs.style !== undefined && isBorderStyle(attrs.style)) {
197
209
  currentEdge = local;
198
210
  borderDraft[currentEdge] = { style: attrs.style };
@@ -388,53 +400,58 @@ function borderToStyle(draft) {
388
400
  }
389
401
  function parseAlignment(attrs) {
390
402
  const out = {};
391
- if (attrs.horizontal !== undefined &&
392
- attrs.horizontal !== 'general' &&
393
- isHorizontalAlignment(attrs.horizontal)) {
394
- out.horizontal = attrs.horizontal;
403
+ for (const facet of ALIGNMENT_FACETS) {
404
+ const raw = attrs[facet.key];
405
+ switch (facet.kind) {
406
+ case 'token':
407
+ if (raw !== undefined && raw !== facet.omit && facet.isValid(raw)) {
408
+ assignAlignmentToken(out, facet.key, raw);
409
+ }
410
+ break;
411
+ case 'number': {
412
+ const value = numFinite(raw);
413
+ if (value !== undefined && value !== 0)
414
+ out[facet.key] = value;
415
+ break;
416
+ }
417
+ case 'flag':
418
+ if (boolStrict(raw))
419
+ out[facet.key] = true;
420
+ break;
421
+ }
395
422
  }
396
- if (attrs.vertical !== undefined && isVerticalAlignment(attrs.vertical))
397
- out.vertical = attrs.vertical;
398
- const rotation = numFinite(attrs.textRotation);
399
- if (rotation !== undefined && rotation !== 0)
400
- out.textRotation = rotation;
401
- if (boolStrict(attrs.wrapText))
402
- out.wrapText = true;
403
- const indent = numInteger(attrs.indent);
404
- if (indent !== undefined && indent !== 0)
405
- out.indent = indent;
406
- if (boolStrict(attrs.shrinkToFit))
407
- out.shrinkToFit = true;
408
- const order = numInteger(attrs.readingOrder);
409
- if (order !== undefined && order !== 0)
410
- out.readingOrder = order;
411
423
  return Object.keys(out).length > 0 ? out : undefined;
412
424
  }
425
+ function assignAlignmentToken(out, key, raw) {
426
+ out[key] = raw;
427
+ }
413
428
  function parseProtection(attrs) {
414
429
  const out = {};
415
- if (attrs.locked === '0' || attrs.locked === 'false')
430
+ if (boolTristate(attrs.locked) === false)
416
431
  out.locked = false;
417
432
  if (boolStrict(attrs.hidden))
418
433
  out.hidden = true;
419
434
  return Object.keys(out).length > 0 ? out : undefined;
420
435
  }
421
436
  export function parseIndexedColors(stylesXml) {
422
- return elementFragments(stylesXml, 'indexedColors', 'rgbColor');
437
+ return capturedFragments(stylesXml, 'indexedColors');
423
438
  }
424
439
  export function parseMruColors(stylesXml) {
425
- return elementFragments(stylesXml, 'mruColors', 'color');
440
+ return capturedFragments(stylesXml, 'mruColors');
426
441
  }
427
442
  export function parseTableStyles(stylesXml) {
428
- const styles = elementFragments(stylesXml, 'tableStyles', 'tableStyle');
429
- const table = { styles };
430
- for (const { attrs } of openElements(stylesXml, 'tableStyles')) {
431
- if (attrs.defaultTableStyle !== undefined)
432
- table.defaultTableStyle = attrs.defaultTableStyle;
433
- if (attrs.defaultPivotStyle !== undefined)
434
- table.defaultPivotStyle = attrs.defaultPivotStyle;
435
- break;
443
+ const { fragments, attributes } = elementSubtrees(stylesXml, new Map([['tableStyles', 'tableStyle']]));
444
+ return buildTableStyleTable(stylesXml, fragments.get('tableStyles') ?? [], attributes.get('tableStyles'));
445
+ }
446
+ function buildTableStyleTable(stylesXml, styles, containerAttrs) {
447
+ const table = { styles: [...styles] };
448
+ if (containerAttrs?.defaultTableStyle !== undefined) {
449
+ table.defaultTableStyle = containerAttrs.defaultTableStyle;
436
450
  }
437
- const namespaces = fragmentNamespaces(stylesXml, styles);
451
+ if (containerAttrs?.defaultPivotStyle !== undefined) {
452
+ table.defaultPivotStyle = containerAttrs.defaultPivotStyle;
453
+ }
454
+ const namespaces = fragmentNamespaces(stylesXml, table.styles);
438
455
  if (namespaces.length > 0)
439
456
  table.namespaces = namespaces;
440
457
  return table;
@@ -469,11 +486,16 @@ function fragmentNamespaces(stylesXml, fragments) {
469
486
  ignorable: ignorable.has(prefix),
470
487
  }));
471
488
  }
472
- function elementFragments(xml, container, child) {
473
- const block = new RegExp(`<${container}\\b[^>]*>([\\s\\S]*?)</${container}>`).exec(xml);
474
- if (block === null)
489
+ const PRESERVED_SUBTREES = new Map([
490
+ ['dxfs', 'dxf'],
491
+ ['indexedColors', 'rgbColor'],
492
+ ['mruColors', 'color'],
493
+ ['tableStyles', 'tableStyle'],
494
+ ]);
495
+ function capturedFragments(xml, container) {
496
+ const child = PRESERVED_SUBTREES.get(container);
497
+ if (child === undefined)
475
498
  return [];
476
- const inner = block[1] ?? '';
477
- const pattern = new RegExp(`<${child}\\b[^>]*/>|<${child}\\b[^>]*>[\\s\\S]*?</${child}>`, 'g');
478
- return [...inner.matchAll(pattern)].map((m) => m[0] ?? '');
499
+ const { fragments } = elementSubtrees(xml, new Map([[container, child]]));
500
+ return [...(fragments.get(container) ?? [])];
479
501
  }
@@ -1,4 +1,13 @@
1
1
  import type { Worksheet } from '../../core/worksheet.ts';
2
+ import { type SaxPass } from '../../xml/xml-read.ts';
2
3
  import type { XfStyle } from '../style/xf-style.ts';
3
4
  import type { SharedString } from './cell-value.ts';
4
- export declare function parseWorksheet(xml: string, sheet: Worksheet, sharedStrings: readonly SharedString[], xfStyles: ReadonlyArray<XfStyle>): void;
5
+ /**
6
+ * A pass reading a worksheet part into `sheet`: cells and their styles, the column and row metadata,
7
+ * merges, the autofilter, page breaks, and the view and print layout. It commits as it goes rather
8
+ * than gathering, so it has nothing to hand back once the parse ends.
9
+ *
10
+ * Offered as a pass because the worksheet is the largest part in a package and four other readers
11
+ * want the same events, so the five share one parse of it rather than scanning it once each.
12
+ */
13
+ export declare function worksheetPass(sheet: Worksheet, sharedStrings: readonly SharedString[], xfStyles: ReadonlyArray<XfStyle>): SaxPass;
@@ -1,12 +1,17 @@
1
- import { decodeRange, MAX_COLUMN, MAX_ROW } from '../../core/address.js';
1
+ import { MAX_COLUMN, MAX_ROW, tryDecodeRange } from '../../core/address.js';
2
2
  import { isCustomFilterOperator, } from '../../core/autofilter.js';
3
3
  import { INTERNAL } from '../../core/internal.js';
4
+ import { HEADER_FOOTER_ELEMENTS, MARGIN_SIDES, PAGE_SETUP_FACETS, PRINT_OPTION_FLAGS, } from '../../core/page-setup.js';
4
5
  import { SHEET_PROTECTION_FLAGS, } from '../../core/protection.js';
5
6
  import { assignStyleFacets } from '../../core/style.js';
6
- import { boolPresent, boolStrict, boolTristate, decodeSpreadsheetText, localName, numFinite, numInteger, parseXml, } from '../../xml/xml-read.js';
7
+ import {} from '../../xml/xml-read.js';
8
+ import { boolPresent, boolStrict, boolTristate, decodeSpreadsheetText, localName, numFinite, numInteger, } from '../../xml/xml-scan.js';
7
9
  import { CellAccumulator } from './cell-accumulator.js';
8
10
  import { parseColor } from './color-xml.js';
9
- const MARGIN_SIDES = ['left', 'right', 'top', 'bottom', 'header', 'footer'];
11
+ const HEADER_FOOTER_CHILDREN = new Set(HEADER_FOOTER_ELEMENTS);
12
+ function isHeaderFooterElement(local) {
13
+ return HEADER_FOOTER_CHILDREN.has(local);
14
+ }
10
15
  const WORKSHEET_EMPTY_CLOSES = new Set(['c', 'autoFilter']);
11
16
  function pendingFilterCriteria(values, blank, predicates, and) {
12
17
  if (values !== null && (values.length > 0 || blank)) {
@@ -18,7 +23,7 @@ function pendingFilterCriteria(values, blank, predicates, and) {
18
23
  return null;
19
24
  }
20
25
  function parseSheetProtection(attrs) {
21
- if (attrs.sheet === '0' || attrs.sheet === 'false')
26
+ if (boolTristate(attrs.sheet) === false)
22
27
  return undefined;
23
28
  const flags = {};
24
29
  for (const { key } of SHEET_PROTECTION_FLAGS) {
@@ -90,13 +95,13 @@ class AutoFilterAccumulator {
90
95
  commit(sheet) {
91
96
  if (this.#ref === null)
92
97
  return;
93
- try {
94
- const { left, right } = decodeRange(this.#ref);
95
- const width = left !== undefined && right !== undefined ? right - left + 1 : 0;
98
+ const decoded = tryDecodeRange(this.#ref);
99
+ const left = decoded?.left;
100
+ const right = decoded?.right;
101
+ if (left !== undefined && right !== undefined) {
102
+ const width = right - left + 1;
96
103
  sheet.autoFilter = { ref: this.#ref, columns: this.#columns.filter((c) => c.colId < width) };
97
104
  }
98
- catch {
99
- }
100
105
  this.#ref = null;
101
106
  this.#columns = [];
102
107
  }
@@ -124,7 +129,7 @@ class PageBreakAccumulator {
124
129
  this.#target.push(brk);
125
130
  }
126
131
  }
127
- export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
132
+ export function worksheetPass(sheet, sharedStrings, xfStyles) {
128
133
  const cell = new CellAccumulator({ richRuns: true });
129
134
  let rowStyle = -1;
130
135
  let rowCustomFormat = false;
@@ -140,11 +145,15 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
140
145
  const style = styleIndex >= 0 ? xfStyles[styleIndex] : xfStyles[0];
141
146
  cell.finalize(sheet, sharedStrings, style);
142
147
  };
143
- parseXml(xml, {
148
+ const handlers = {
144
149
  onOpen(name, attrs, selfClosing) {
145
150
  const local = localName(name);
146
151
  if (cell.openElement(local, attrs, selfClosing))
147
152
  return;
153
+ if (HEADER_FOOTER_CHILDREN.has(local)) {
154
+ cell.capture();
155
+ return;
156
+ }
148
157
  switch (local) {
149
158
  case 'col':
150
159
  applyColumn(sheet, attrs, xfStyles, columnStyle);
@@ -154,14 +163,6 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
154
163
  rowStyle = numInteger(attrs.s, 0) ?? -1;
155
164
  rowCustomFormat = boolStrict(attrs.customFormat);
156
165
  break;
157
- case 'oddHeader':
158
- case 'oddFooter':
159
- case 'evenHeader':
160
- case 'evenFooter':
161
- case 'firstHeader':
162
- case 'firstFooter':
163
- cell.capture();
164
- break;
165
166
  case 'mergeCell':
166
167
  if (attrs.ref !== undefined && attrs.ref !== '') {
167
168
  try {
@@ -214,9 +215,6 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
214
215
  case 'customFilter':
215
216
  autoFilter.addCustom(attrs);
216
217
  break;
217
- default:
218
- cell.runs.applyProperty(local, attrs);
219
- break;
220
218
  }
221
219
  },
222
220
  onText(chunk) {
@@ -231,15 +229,11 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
231
229
  }
232
230
  if (claimed === 'claimed')
233
231
  return;
232
+ if (isHeaderFooterElement(local)) {
233
+ sheet.headerFooter[local] = decodeSpreadsheetText(cell.capturedText);
234
+ return;
235
+ }
234
236
  switch (local) {
235
- case 'oddHeader':
236
- case 'oddFooter':
237
- case 'evenHeader':
238
- case 'evenFooter':
239
- case 'firstHeader':
240
- case 'firstFooter':
241
- sheet.headerFooter[local] = decodeSpreadsheetText(cell.capturedText);
242
- break;
243
237
  case 'row':
244
238
  rowStyle = -1;
245
239
  rowCustomFormat = false;
@@ -258,7 +252,8 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
258
252
  break;
259
253
  }
260
254
  },
261
- }, { closeEmptyElements: WORKSHEET_EMPTY_CLOSES });
255
+ };
256
+ return { handlers, closeEmptyElements: WORKSHEET_EMPTY_CLOSES };
262
257
  }
263
258
  function applySheetProperties(local, attrs, sheet) {
264
259
  switch (local) {
@@ -348,21 +343,11 @@ function applyRow(sheet, attrs) {
348
343
  row.collapsed = true;
349
344
  }
350
345
  function applyPrintOptions(printOptions, attrs) {
351
- const horizontalCentered = boolTristate(attrs.horizontalCentered);
352
- if (horizontalCentered !== undefined)
353
- printOptions.horizontalCentered = horizontalCentered;
354
- const verticalCentered = boolTristate(attrs.verticalCentered);
355
- if (verticalCentered !== undefined)
356
- printOptions.verticalCentered = verticalCentered;
357
- const headings = boolTristate(attrs.headings);
358
- if (headings !== undefined)
359
- printOptions.headings = headings;
360
- const gridLines = boolTristate(attrs.gridLines);
361
- if (gridLines !== undefined)
362
- printOptions.gridLines = gridLines;
363
- const gridLinesSet = boolTristate(attrs.gridLinesSet);
364
- if (gridLinesSet !== undefined)
365
- printOptions.gridLinesSet = gridLinesSet;
346
+ for (const flag of PRINT_OPTION_FLAGS) {
347
+ const value = boolTristate(attrs[flag]);
348
+ if (value !== undefined)
349
+ printOptions[flag] = value;
350
+ }
366
351
  }
367
352
  function applyMargins(margins, attrs) {
368
353
  for (const side of MARGIN_SIDES) {
@@ -372,22 +357,22 @@ function applyMargins(margins, attrs) {
372
357
  }
373
358
  }
374
359
  function applyPageSetup(pageSetup, attrs) {
375
- const paperSize = numInteger(attrs.paperSize, 0);
376
- if (paperSize !== undefined)
377
- pageSetup.paperSize = paperSize;
378
- const scale = numInteger(attrs.scale, 0);
379
- if (scale !== undefined)
380
- pageSetup.scale = scale;
381
- const fitToWidth = numInteger(attrs.fitToWidth, 0);
382
- if (fitToWidth !== undefined)
383
- pageSetup.fitToWidth = fitToWidth;
384
- const fitToHeight = numInteger(attrs.fitToHeight, 0);
385
- if (fitToHeight !== undefined)
386
- pageSetup.fitToHeight = fitToHeight;
387
- if (attrs.pageOrder === 'downThenOver' || attrs.pageOrder === 'overThenDown') {
388
- pageSetup.pageOrder = attrs.pageOrder;
389
- }
390
- if (attrs.orientation === 'portrait' || attrs.orientation === 'landscape') {
391
- pageSetup.orientation = attrs.orientation;
360
+ for (const facet of PAGE_SETUP_FACETS) {
361
+ const raw = attrs[facet.key];
362
+ switch (facet.kind) {
363
+ case 'count': {
364
+ const value = numInteger(raw, 0);
365
+ if (value !== undefined)
366
+ pageSetup[facet.key] = value;
367
+ break;
368
+ }
369
+ case 'token':
370
+ if (raw !== undefined && facet.isValid(raw))
371
+ assignPageSetupToken(pageSetup, facet.key, raw);
372
+ break;
373
+ }
392
374
  }
393
375
  }
376
+ function assignPageSetupToken(pageSetup, key, raw) {
377
+ pageSetup[key] = raw;
378
+ }
@@ -1,8 +1,7 @@
1
1
  import { Workbook, type WorkbookView } from '../../core/workbook.ts';
2
- import type { WorksheetState } from '../../core/worksheet.ts';
3
- import { type ReadXlsxOptions } from '../opc/read-options.ts';
4
- export { parseRelationships, resolveWorkbookPart } from '../opc/read-opc.ts';
5
- export { DEFAULT_MAX_UNCOMPRESSED, type ReadXlsxOptions } from '../opc/read-options.ts';
2
+ import { type WorksheetState } from '../../core/worksheet.ts';
3
+ import type { ReadXlsxOptions } from '../opc/read-options.ts';
4
+ export type { ReadXlsxOptions } from '../opc/read-options.ts';
6
5
  export type { StyleTable, XfStyle } from '../style/xf-style.ts';
7
6
  export { parseStyleTable } from './read-styles.ts';
8
7
  /**