@shbernal/ts-xlsx 1.2.0 → 2.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 (161) hide show
  1. package/README.md +5 -0
  2. package/dist/core/address.d.ts +49 -2
  3. package/dist/core/address.js +31 -3
  4. package/dist/core/autofilter.d.ts +2 -2
  5. package/dist/core/cell.d.ts +17 -16
  6. package/dist/core/cell.js +3 -7
  7. package/dist/core/color-resolution.d.ts +7 -7
  8. package/dist/core/column.d.ts +8 -9
  9. package/dist/core/column.js +2 -4
  10. package/dist/core/comment-thread.d.ts +32 -23
  11. package/dist/core/comment-thread.js +4 -4
  12. package/dist/core/conditional-formatting-overlay.d.ts +1 -1
  13. package/dist/core/conditional-formatting.d.ts +3 -3
  14. package/dist/core/data-validation-overlay.d.ts +1 -1
  15. package/dist/core/data-validation.d.ts +3 -3
  16. package/dist/core/date.d.ts +3 -3
  17. package/dist/core/formula.d.ts +6 -6
  18. package/dist/core/grid-edits.js +3 -3
  19. package/dist/core/image.d.ts +37 -2
  20. package/dist/core/image.js +6 -0
  21. package/dist/core/internal.d.ts +9 -1
  22. package/dist/core/limits.d.ts +4 -4
  23. package/dist/core/merge.d.ts +6 -12
  24. package/dist/core/merge.js +0 -3
  25. package/dist/core/page-setup.d.ts +4 -4
  26. package/dist/core/pivot-table.d.ts +2 -4
  27. package/dist/core/pivot-table.js +5 -5
  28. package/dist/core/preserved.d.ts +3 -3
  29. package/dist/core/protection.d.ts +4 -4
  30. package/dist/core/range.d.ts +16 -14
  31. package/dist/core/range.js +5 -5
  32. package/dist/core/row-input.d.ts +2 -8
  33. package/dist/core/row-input.js +2 -2
  34. package/dist/core/row.d.ts +7 -8
  35. package/dist/core/row.js +2 -4
  36. package/dist/core/style.d.ts +14 -14
  37. package/dist/core/table-style.d.ts +9 -9
  38. package/dist/core/table-style.js +1 -1
  39. package/dist/core/table.d.ts +30 -42
  40. package/dist/core/table.js +16 -10
  41. package/dist/core/theme.d.ts +13 -43
  42. package/dist/core/theme.js +2 -148
  43. package/dist/core/value.d.ts +7 -7
  44. package/dist/core/workbook-protection.d.ts +2 -2
  45. package/dist/core/workbook-styles.d.ts +26 -0
  46. package/dist/core/workbook-styles.js +48 -0
  47. package/dist/core/workbook-theme.d.ts +25 -0
  48. package/dist/core/workbook-theme.js +49 -0
  49. package/dist/core/workbook-vba.d.ts +17 -0
  50. package/dist/core/workbook-vba.js +79 -0
  51. package/dist/core/workbook.d.ts +141 -83
  52. package/dist/core/workbook.js +74 -133
  53. package/dist/core/worksheet-comments.d.ts +9 -0
  54. package/dist/core/worksheet-comments.js +52 -0
  55. package/dist/core/worksheet-model.d.ts +4 -4
  56. package/dist/core/worksheet-model.js +1 -0
  57. package/dist/core/worksheet-pictures.d.ts +29 -0
  58. package/dist/core/worksheet-pictures.js +42 -0
  59. package/dist/core/worksheet.d.ts +94 -77
  60. package/dist/core/worksheet.js +36 -95
  61. package/dist/customui/errors.d.ts +1 -1
  62. package/dist/customui/ribbon.d.ts +3 -3
  63. package/dist/entries/core.d.ts +4 -4
  64. package/dist/entries/core.js +1 -1
  65. package/dist/entries/vba.d.ts +1 -1
  66. package/dist/entries/vba.js +1 -1
  67. package/dist/entries/xlsx.d.ts +1 -0
  68. package/dist/entries/xlsx.js +1 -0
  69. package/dist/errors.d.ts +12 -12
  70. package/dist/io/csv/read.js +1 -2
  71. package/dist/io/csv/write.d.ts +8 -3
  72. package/dist/io/csv/write.js +17 -2
  73. package/dist/io/opc/errors.d.ts +6 -6
  74. package/dist/io/opc/inflate.d.ts +1 -1
  75. package/dist/io/opc/namespaces.d.ts +1 -1
  76. package/dist/io/opc/read-opc.d.ts +19 -3
  77. package/dist/io/opc/read-opc.js +14 -8
  78. package/dist/io/opc/read-options.d.ts +2 -2
  79. package/dist/io/opc/sniff-format.d.ts +2 -2
  80. package/dist/io/opc/zip-mtime.d.ts +5 -0
  81. package/dist/io/opc/zip-mtime.js +1 -0
  82. package/dist/io/style/xf-style.d.ts +38 -6
  83. package/dist/io/style/xf-style.js +22 -0
  84. package/dist/io/xlsb/errors.d.ts +1 -1
  85. package/dist/io/xlsb/formula.d.ts +4 -4
  86. package/dist/io/xlsb/primitives.d.ts +8 -8
  87. package/dist/io/xlsb/ptg-functions.d.ts +1 -1
  88. package/dist/io/xlsb/read-styles.js +2 -20
  89. package/dist/io/xlsb/read.d.ts +2 -2
  90. package/dist/io/xlsx/cell-accumulator.d.ts +25 -6
  91. package/dist/io/xlsx/cell-accumulator.js +111 -30
  92. package/dist/io/xlsx/cell-value.d.ts +2 -2
  93. package/dist/io/xlsx/cell-value.js +3 -3
  94. package/dist/io/xlsx/color-xml.js +11 -17
  95. package/dist/io/xlsx/comments.d.ts +5 -5
  96. package/dist/io/xlsx/comments.js +13 -6
  97. package/dist/io/xlsx/conditional-formatting.d.ts +3 -3
  98. package/dist/io/xlsx/conditional-formatting.js +7 -16
  99. package/dist/io/xlsx/data-validation.d.ts +2 -2
  100. package/dist/io/xlsx/data-validation.js +1 -1
  101. package/dist/io/xlsx/edit-vba.js +2 -1
  102. package/dist/io/xlsx/errors.d.ts +3 -3
  103. package/dist/io/xlsx/hyperlinks.d.ts +4 -2
  104. package/dist/io/xlsx/hyperlinks.js +5 -5
  105. package/dist/io/xlsx/images.d.ts +1 -1
  106. package/dist/io/xlsx/images.js +8 -8
  107. package/dist/io/xlsx/namespaces.d.ts +2 -2
  108. package/dist/io/xlsx/package-plan.js +5 -2
  109. package/dist/io/xlsx/read-pivot.js +2 -5
  110. package/dist/io/xlsx/read-rows.d.ts +13 -13
  111. package/dist/io/xlsx/read-rows.js +19 -55
  112. package/dist/io/xlsx/read-shared-strings.js +7 -5
  113. package/dist/io/xlsx/read-styles.d.ts +3 -3
  114. package/dist/io/xlsx/read-styles.js +40 -65
  115. package/dist/io/xlsx/read-worksheet.js +67 -115
  116. package/dist/io/xlsx/read.d.ts +3 -5
  117. package/dist/io/xlsx/read.js +94 -71
  118. package/dist/io/xlsx/rich-runs.d.ts +1 -1
  119. package/dist/io/xlsx/rich-runs.js +1 -1
  120. package/dist/io/xlsx/rich-text.d.ts +1 -1
  121. package/dist/io/xlsx/shared-strings.d.ts +2 -2
  122. package/dist/io/xlsx/sheet-properties.js +5 -4
  123. package/dist/io/xlsx/styles.d.ts +8 -9
  124. package/dist/io/xlsx/styles.js +4 -3
  125. package/dist/io/xlsx/tables.d.ts +2 -2
  126. package/dist/io/xlsx/tables.js +8 -13
  127. package/dist/io/xlsx/theme-xml.d.ts +37 -0
  128. package/dist/io/xlsx/theme-xml.js +142 -0
  129. package/dist/io/xlsx/threaded-comments.d.ts +18 -27
  130. package/dist/io/xlsx/threaded-comments.js +9 -21
  131. package/dist/io/xlsx/workbook-xml.d.ts +1 -1
  132. package/dist/io/xlsx/workbook-xml.js +6 -2
  133. package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
  134. package/dist/io/xlsx/worksheet-xml.js +7 -12
  135. package/dist/io/xlsx/write-stream.d.ts +15 -15
  136. package/dist/io/xlsx/write-stream.js +5 -3
  137. package/dist/io/xlsx/write.d.ts +12 -7
  138. package/dist/io/xlsx/write.js +10 -6
  139. package/dist/io/xlsx/x14-ext.d.ts +1 -1
  140. package/dist/vba/bytes.d.ts +12 -0
  141. package/dist/vba/bytes.js +40 -0
  142. package/dist/vba/cfb-writer.d.ts +1 -1
  143. package/dist/vba/cfb.d.ts +1 -1
  144. package/dist/vba/cfb.js +15 -51
  145. package/dist/vba/codepage.d.ts +2 -2
  146. package/dist/vba/errors.d.ts +2 -2
  147. package/dist/vba/index.d.ts +2 -2
  148. package/dist/vba/index.js +2 -2
  149. package/dist/vba/ms-ovba.d.ts +1 -1
  150. package/dist/vba/ms-ovba.js +1 -3
  151. package/dist/vba/project-editor.d.ts +9 -9
  152. package/dist/vba/project-editor.js +2 -11
  153. package/dist/vba/project.d.ts +5 -5
  154. package/dist/vba/project.js +1 -10
  155. package/dist/vba/vba-encoding.d.ts +1 -1
  156. package/dist/xml/errors.d.ts +1 -1
  157. package/dist/xml/xml-read.d.ts +38 -9
  158. package/dist/xml/xml-read.js +23 -0
  159. package/dist/xml/xml.d.ts +31 -9
  160. package/dist/xml/xml.js +23 -3
  161. package/package.json +41 -35
@@ -1,6 +1,6 @@
1
- import { assignStyleFacets, isBorderStyle, isFillPatternType, isFontScheme, isFontVerticalAlignment, isHorizontalAlignment, isNamedUnderlineStyle, isVerticalAlignment, } from '../../core/style.js';
2
- import { boolPresent, boolStrict, closeEmptyElements, localName, openElements, xmlEvents, } from '../../xml/xml-read.js';
3
- import { numFmtCodeFor } from '../style/xf-style.js';
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';
4
4
  import { parseColor } from './color-xml.js';
5
5
  const BORDER_EDGE_NAMES = ['left', 'right', 'top', 'bottom', 'diagonal'];
6
6
  const BORDER_EDGES = new Set(BORDER_EDGE_NAMES);
@@ -53,24 +53,7 @@ export function parseStyleTable(xml) {
53
53
  }
54
54
  next = events.next();
55
55
  }
56
- const cellXfs = xfStyles.map((xf) => {
57
- if (xf.xfId === undefined)
58
- return xf;
59
- const named = namedXfs[xf.xfId];
60
- return named === undefined ? xf : { ...named, ...xf };
61
- });
62
- const namedStyles = namedXfs.map((xf, index) => {
63
- const label = cellStyleNames.find((entry) => entry.xfId === index);
64
- const style = {};
65
- assignStyleFacets(style, xf);
66
- if (label?.name !== undefined)
67
- style.name = label.name;
68
- if (label?.builtinId !== undefined)
69
- style.builtinId = label.builtinId;
70
- return style;
71
- });
72
- const defaultFont = fonts[0];
73
- return defaultFont === undefined ? { cellXfs, namedStyles } : { cellXfs, namedStyles, defaultFont };
56
+ return resolveStyleTable({ directXfs: xfStyles, namedXfs, labels: cellStyleNames, fonts });
74
57
  }
75
58
  function* until(events, container) {
76
59
  let next = events.next();
@@ -86,8 +69,8 @@ function parseNumFmts(events) {
86
69
  const codes = new Map();
87
70
  for (const event of until(events, 'numFmts')) {
88
71
  if (event.kind === 'open' && localName(event.name) === 'numFmt') {
89
- const id = Number(event.attrs.numFmtId);
90
- if (Number.isInteger(id) && id > 0 && event.attrs.formatCode !== undefined) {
72
+ const id = numInteger(event.attrs.numFmtId, 1);
73
+ if (id !== undefined && event.attrs.formatCode !== undefined) {
91
74
  codes.set(id, event.attrs.formatCode);
92
75
  }
93
76
  }
@@ -151,8 +134,7 @@ function parseFills(events) {
151
134
  break;
152
135
  case 'stop':
153
136
  if (gradientDraft !== null) {
154
- const position = Number(attrs.position);
155
- gradientDraft.stopPosition = Number.isFinite(position) ? position : 0;
137
+ gradientDraft.stopPosition = numFinite(attrs.position) ?? 0;
156
138
  gradientDraft.stopColor = undefined;
157
139
  }
158
140
  break;
@@ -271,12 +253,12 @@ function parseXfTable(events, container, deps) {
271
253
  return xfs;
272
254
  }
273
255
  function resolveXf(attrs, deps, captureXfId) {
274
- const fillId = Number(attrs.fillId);
275
- const fill = Number.isInteger(fillId) ? deps.fills[fillId] : undefined;
276
- const fontId = Number(attrs.fontId);
277
- const font = Number.isInteger(fontId) ? deps.fonts[fontId] : undefined;
278
- const borderId = Number(attrs.borderId);
279
- const border = Number.isInteger(borderId) && borderId > 0 ? deps.borders[borderId] : undefined;
256
+ const fillId = numInteger(attrs.fillId, 0);
257
+ const fill = fillId !== undefined ? deps.fills[fillId] : undefined;
258
+ const fontId = numInteger(attrs.fontId, 0);
259
+ const font = fontId !== undefined ? deps.fonts[fontId] : undefined;
260
+ const borderId = numInteger(attrs.borderId, 1);
261
+ const border = borderId !== undefined ? deps.borders[borderId] : undefined;
280
262
  const numFmt = resolveNumFmt(attrs.numFmtId, deps.numFmtCodes);
281
263
  const draft = {};
282
264
  if (fill)
@@ -289,9 +271,9 @@ function resolveXf(attrs, deps, captureXfId) {
289
271
  draft.border = border;
290
272
  if (boolStrict(attrs.quotePrefix))
291
273
  draft.quotePrefix = true;
292
- if (captureXfId && attrs.xfId !== undefined) {
293
- const xfId = Number(attrs.xfId);
294
- if (Number.isInteger(xfId) && xfId > 0)
274
+ if (captureXfId) {
275
+ const xfId = numInteger(attrs.xfId, 1);
276
+ if (xfId !== undefined)
295
277
  draft.xfId = xfId;
296
278
  }
297
279
  return draft;
@@ -301,16 +283,14 @@ function parseCellStyles(events) {
301
283
  for (const event of until(events, 'cellStyles')) {
302
284
  if (event.kind === 'open' && localName(event.name) === 'cellStyle') {
303
285
  const attrs = event.attrs;
304
- const xfId = Number(attrs.xfId);
305
- if (Number.isInteger(xfId)) {
286
+ const xfId = numInteger(attrs.xfId);
287
+ if (xfId !== undefined) {
306
288
  const entry = { xfId };
307
289
  if (attrs.name !== undefined)
308
290
  entry.name = attrs.name;
309
- if (attrs.builtinId !== undefined) {
310
- const builtinId = Number(attrs.builtinId);
311
- if (Number.isInteger(builtinId))
312
- entry.builtinId = builtinId;
313
- }
291
+ const builtinId = numInteger(attrs.builtinId);
292
+ if (builtinId !== undefined)
293
+ entry.builtinId = builtinId;
314
294
  names.push(entry);
315
295
  }
316
296
  }
@@ -346,8 +326,8 @@ export function applyFontChild(draft, local, attrs) {
346
326
  draft.vertAlign = attrs.val;
347
327
  break;
348
328
  case 'sz': {
349
- const size = Number(attrs.val);
350
- if (Number.isFinite(size))
329
+ const size = numFinite(attrs.val);
330
+ if (size !== undefined)
351
331
  draft.size = size;
352
332
  break;
353
333
  }
@@ -360,14 +340,14 @@ export function applyFontChild(draft, local, attrs) {
360
340
  draft.name = attrs.val;
361
341
  break;
362
342
  case 'family': {
363
- const family = Number(attrs.val);
364
- if (Number.isInteger(family))
343
+ const family = numInteger(attrs.val);
344
+ if (family !== undefined)
365
345
  draft.family = family;
366
346
  break;
367
347
  }
368
348
  case 'charset': {
369
- const charset = Number(attrs.val);
370
- if (Number.isInteger(charset))
349
+ const charset = numInteger(attrs.val);
350
+ if (charset !== undefined)
371
351
  draft.charset = charset;
372
352
  break;
373
353
  }
@@ -380,7 +360,8 @@ export function applyFontChild(draft, local, attrs) {
380
360
  }
381
361
  }
382
362
  function resolveNumFmt(raw, custom) {
383
- return raw === undefined ? undefined : numFmtCodeFor(Number(raw), custom);
363
+ const id = numInteger(raw, 1);
364
+ return id === undefined ? undefined : numFmtCodeFor(id, custom);
384
365
  }
385
366
  function toFill(pattern, fgColor, bgColor) {
386
367
  if (!isFillPatternType(pattern) || pattern === 'none')
@@ -394,8 +375,8 @@ function toFill(pattern, fgColor, bgColor) {
394
375
  }
395
376
  function assignGradientNumbers(fill, attrs) {
396
377
  for (const key of ['degree', 'left', 'right', 'top', 'bottom']) {
397
- const value = Number(attrs[key]);
398
- if (attrs[key] !== undefined && Number.isFinite(value))
378
+ const value = numFinite(attrs[key]);
379
+ if (value !== undefined)
399
380
  fill[key] = value;
400
381
  }
401
382
  }
@@ -414,25 +395,19 @@ function parseAlignment(attrs) {
414
395
  }
415
396
  if (attrs.vertical !== undefined && isVerticalAlignment(attrs.vertical))
416
397
  out.vertical = attrs.vertical;
417
- if (attrs.textRotation !== undefined) {
418
- const rotation = Number(attrs.textRotation);
419
- if (Number.isFinite(rotation) && rotation !== 0)
420
- out.textRotation = rotation;
421
- }
398
+ const rotation = numFinite(attrs.textRotation);
399
+ if (rotation !== undefined && rotation !== 0)
400
+ out.textRotation = rotation;
422
401
  if (boolStrict(attrs.wrapText))
423
402
  out.wrapText = true;
424
- if (attrs.indent !== undefined) {
425
- const indent = Number(attrs.indent);
426
- if (Number.isInteger(indent) && indent !== 0)
427
- out.indent = indent;
428
- }
403
+ const indent = numInteger(attrs.indent);
404
+ if (indent !== undefined && indent !== 0)
405
+ out.indent = indent;
429
406
  if (boolStrict(attrs.shrinkToFit))
430
407
  out.shrinkToFit = true;
431
- if (attrs.readingOrder !== undefined) {
432
- const order = Number(attrs.readingOrder);
433
- if (Number.isInteger(order) && order !== 0)
434
- out.readingOrder = order;
435
- }
408
+ const order = numInteger(attrs.readingOrder);
409
+ if (order !== undefined && order !== 0)
410
+ out.readingOrder = order;
436
411
  return Object.keys(out).length > 0 ? out : undefined;
437
412
  }
438
413
  function parseProtection(attrs) {
@@ -1,9 +1,9 @@
1
- import { decodeRange } from '../../core/address.js';
1
+ import { decodeRange, MAX_COLUMN, MAX_ROW } from '../../core/address.js';
2
2
  import { isCustomFilterOperator, } from '../../core/autofilter.js';
3
3
  import { INTERNAL } from '../../core/internal.js';
4
4
  import { SHEET_PROTECTION_FLAGS, } from '../../core/protection.js';
5
5
  import { assignStyleFacets } from '../../core/style.js';
6
- import { boolPresent, boolStrict, boolTristate, localName, parseXml, } from '../../xml/xml-read.js';
6
+ import { boolPresent, boolStrict, boolTristate, decodeSpreadsheetText, localName, numFinite, numInteger, parseXml, } from '../../xml/xml-read.js';
7
7
  import { CellAccumulator } from './cell-accumulator.js';
8
8
  import { parseColor } from './color-xml.js';
9
9
  const MARGIN_SIDES = ['left', 'right', 'top', 'bottom', 'header', 'footer'];
@@ -27,20 +27,18 @@ function parseSheetProtection(attrs) {
27
27
  flags[key] = !boolStrict(raw);
28
28
  }
29
29
  const { algorithmName, hashValue, saltValue, spinCount } = attrs;
30
+ const spin = numInteger(spinCount, 0);
30
31
  if (algorithmName !== undefined &&
31
32
  hashValue !== undefined &&
32
33
  saltValue !== undefined &&
33
- spinCount !== undefined) {
34
- const spin = Number(spinCount);
35
- if (Number.isFinite(spin)) {
36
- const credential = {
37
- algorithmName,
38
- hashValue,
39
- saltValue,
40
- spinCount: spin,
41
- };
42
- return { flags, credential };
43
- }
34
+ spin !== undefined) {
35
+ const credential = {
36
+ algorithmName,
37
+ hashValue,
38
+ saltValue,
39
+ spinCount: spin,
40
+ };
41
+ return { flags, credential };
44
42
  }
45
43
  return { flags };
46
44
  }
@@ -57,7 +55,7 @@ class AutoFilterAccumulator {
57
55
  this.#columns = [];
58
56
  }
59
57
  beginColumn(attrs) {
60
- this.#colId = attrs.colId !== undefined ? Number(attrs.colId) : -1;
58
+ this.#colId = numInteger(attrs.colId, 0) ?? -1;
61
59
  this.#values = null;
62
60
  this.#blank = false;
63
61
  this.#predicates = null;
@@ -114,12 +112,12 @@ class PageBreakAccumulator {
114
112
  add(attrs) {
115
113
  if (this.#target === null)
116
114
  return;
117
- const id = Number(attrs.id);
118
- if (!Number.isInteger(id) || id < 1)
115
+ const id = numInteger(attrs.id, 1);
116
+ if (id === undefined)
119
117
  return;
120
118
  const brk = { id };
121
- const max = Number(attrs.max);
122
- if (Number.isInteger(max) && max >= 0)
119
+ const max = numInteger(attrs.max, 0);
120
+ if (max !== undefined)
123
121
  brk.max = max;
124
122
  if (boolStrict(attrs.man))
125
123
  brk.man = true;
@@ -127,10 +125,7 @@ class PageBreakAccumulator {
127
125
  }
128
126
  }
129
127
  export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
130
- const cell = new CellAccumulator();
131
- let inInlineString = false;
132
- let capture = false;
133
- let text = '';
128
+ const cell = new CellAccumulator({ richRuns: true });
134
129
  let rowStyle = -1;
135
130
  let rowCustomFormat = false;
136
131
  const autoFilter = new AutoFilterAccumulator();
@@ -148,46 +143,24 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
148
143
  parseXml(xml, {
149
144
  onOpen(name, attrs, selfClosing) {
150
145
  const local = localName(name);
151
- text = '';
152
- capture = false;
146
+ if (cell.openElement(local, attrs, selfClosing))
147
+ return;
153
148
  switch (local) {
154
149
  case 'col':
155
150
  applyColumn(sheet, attrs, xfStyles, columnStyle);
156
151
  break;
157
152
  case 'row':
158
153
  applyRow(sheet, attrs);
159
- rowStyle = attrs.s !== undefined ? Number(attrs.s) : -1;
154
+ rowStyle = numInteger(attrs.s, 0) ?? -1;
160
155
  rowCustomFormat = boolStrict(attrs.customFormat);
161
156
  break;
162
- case 'c':
163
- cell.beginCell(attrs);
164
- break;
165
- case 'is':
166
- inInlineString = true;
167
- cell.beginInlineString();
168
- break;
169
- case 'r':
170
- if (inInlineString)
171
- cell.runs.beginRun();
172
- break;
173
- case 'rPr':
174
- cell.runs.beginProperties();
175
- break;
176
- case 'f':
177
- capture = true;
178
- cell.beginFormula(attrs, selfClosing);
179
- break;
180
- case 'v':
181
- case 't':
182
- capture = true;
183
- break;
184
157
  case 'oddHeader':
185
158
  case 'oddFooter':
186
159
  case 'evenHeader':
187
160
  case 'evenFooter':
188
161
  case 'firstHeader':
189
162
  case 'firstFooter':
190
- capture = true;
163
+ cell.capture();
191
164
  break;
192
165
  case 'mergeCell':
193
166
  if (attrs.ref !== undefined && attrs.ref !== '') {
@@ -200,6 +173,7 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
200
173
  break;
201
174
  case 'tabColor':
202
175
  case 'outlinePr':
176
+ case 'sheetView':
203
177
  case 'pane':
204
178
  case 'pageSetUpPr':
205
179
  case 'printOptions':
@@ -244,41 +218,27 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
244
218
  cell.runs.applyProperty(local, attrs);
245
219
  break;
246
220
  }
247
- if (selfClosing && (local === 'f' || local === 'v'))
248
- capture = false;
249
221
  },
250
222
  onText(chunk) {
251
- if (capture)
252
- text += chunk;
223
+ cell.appendChunk(chunk);
253
224
  },
254
225
  onClose(name) {
255
226
  const local = localName(name);
227
+ const claimed = cell.closeElement(local);
228
+ if (claimed === 'cell') {
229
+ finalizeCellFromState();
230
+ return;
231
+ }
232
+ if (claimed === 'claimed')
233
+ return;
256
234
  switch (local) {
257
- case 'f':
258
- cell.setFormula(text);
259
- break;
260
- case 'v':
261
- cell.setValue(text);
262
- break;
263
- case 't':
264
- cell.appendText(text, inInlineString);
265
- break;
266
- case 'r':
267
- cell.runs.endRun();
268
- break;
269
- case 'is':
270
- inInlineString = false;
271
- break;
272
235
  case 'oddHeader':
273
236
  case 'oddFooter':
274
237
  case 'evenHeader':
275
238
  case 'evenFooter':
276
239
  case 'firstHeader':
277
240
  case 'firstFooter':
278
- sheet.headerFooter[local] = text;
279
- break;
280
- case 'c':
281
- finalizeCellFromState();
241
+ sheet.headerFooter[local] = decodeSpreadsheetText(cell.capturedText);
282
242
  break;
283
243
  case 'row':
284
244
  rowStyle = -1;
@@ -297,7 +257,6 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
297
257
  default:
298
258
  break;
299
259
  }
300
- capture = false;
301
260
  },
302
261
  }, { closeEmptyElements: WORKSHEET_EMPTY_CLOSES });
303
262
  }
@@ -312,13 +271,20 @@ function applySheetProperties(local, attrs, sheet) {
312
271
  if (attrs.summaryRight !== undefined)
313
272
  sheet.outline.summaryRight = boolPresent(attrs.summaryRight);
314
273
  break;
274
+ case 'sheetView':
275
+ if (attrs.showGridLines !== undefined && !boolPresent(attrs.showGridLines)) {
276
+ sheet.view.showGridLines = false;
277
+ }
278
+ break;
315
279
  case 'pane':
316
280
  if (attrs.state === 'frozen' || attrs.state === 'frozenSplit') {
317
281
  sheet.view.state = 'frozen';
318
- if (attrs.xSplit !== undefined)
319
- sheet.view.xSplit = Number(attrs.xSplit);
320
- if (attrs.ySplit !== undefined)
321
- sheet.view.ySplit = Number(attrs.ySplit);
282
+ const xSplit = numInteger(attrs.xSplit, 0);
283
+ const ySplit = numInteger(attrs.ySplit, 0);
284
+ if (xSplit !== undefined)
285
+ sheet.view.xSplit = xSplit;
286
+ if (ySplit !== undefined)
287
+ sheet.view.ySplit = ySplit;
322
288
  if (attrs.topLeftCell !== undefined)
323
289
  sheet.view.topLeftCell = attrs.topLeftCell;
324
290
  }
@@ -339,25 +305,24 @@ function applySheetProperties(local, attrs, sheet) {
339
305
  }
340
306
  }
341
307
  function applyColumn(sheet, attrs, xfStyles, columnStyle) {
342
- const min = Number(attrs.min);
343
- const max = Number(attrs.max);
344
- if (!Number.isInteger(min) || !Number.isInteger(max) || min < 1)
308
+ const min = numInteger(attrs.min, 1);
309
+ const max = numInteger(attrs.max, 1);
310
+ if (min === undefined || max === undefined || min > MAX_COLUMN)
345
311
  return;
346
- const width = attrs.width !== undefined ? Number(attrs.width) : undefined;
312
+ const last = Math.min(max, MAX_COLUMN);
313
+ const width = numFinite(attrs.width);
347
314
  const hidden = boolStrict(attrs.hidden);
348
- const styleIndex = attrs.style !== undefined ? Number(attrs.style) : -1;
315
+ const styleIndex = numInteger(attrs.style, 0) ?? -1;
349
316
  const style = styleIndex >= 0 ? xfStyles[styleIndex] : undefined;
350
- for (let index = min; index <= max; index++) {
317
+ for (let index = min; index <= last; index++) {
351
318
  const column = sheet.getColumn(index);
352
- if (width !== undefined && Number.isFinite(width) && attrs.customWidth !== '0')
319
+ if (width !== undefined && boolPresent(attrs.customWidth))
353
320
  column.width = width;
354
321
  if (hidden)
355
322
  column.hidden = true;
356
- if (attrs.outlineLevel !== undefined) {
357
- const level = Number(attrs.outlineLevel);
358
- if (Number.isInteger(level) && level > 0)
359
- column.outlineLevel = level;
360
- }
323
+ const outlineLevel = numInteger(attrs.outlineLevel, 1);
324
+ if (outlineLevel !== undefined)
325
+ column.outlineLevel = outlineLevel;
361
326
  if (boolStrict(attrs.collapsed))
362
327
  column.collapsed = true;
363
328
  if (style !== undefined)
@@ -367,22 +332,18 @@ function applyColumn(sheet, attrs, xfStyles, columnStyle) {
367
332
  }
368
333
  }
369
334
  function applyRow(sheet, attrs) {
370
- const number = Number(attrs.r);
371
- if (!Number.isInteger(number) || number < 1)
335
+ const number = numInteger(attrs.r, 1);
336
+ if (number === undefined || number > MAX_ROW)
372
337
  return;
373
338
  const row = sheet.getRow(number);
374
- if (attrs.ht !== undefined && attrs.customHeight !== '0') {
375
- const height = Number(attrs.ht);
376
- if (Number.isFinite(height))
377
- row.height = height;
378
- }
339
+ const height = numFinite(attrs.ht);
340
+ if (height !== undefined && boolPresent(attrs.customHeight))
341
+ row.height = height;
379
342
  if (boolStrict(attrs.hidden))
380
343
  row.hidden = true;
381
- if (attrs.outlineLevel !== undefined) {
382
- const level = Number(attrs.outlineLevel);
383
- if (Number.isInteger(level) && level > 0)
384
- row.outlineLevel = level;
385
- }
344
+ const outlineLevel = numInteger(attrs.outlineLevel, 1);
345
+ if (outlineLevel !== undefined)
346
+ row.outlineLevel = outlineLevel;
386
347
  if (boolStrict(attrs.collapsed))
387
348
  row.collapsed = true;
388
349
  }
@@ -405,31 +366,22 @@ function applyPrintOptions(printOptions, attrs) {
405
366
  }
406
367
  function applyMargins(margins, attrs) {
407
368
  for (const side of MARGIN_SIDES) {
408
- const raw = attrs[side];
409
- if (raw === undefined)
410
- continue;
411
- const value = Number(raw);
412
- if (Number.isFinite(value))
369
+ const value = numFinite(attrs[side]);
370
+ if (value !== undefined)
413
371
  margins[side] = value;
414
372
  }
415
373
  }
416
374
  function applyPageSetup(pageSetup, attrs) {
417
- const num = (raw) => {
418
- if (raw === undefined)
419
- return undefined;
420
- const value = Number(raw);
421
- return Number.isFinite(value) ? value : undefined;
422
- };
423
- const paperSize = num(attrs.paperSize);
375
+ const paperSize = numInteger(attrs.paperSize, 0);
424
376
  if (paperSize !== undefined)
425
377
  pageSetup.paperSize = paperSize;
426
- const scale = num(attrs.scale);
378
+ const scale = numInteger(attrs.scale, 0);
427
379
  if (scale !== undefined)
428
380
  pageSetup.scale = scale;
429
- const fitToWidth = num(attrs.fitToWidth);
381
+ const fitToWidth = numInteger(attrs.fitToWidth, 0);
430
382
  if (fitToWidth !== undefined)
431
383
  pageSetup.fitToWidth = fitToWidth;
432
- const fitToHeight = num(attrs.fitToHeight);
384
+ const fitToHeight = numInteger(attrs.fitToHeight, 0);
433
385
  if (fitToHeight !== undefined)
434
386
  pageSetup.fitToHeight = fitToHeight;
435
387
  if (attrs.pageOrder === 'downThenOver' || attrs.pageOrder === 'overThenDown') {
@@ -1,5 +1,4 @@
1
1
  import { Workbook, type WorkbookView } from '../../core/workbook.ts';
2
- import { type WorkbookProtection } from '../../core/workbook-protection.ts';
3
2
  import type { WorksheetState } from '../../core/worksheet.ts';
4
3
  import { type ReadXlsxOptions } from '../opc/read-options.ts';
5
4
  export { parseRelationships, resolveWorkbookPart } from '../opc/read-opc.ts';
@@ -11,14 +10,14 @@ export { parseStyleTable } from './read-styles.ts';
11
10
  *
12
11
  * Both OOXML serialisations are accepted: an XML `.xlsx`, and a binary `.xlsb` (BIFF12), which is the
13
12
  * same OPC container with binary office-document parts. The two are auto-detected from the package
14
- * itself rather than from a file extension, so a caller never branches on which form it holds and
13
+ * itself rather than from a file extension, so a caller never branches on which form it holds, and
15
14
  * the model produced is the same either way. See `../xlsb/read.ts` for what the binary path does not
16
15
  * yet decode.
17
16
  *
18
- * @throws {UnsupportedFormatError} if the input is neither a legacy `.xls` (`.format === 'xls'`) or
17
+ * @throws {UnsupportedFormatError} if the input is neither: a legacy `.xls` (`.format === 'xls'`) or
19
18
  * an unrecognised/non-ZIP blob (`'unknown'`).
20
19
  * @throws {XlsbParseError} if a binary `.xlsb` part is malformed.
21
- * @throws {PackageReadError} if the input is a ZIP that cannot be unpacked a corrupt or
20
+ * @throws {PackageReadError} if the input is a ZIP that cannot be unpacked: a corrupt or
22
21
  * truncated archive, or one exceeding the inflate bound (a probable zip bomb).
23
22
  */
24
23
  export declare function readXlsx(data: Uint8Array, options?: ReadXlsxOptions): Workbook;
@@ -28,5 +27,4 @@ export interface SheetEntry {
28
27
  readonly state?: WorksheetState['state'];
29
28
  }
30
29
  export declare function parseWorkbookSheets(xml: string): SheetEntry[];
31
- export declare function parseWorkbookProtection(xml: string): WorkbookProtection | undefined;
32
30
  export declare function applyWorkbookView(view: WorkbookView, xml: string): void;