@shbernal/ts-xlsx 3.0.0 → 3.2.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 (277) hide show
  1. package/README.md +34 -24
  2. package/dist/bytes.d.ts +10 -2
  3. package/dist/bytes.js +22 -0
  4. package/dist/core/address.d.ts +96 -2
  5. package/dist/core/address.js +87 -33
  6. package/dist/core/array-formula-ranges.d.ts +33 -0
  7. package/dist/core/array-formula-ranges.js +62 -0
  8. package/dist/core/autofilter.d.ts +4 -3
  9. package/dist/core/autofilter.js +31 -30
  10. package/dist/core/axis-handle.d.ts +2 -0
  11. package/dist/core/axis-handle.js +5 -2
  12. package/dist/core/cell.d.ts +4 -3
  13. package/dist/core/cell.js +4 -6
  14. package/dist/core/clone.d.ts +29 -0
  15. package/dist/core/clone.js +24 -0
  16. package/dist/core/color-resolution.js +4 -6
  17. package/dist/core/column.d.ts +1 -0
  18. package/dist/core/column.js +6 -2
  19. package/dist/core/comment-thread.d.ts +7 -3
  20. package/dist/core/comment-thread.js +2 -1
  21. package/dist/core/conditional-formatting-overlay.d.ts +11 -1
  22. package/dist/core/conditional-formatting-overlay.js +30 -3
  23. package/dist/core/conditional-formatting.d.ts +107 -11
  24. package/dist/core/conditional-formatting.js +76 -19
  25. package/dist/core/containers.d.ts +12 -0
  26. package/dist/core/containers.js +5 -0
  27. package/dist/core/data-validation-overlay.d.ts +7 -1
  28. package/dist/core/data-validation-overlay.js +19 -4
  29. package/dist/core/data-validation.d.ts +22 -0
  30. package/dist/core/data-validation.js +30 -4
  31. package/dist/core/date-format.d.ts +20 -0
  32. package/dist/core/date-format.js +170 -0
  33. package/dist/core/date.d.ts +43 -8
  34. package/dist/core/date.js +19 -3
  35. package/dist/core/formula-references.d.ts +26 -0
  36. package/dist/core/formula-references.js +173 -0
  37. package/dist/core/formula-scan.d.ts +2 -0
  38. package/dist/core/formula-scan.js +58 -0
  39. package/dist/core/formula.d.ts +76 -17
  40. package/dist/core/formula.js +87 -80
  41. package/dist/core/function-values.d.ts +4 -0
  42. package/dist/core/function-values.js +58 -0
  43. package/dist/core/future-functions.d.ts +3 -0
  44. package/dist/core/{modern-functions.js → future-functions.js} +119 -88
  45. package/dist/core/grid-edits.d.ts +30 -3
  46. package/dist/core/grid-edits.js +248 -81
  47. package/dist/core/grid-shift.d.ts +58 -9
  48. package/dist/core/grid-shift.js +26 -4
  49. package/dist/core/hyperlink.d.ts +39 -0
  50. package/dist/core/hyperlink.js +88 -0
  51. package/dist/core/image.d.ts +49 -14
  52. package/dist/core/image.js +16 -5
  53. package/dist/core/internal.d.ts +10 -2
  54. package/dist/core/limits.d.ts +25 -0
  55. package/dist/core/limits.js +4 -0
  56. package/dist/core/merge.d.ts +18 -4
  57. package/dist/core/merge.js +33 -20
  58. package/dist/core/page-setup.d.ts +26 -11
  59. package/dist/core/pivot-table.d.ts +49 -10
  60. package/dist/core/pivot-table.js +112 -60
  61. package/dist/core/protection.d.ts +66 -4
  62. package/dist/core/protection.js +6 -11
  63. package/dist/core/range.js +34 -30
  64. package/dist/core/row-input.js +2 -2
  65. package/dist/core/row.d.ts +1 -0
  66. package/dist/core/row.js +6 -2
  67. package/dist/core/structured-reference.d.ts +7 -0
  68. package/dist/core/structured-reference.js +7 -0
  69. package/dist/core/style.d.ts +85 -70
  70. package/dist/core/style.js +92 -28
  71. package/dist/core/table-style.d.ts +1 -1
  72. package/dist/core/table-style.js +4 -4
  73. package/dist/core/table.d.ts +64 -16
  74. package/dist/core/table.js +87 -40
  75. package/dist/core/theme.d.ts +2 -0
  76. package/dist/core/theme.js +9 -5
  77. package/dist/core/value.d.ts +60 -28
  78. package/dist/core/value.js +48 -43
  79. package/dist/core/workbook-media.d.ts +34 -0
  80. package/dist/core/workbook-media.js +44 -0
  81. package/dist/core/workbook-styles.d.ts +83 -1
  82. package/dist/core/workbook-styles.js +4 -0
  83. package/dist/core/workbook-theme.js +5 -3
  84. package/dist/core/workbook-vba.js +3 -2
  85. package/dist/core/workbook.d.ts +41 -3
  86. package/dist/core/workbook.js +46 -41
  87. package/dist/core/worksheet-comments.d.ts +2 -1
  88. package/dist/core/worksheet-comments.js +20 -13
  89. package/dist/core/worksheet-merges.d.ts +49 -0
  90. package/dist/core/worksheet-merges.js +65 -0
  91. package/dist/core/worksheet-model.d.ts +10 -2
  92. package/dist/core/worksheet-model.js +28 -9
  93. package/dist/core/worksheet-pictures.d.ts +3 -3
  94. package/dist/core/worksheet-pictures.js +7 -6
  95. package/dist/core/worksheet.d.ts +165 -27
  96. package/dist/core/worksheet.js +206 -89
  97. package/dist/customui/ribbon.js +2 -1
  98. package/dist/entries/core.d.ts +21 -14
  99. package/dist/entries/core.js +14 -7
  100. package/dist/entries/errors.d.ts +1 -0
  101. package/dist/entries/errors.js +1 -0
  102. package/dist/entries/xlsx.d.ts +1 -1
  103. package/dist/errors.d.ts +64 -0
  104. package/dist/errors.js +22 -0
  105. package/dist/hex.d.ts +8 -0
  106. package/dist/hex.js +3 -0
  107. package/dist/io/cell-metadata/metadata.d.ts +42 -0
  108. package/dist/io/cell-metadata/metadata.js +35 -0
  109. package/dist/io/cell-metadata/rich-values.d.ts +11 -0
  110. package/dist/io/cell-metadata/rich-values.js +80 -0
  111. package/dist/io/csv/delimiter.d.ts +21 -0
  112. package/dist/io/csv/delimiter.js +18 -0
  113. package/dist/io/csv/errors.d.ts +14 -0
  114. package/dist/io/csv/errors.js +5 -0
  115. package/dist/io/csv/read.d.ts +6 -1
  116. package/dist/io/csv/read.js +51 -22
  117. package/dist/io/csv/write.d.ts +19 -5
  118. package/dist/io/csv/write.js +24 -44
  119. package/dist/io/opc/inflate.js +14 -0
  120. package/dist/io/opc/namespaces.d.ts +16 -0
  121. package/dist/io/opc/namespaces.js +4 -0
  122. package/dist/io/opc/part-paths.d.ts +9 -0
  123. package/dist/io/opc/part-paths.js +5 -5
  124. package/dist/io/opc/read-opc.d.ts +58 -14
  125. package/dist/io/opc/read-opc.js +49 -21
  126. package/dist/io/opc/read-options.d.ts +5 -1
  127. package/dist/io/opc/sniff-format.d.ts +3 -3
  128. package/dist/io/opc/sniff-format.js +2 -2
  129. package/dist/io/opc/strict-relationships.d.ts +2 -0
  130. package/dist/io/opc/strict-relationships.js +12 -0
  131. package/dist/io/read-policy/column-budget.d.ts +26 -0
  132. package/dist/io/read-policy/column-budget.js +18 -0
  133. package/dist/io/read-policy/read-repair.d.ts +74 -0
  134. package/dist/io/read-policy/read-repair.js +119 -0
  135. package/dist/io/style/cell-style-resolution.d.ts +25 -0
  136. package/dist/io/style/cell-style-resolution.js +30 -0
  137. package/dist/io/style/xf-style.d.ts +23 -1
  138. package/dist/io/style/xf-style.js +8 -0
  139. package/dist/io/xlsb/formula.d.ts +2 -2
  140. package/dist/io/xlsb/formula.js +52 -35
  141. package/dist/io/xlsb/primitives.js +8 -14
  142. package/dist/io/xlsb/ptg-functions.d.ts +19 -10
  143. package/dist/io/xlsb/ptg-functions.js +495 -596
  144. package/dist/io/xlsb/read-metadata.d.ts +7 -0
  145. package/dist/io/xlsb/read-metadata.js +69 -0
  146. package/dist/io/xlsb/read-styles.js +45 -81
  147. package/dist/io/xlsb/read-worksheet.d.ts +26 -1
  148. package/dist/io/xlsb/read-worksheet.js +148 -106
  149. package/dist/io/xlsb/read.d.ts +6 -3
  150. package/dist/io/xlsb/read.js +70 -31
  151. package/dist/io/xlsb/record-stream.d.ts +30 -0
  152. package/dist/io/xlsb/record-stream.js +20 -0
  153. package/dist/io/xlsb/record-types.d.ts +14 -5
  154. package/dist/io/xlsb/record-types.js +14 -5
  155. package/dist/io/xlsb/sheet-protection.d.ts +20 -0
  156. package/dist/io/xlsb/sheet-protection.js +60 -0
  157. package/dist/io/xlsx/cell-accumulator.d.ts +24 -9
  158. package/dist/io/xlsx/cell-accumulator.js +74 -21
  159. package/dist/io/xlsx/cell-metadata.d.ts +39 -0
  160. package/dist/io/xlsx/cell-metadata.js +162 -0
  161. package/dist/io/xlsx/cell-value.d.ts +19 -5
  162. package/dist/io/xlsx/cell-value.js +45 -30
  163. package/dist/io/xlsx/color-xml.js +3 -2
  164. package/dist/io/xlsx/column-span.d.ts +11 -0
  165. package/dist/io/xlsx/column-span.js +9 -0
  166. package/dist/io/xlsx/comments.d.ts +9 -30
  167. package/dist/io/xlsx/comments.js +25 -83
  168. package/dist/io/xlsx/conditional-formatting.d.ts +43 -23
  169. package/dist/io/xlsx/conditional-formatting.js +437 -138
  170. package/dist/io/xlsx/data-validation.d.ts +12 -7
  171. package/dist/io/xlsx/data-validation.js +67 -53
  172. package/dist/io/xlsx/edit-vba.d.ts +7 -2
  173. package/dist/io/xlsx/edit-vba.js +52 -52
  174. package/dist/io/xlsx/font-xml.d.ts +7 -0
  175. package/dist/io/xlsx/font-xml.js +104 -0
  176. package/dist/io/xlsx/hyperlinks.d.ts +19 -21
  177. package/dist/io/xlsx/hyperlinks.js +12 -32
  178. package/dist/io/xlsx/images.d.ts +49 -16
  179. package/dist/io/xlsx/images.js +149 -50
  180. package/dist/io/xlsx/namespaces.d.ts +24 -0
  181. package/dist/io/xlsx/namespaces.js +11 -0
  182. package/dist/io/xlsx/package-plan.d.ts +60 -15
  183. package/dist/io/xlsx/package-plan.js +83 -18
  184. package/dist/io/xlsx/part-names.d.ts +6 -8
  185. package/dist/io/xlsx/part-names.js +3 -7
  186. package/dist/io/xlsx/pivot.d.ts +5 -5
  187. package/dist/io/xlsx/pivot.js +26 -24
  188. package/dist/io/xlsx/preserved-splices.d.ts +6 -0
  189. package/dist/io/xlsx/preserved-splices.js +74 -0
  190. package/dist/io/xlsx/read-comments.d.ts +29 -0
  191. package/dist/io/xlsx/read-comments.js +75 -0
  192. package/dist/io/xlsx/read-parts.d.ts +59 -0
  193. package/dist/io/xlsx/read-parts.js +259 -0
  194. package/dist/io/xlsx/read-pivot.js +11 -4
  195. package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +8 -5
  196. package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +24 -4
  197. package/dist/io/xlsx/read-rows.d.ts +35 -11
  198. package/dist/io/xlsx/read-rows.js +73 -49
  199. package/dist/io/xlsx/read-shared-strings.js +3 -2
  200. package/dist/io/xlsx/read-styles.d.ts +0 -30
  201. package/dist/io/xlsx/read-styles.js +45 -105
  202. package/dist/io/xlsx/read-workbook-xml.d.ts +42 -0
  203. package/dist/io/xlsx/read-workbook-xml.js +175 -0
  204. package/dist/io/xlsx/read-worksheet.d.ts +9 -3
  205. package/dist/io/xlsx/read-worksheet.js +70 -177
  206. package/dist/io/xlsx/read.d.ts +3 -14
  207. package/dist/io/xlsx/read.js +74 -411
  208. package/dist/io/xlsx/relationships.d.ts +3 -0
  209. package/dist/io/xlsx/relationships.js +4 -0
  210. package/dist/io/xlsx/rich-text.js +1 -1
  211. package/dist/io/xlsx/row-position.d.ts +20 -0
  212. package/dist/io/xlsx/row-position.js +11 -0
  213. package/dist/io/xlsx/row-xml.d.ts +139 -0
  214. package/dist/io/xlsx/row-xml.js +222 -0
  215. package/dist/io/xlsx/shared-formulas.js +2 -2
  216. package/dist/io/xlsx/sheet-properties.d.ts +10 -1
  217. package/dist/io/xlsx/sheet-properties.js +182 -20
  218. package/dist/io/xlsx/strict-parts.d.ts +7 -0
  219. package/dist/io/xlsx/strict-parts.js +171 -0
  220. package/dist/io/xlsx/style-elements.d.ts +41 -0
  221. package/dist/io/xlsx/style-elements.js +136 -0
  222. package/dist/io/xlsx/styles.d.ts +17 -3
  223. package/dist/io/xlsx/styles.js +13 -209
  224. package/dist/io/xlsx/tables.d.ts +10 -2
  225. package/dist/io/xlsx/tables.js +55 -52
  226. package/dist/io/xlsx/theme-xml.d.ts +32 -4
  227. package/dist/io/xlsx/theme-xml.js +106 -71
  228. package/dist/io/xlsx/threaded-comments.d.ts +14 -11
  229. package/dist/io/xlsx/threaded-comments.js +16 -8
  230. package/dist/io/xlsx/workbook-xml.d.ts +45 -6
  231. package/dist/io/xlsx/workbook-xml.js +62 -54
  232. package/dist/io/xlsx/worksheet-xml.d.ts +26 -70
  233. package/dist/io/xlsx/worksheet-xml.js +69 -282
  234. package/dist/io/xlsx/write-stream.d.ts +90 -19
  235. package/dist/io/xlsx/write-stream.js +80 -25
  236. package/dist/io/xlsx/write.d.ts +12 -6
  237. package/dist/io/xlsx/write.js +226 -123
  238. package/dist/rel-type.d.ts +25 -0
  239. package/dist/rel-type.js +9 -0
  240. package/dist/token-set.d.ts +13 -0
  241. package/dist/token-set.js +4 -1
  242. package/dist/vba/bytes.d.ts +16 -5
  243. package/dist/vba/bytes.js +27 -6
  244. package/dist/vba/cfb-format.d.ts +55 -0
  245. package/dist/vba/cfb-format.js +35 -0
  246. package/dist/vba/cfb-writer.d.ts +8 -0
  247. package/dist/vba/cfb-writer.js +40 -40
  248. package/dist/vba/cfb.d.ts +21 -4
  249. package/dist/vba/cfb.js +124 -90
  250. package/dist/vba/codepage.js +2 -1
  251. package/dist/vba/dir-records.d.ts +6 -0
  252. package/dist/vba/dir-records.js +10 -2
  253. package/dist/vba/errors.d.ts +11 -4
  254. package/dist/vba/index.d.ts +0 -2
  255. package/dist/vba/index.js +0 -2
  256. package/dist/vba/ms-ovba.d.ts +6 -2
  257. package/dist/vba/ms-ovba.js +66 -22
  258. package/dist/vba/project-editor.js +129 -119
  259. package/dist/vba/project.d.ts +15 -1
  260. package/dist/vba/project.js +38 -13
  261. package/dist/vba/vba-encoding.d.ts +4 -10
  262. package/dist/vba/vba-encoding.js +3 -17
  263. package/dist/xml/xml-attrs.d.ts +37 -0
  264. package/dist/xml/xml-attrs.js +30 -0
  265. package/dist/xml/xml-chars.d.ts +40 -0
  266. package/dist/xml/xml-chars.js +12 -0
  267. package/dist/xml/xml-namespaces.d.ts +31 -0
  268. package/dist/xml/xml-namespaces.js +50 -0
  269. package/dist/xml/xml-read.d.ts +101 -11
  270. package/dist/xml/xml-read.js +150 -18
  271. package/dist/xml/xml-scan.d.ts +25 -34
  272. package/dist/xml/xml-scan.js +69 -46
  273. package/dist/xml/xml.d.ts +59 -26
  274. package/dist/xml/xml.js +45 -23
  275. package/package.json +15 -9
  276. package/skills/ts-xlsx-upstream/SKILL.md +21 -13
  277. package/dist/core/modern-functions.d.ts +0 -1
@@ -1,74 +1,99 @@
1
- import { unmangleFunctions } from '../../core/formula.js';
1
+ import { definedNameKeys, unmangleFunctions } from '../../core/formula.js';
2
2
  import { INTERNAL } from '../../core/internal.js';
3
3
  import { Workbook } from '../../core/workbook.js';
4
+ import { quoted } from '../../errors.js';
5
+ import { indexCellMetadata } from '../cell-metadata/metadata.js';
6
+ import { parseRichValueErrors } from '../cell-metadata/rich-values.js';
4
7
  import { UnsupportedFormatError } from '../opc/errors.js';
5
8
  import { openSpreadsheetPackage, packageAccessors, readPartRelationships } from '../opc/read-opc.js';
9
+ import { admitting, repairedSheetNames } from '../read-policy/read-repair.js';
10
+ import { XlsbParseError } from './errors.js';
6
11
  import { decodeFormula } from './formula.js';
7
12
  import { RecordReader } from './primitives.js';
13
+ import { parseMetadataPart } from './read-metadata.js';
8
14
  import { parseSharedStrings } from './read-shared-strings.js';
9
15
  import { parseStyleTable } from './read-styles.js';
10
16
  import { parseWorksheet } from './read-worksheet.js';
11
- import { readRecords } from './record-stream.js';
17
+ import { blockTracker, readRecords } from './record-stream.js';
12
18
  import { BRT } from './record-types.js';
13
19
  export const XLSB_WORKBOOK_PART = 'xl/workbook.bin';
14
20
  export function readXlsb(data, options = {}) {
15
- return readXlsbPackage(openSpreadsheetPackage(data, options.maxUncompressedBytes).files);
21
+ const { files, documentPath, workbookXml } = openSpreadsheetPackage(data, options.maxUncompressedBytes);
22
+ if (workbookXml !== undefined) {
23
+ throw new UnsupportedFormatError('unknown', `not a valid .xlsb package: its office document ${quoted(documentPath)} is XML, not the binary ${XLSB_WORKBOOK_PART} a .xlsb carries; read it with readXlsx`);
24
+ }
25
+ return readXlsbPackage(files, documentPath);
16
26
  }
17
- export function readXlsbPackage(files) {
27
+ export function readXlsbPackage(files, documentPath = XLSB_WORKBOOK_PART) {
18
28
  const { partText, partBytes } = packageAccessors(files);
19
- const workbookPart = partBytes(XLSB_WORKBOOK_PART);
29
+ const workbookPart = partBytes(documentPath);
20
30
  if (workbookPart === undefined) {
21
- throw new UnsupportedFormatError('unknown', `not a valid .xlsb package: ${XLSB_WORKBOOK_PART} is missing`);
31
+ throw new UnsupportedFormatError('unknown', `not a valid .xlsb package: ${quoted(documentPath)} is missing`);
22
32
  }
23
- const rels = readPartRelationships(XLSB_WORKBOOK_PART, partText);
24
- const sharedStrings = parseSharedStrings(partBytes('xl/sharedStrings.bin'));
25
- const { cellXfs, namedStyles, defaultFont } = parseStyleTable(partBytes('xl/styles.bin'));
33
+ const rels = readPartRelationships(documentPath, partText, partBytes);
34
+ const sharedStrings = parseSharedStrings(rels.relatedBytes('sharedStrings') ?? partBytes('xl/sharedStrings.bin'));
35
+ const { cellXfs, namedStyles, defaultFont } = parseStyleTable(rels.relatedBytes('styles') ?? partBytes('xl/styles.bin'));
26
36
  const workbook = new Workbook();
27
37
  if (namedStyles.length > 1)
28
38
  workbook[INTERNAL].restoreNamedStyles(namedStyles);
29
39
  workbook[INTERNAL].restoreDefaultFont(defaultFont);
30
40
  const declaration = readWorkbookPart(workbookPart);
41
+ workbook.dateEpoch = declaration.dateEpoch;
42
+ const sheets = repairedSheetNames(declaration.sheets);
31
43
  const scope = {
32
- sheetNames: declaration.sheets.map((sheet) => sheet.name),
44
+ sheetNames: sheets.map((sheet) => sheet.name),
33
45
  externSheets: declaration.externSheets,
34
46
  selfSupBook: declaration.selfSupBook,
35
47
  names: declaration.names.map((name) => name.name),
36
48
  };
37
- for (const declared of declaration.sheets) {
49
+ const namesInWorkbook = definedNameKeys(declaration.names.filter(isWorkbookName));
50
+ const cellMetadata = indexCellMetadata(parseMetadataPart(rels.relatedBytes('sheetMetadata')), parseRichValueErrors(rels.relatedText('rdRichValueStructure') ?? '', rels.relatedText('rdRichValue') ?? ''));
51
+ for (const declared of sheets) {
38
52
  const sheet = workbook.addWorksheet(declared.name, { state: declared.state });
39
53
  const target = declared.relId === undefined ? undefined : rels.byId(declared.relId)?.target;
40
54
  const part = target === undefined ? undefined : partBytes(rels.pathOf(target));
41
55
  if (part !== undefined)
42
- parseWorksheet(part, sheet, sharedStrings, cellXfs, scope);
56
+ parseWorksheet(part, {
57
+ sheet,
58
+ sharedStrings,
59
+ xfStyles: cellXfs,
60
+ scope,
61
+ dateEpoch: declaration.dateEpoch,
62
+ definedNames: namesInWorkbook,
63
+ cellMetadata,
64
+ });
65
+ }
66
+ for (const defined of definedNames(declaration, scope, namesInWorkbook)) {
67
+ admitting(() => {
68
+ workbook.defineName(defined);
69
+ });
43
70
  }
44
- for (const defined of definedNames(declaration, scope))
45
- workbook.defineName(defined);
46
71
  return workbook;
47
72
  }
73
+ const WORKBOOK_BLOCKS = [
74
+ [BRT.BeginBundleShs, BRT.EndBundleShs, 'bundle'],
75
+ [BRT.BeginExternals, BRT.EndExternals, 'externals'],
76
+ ];
48
77
  function readWorkbookPart(part) {
49
78
  const sheets = [];
50
79
  const names = [];
51
80
  let externSheets = [];
52
- let inBundle = false;
53
- let inExternals = false;
81
+ const blocks = blockTracker(WORKBOOK_BLOCKS);
54
82
  let supportingBooks = 0;
55
83
  let selfSupBook;
84
+ let dateEpoch = 1900;
56
85
  for (const record of readRecords(part)) {
57
- if (record.type === BRT.BeginBundleShs)
58
- inBundle = true;
59
- else if (record.type === BRT.EndBundleShs)
60
- inBundle = false;
61
- else if (record.type === BRT.BundleSh && inBundle)
86
+ if (blocks.boundary(record.type))
87
+ continue;
88
+ if (record.type === BRT.WbProp)
89
+ dateEpoch = readDateEpoch(record.data);
90
+ else if (record.type === BRT.BundleSh && blocks.isOpen('bundle'))
62
91
  sheets.push(readSheet(record.data));
63
- else if (record.type === BRT.BeginExternals)
64
- inExternals = true;
65
- else if (record.type === BRT.EndExternals)
66
- inExternals = false;
67
92
  else if (record.type === BRT.ExternSheet)
68
93
  externSheets = readExternSheets(record.data);
69
94
  else if (record.type === BRT.SupSelf)
70
95
  selfSupBook = supportingBooks++;
71
- else if (inExternals)
96
+ else if (blocks.isOpen('externals'))
72
97
  supportingBooks++;
73
98
  else if (record.type === BRT.Name)
74
99
  names.push(readName(record.data));
@@ -78,8 +103,14 @@ function readWorkbookPart(part) {
78
103
  names,
79
104
  externSheets,
80
105
  selfSupBook: supportingBooks === 1 ? selfSupBook : undefined,
106
+ dateEpoch,
81
107
  };
82
108
  }
109
+ function readDateEpoch(data) {
110
+ if (data.length < 4)
111
+ return 1900;
112
+ return (new RecordReader(data).u32() & 1) === 0 ? 1900 : 1904;
113
+ }
83
114
  function readSheet(data) {
84
115
  const reader = new RecordReader(data);
85
116
  const state = SHEET_STATES[reader.u32()] ?? 'visible';
@@ -90,9 +121,11 @@ function readSheet(data) {
90
121
  function readExternSheets(data) {
91
122
  const reader = new RecordReader(data);
92
123
  const count = reader.u32();
124
+ if (count * XTI_BYTES > reader.remaining) {
125
+ throw new XlsbParseError(`BIFF12 externSheet table declares ${count} entries needing ${count * XTI_BYTES} bytes but ` +
126
+ `only ${reader.remaining} remain in the record`);
127
+ }
93
128
  const entries = [];
94
- if (count * XTI_BYTES > reader.remaining)
95
- return entries;
96
129
  for (let index = 0; index < count; index++) {
97
130
  entries.push({ supBook: reader.u32(), firstSheet: reader.i32(), lastSheet: reader.i32() });
98
131
  }
@@ -117,10 +150,10 @@ function readName(data) {
117
150
  }
118
151
  const GLOBAL_NAME_SCOPE = 0xffffffff;
119
152
  const NAME_IS_FUNCTION = 0x00000002;
120
- function definedNames(declaration, scope) {
153
+ function definedNames(declaration, scope, namesInWorkbook) {
121
154
  const names = [];
122
155
  for (const declared of declaration.names) {
123
- if (declared.isFunction || declared.name === FILTER_DATABASE_NAME)
156
+ if (!isWorkbookName(declared))
124
157
  continue;
125
158
  const refersTo = decodeFormula(declared.rgce, declared.rgcb, scope);
126
159
  if (refersTo === undefined)
@@ -129,10 +162,16 @@ function definedNames(declaration, scope) {
129
162
  names.push({
130
163
  name: declared.name,
131
164
  ...(sheet === undefined ? {} : { scope: sheet }),
132
- refersTo: unmangleFunctions(refersTo),
165
+ refersTo: unmangleFunctions(refersTo, namesInWorkbook),
133
166
  });
134
167
  }
135
168
  return names;
136
169
  }
170
+ function isWorkbookName(declared) {
171
+ return (!declared.isFunction &&
172
+ !FORMULA_PLACEHOLDER_NAME.test(declared.name) &&
173
+ declared.name !== FILTER_DATABASE_NAME);
174
+ }
175
+ const FORMULA_PLACEHOLDER_NAME = /^_xl(?:fn|pm|eta)\./;
137
176
  const FILTER_DATABASE_NAME = '_xlnm._FilterDatabase';
138
177
  const SHEET_STATES = ['visible', 'hidden', 'veryHidden'];
@@ -12,3 +12,33 @@ export interface BiffRecord {
12
12
  * end of the part.
13
13
  */
14
14
  export declare function readRecords(part: Uint8Array): Generator<BiffRecord>;
15
+ /**
16
+ * Track which `Begin…`/`End…` blocks a BIFF12 record stream is currently inside.
17
+ *
18
+ * BIFF12 is flat: a collection is a `BeginFonts` record, its members, then `EndFonts`, and a reader
19
+ * has to carry that state itself. Two readers here did, and only one did it legibly. The style reader
20
+ * kept an explicit collection with start and end tables; the workbook reader re-solved it with loose
21
+ * booleans in an if-else chain whose *ordering was load-bearing and unstated*: move the `EndExternals`
22
+ * arm below the catch-all that counts records inside the externals block and the count silently goes
23
+ * wrong. Answering "is this record a block boundary" separately from "what does this record mean"
24
+ * removes that constraint rather than documenting it.
25
+ *
26
+ * Each end names the block it closes, so an `EndFonts` cannot close `<fills>` the way a bare set of
27
+ * end markers allowed. Blocks are tracked independently, so two that a damaged file interleaves stay
28
+ * separate rather than one clearing the other.
29
+ *
30
+ * A block is declared as one `[start, end, block]` triple rather than as an entry in a start table
31
+ * and a matching entry in an end table. The two-table form let a caller pair `BeginFills` with
32
+ * `EndFonts` in a way that compiles and reads plausibly, which is the very mistake the paragraph
33
+ * above says this exists to prevent.
34
+ */
35
+ export declare function blockTracker<T>(blocks: readonly (readonly [number, number, T])[]): BlockTracker<T>;
36
+ export interface BlockTracker<T> {
37
+ /** Whether the stream is currently inside `block`. */
38
+ isOpen(block: T): boolean;
39
+ /**
40
+ * Take a record's type as a possible block boundary, returning whether it was one. A boundary
41
+ * carries no content of its own, so a caller that gets `true` skips the record entirely.
42
+ */
43
+ boundary(type: number): boolean;
44
+ }
@@ -26,3 +26,23 @@ function byteAt(part, index) {
26
26
  throw new XlsbParseError('truncated BIFF12 record header');
27
27
  return value;
28
28
  }
29
+ export function blockTracker(blocks) {
30
+ const starts = new Map(blocks.map(([start, , block]) => [start, block]));
31
+ const ends = new Map(blocks.map(([, end, block]) => [end, block]));
32
+ const open = new Set();
33
+ return {
34
+ isOpen: (block) => open.has(block),
35
+ boundary(type) {
36
+ const ended = ends.get(type);
37
+ if (ended !== undefined) {
38
+ open.delete(ended);
39
+ return true;
40
+ }
41
+ const started = starts.get(type);
42
+ if (started === undefined)
43
+ return false;
44
+ open.add(started);
45
+ return true;
46
+ },
47
+ };
48
+ }
@@ -16,7 +16,6 @@ export declare const BRT: {
16
16
  readonly ColInfo: 60;
17
17
  readonly MergeCell: 176;
18
18
  readonly SSTItem: 19;
19
- readonly BeginSst: 159;
20
19
  readonly EndSst: 160;
21
20
  readonly Fmt: 44;
22
21
  readonly Font: 43;
@@ -38,6 +37,7 @@ export declare const BRT: {
38
37
  readonly EndCellXFs: 618;
39
38
  readonly BeginStyles: 619;
40
39
  readonly EndStyles: 620;
40
+ readonly WbProp: 153;
41
41
  readonly BundleSh: 156;
42
42
  readonly BeginBundleShs: 143;
43
43
  readonly EndBundleShs: 144;
@@ -46,10 +46,19 @@ export declare const BRT: {
46
46
  readonly EndExternals: 354;
47
47
  readonly SupSelf: 357;
48
48
  readonly ExternSheet: 362;
49
- readonly WsProp: 147;
50
- readonly WsDim: 148;
51
49
  readonly WsFmtInfo: 485;
52
- readonly BeginSheetData: 145;
53
- readonly EndSheetData: 146;
54
50
  readonly ArrFmla: 426;
51
+ readonly SheetProtection: 535;
52
+ readonly SheetProtectionIso: 678;
53
+ readonly CellMeta: 49;
54
+ readonly ValueMeta: 50;
55
+ readonly Mdtinfo: 335;
56
+ readonly BeginEsfmd: 339;
57
+ readonly EndEsfmd: 340;
58
+ readonly BeginFmd: 52;
59
+ readonly BeginEsmdb: 337;
60
+ readonly EndEsmdb: 338;
61
+ readonly Mdb: 51;
62
+ readonly DynamicArrayProperties: 4097;
63
+ readonly RichValueBlock: 5003;
55
64
  };
@@ -15,7 +15,6 @@ export const BRT = {
15
15
  ColInfo: 60,
16
16
  MergeCell: 176,
17
17
  SSTItem: 19,
18
- BeginSst: 159,
19
18
  EndSst: 160,
20
19
  Fmt: 44,
21
20
  Font: 43,
@@ -37,6 +36,7 @@ export const BRT = {
37
36
  EndCellXFs: 618,
38
37
  BeginStyles: 619,
39
38
  EndStyles: 620,
39
+ WbProp: 153,
40
40
  BundleSh: 156,
41
41
  BeginBundleShs: 143,
42
42
  EndBundleShs: 144,
@@ -45,10 +45,19 @@ export const BRT = {
45
45
  EndExternals: 354,
46
46
  SupSelf: 357,
47
47
  ExternSheet: 362,
48
- WsProp: 147,
49
- WsDim: 148,
50
48
  WsFmtInfo: 485,
51
- BeginSheetData: 145,
52
- EndSheetData: 146,
53
49
  ArrFmla: 426,
50
+ SheetProtection: 535,
51
+ SheetProtectionIso: 678,
52
+ CellMeta: 49,
53
+ ValueMeta: 50,
54
+ Mdtinfo: 335,
55
+ BeginEsfmd: 339,
56
+ EndEsfmd: 340,
57
+ BeginFmd: 52,
58
+ BeginEsmdb: 337,
59
+ EndEsmdb: 338,
60
+ Mdb: 51,
61
+ DynamicArrayProperties: 4097,
62
+ RichValueBlock: 5003,
54
63
  };
@@ -0,0 +1,20 @@
1
+ import type { AssertNever } from '../../core/internal.ts';
2
+ import { type SheetProtection, type SheetProtectionFlags } from '../../core/protection.ts';
3
+ import type { RecordReader } from './primitives.ts';
4
+ declare const FLAGS_IN_RECORD_ORDER: readonly ["objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"];
5
+ /**
6
+ * The half of the proof an ordered list owes: `satisfies` covers "no invented flag", this covers "no
7
+ * omission". A flag left out here would be read at the wrong offset along with every flag after it.
8
+ */
9
+ export type EveryProtectionFlagHasARecordSlot = AssertNever<Exclude<keyof SheetProtectionFlags, (typeof FLAGS_IN_RECORD_ORDER)[number]>>;
10
+ /** What a worksheet's protection records say, gathered as they arrive. */
11
+ export declare class SheetProtectionRecords {
12
+ #private;
13
+ /** Read a `BrtSheetProtection`. */
14
+ legacy(reader: RecordReader): void;
15
+ /** Read a `BrtSheetProtectionIso`. */
16
+ iso(reader: RecordReader): void;
17
+ /** The protection the records described, or `undefined` for a sheet that is not protected. */
18
+ result(): SheetProtection | undefined;
19
+ }
20
+ export {};
@@ -0,0 +1,60 @@
1
+ import { toBase64 } from '../../bytes.js';
2
+ import { SHEET_PROTECTION_FLAGS, } from '../../core/protection.js';
3
+ import { hex } from '../../hex.js';
4
+ const FLAGS_IN_RECORD_ORDER = [
5
+ 'objects',
6
+ 'scenarios',
7
+ 'formatCells',
8
+ 'formatColumns',
9
+ 'formatRows',
10
+ 'insertColumns',
11
+ 'insertRows',
12
+ 'insertHyperlinks',
13
+ 'deleteColumns',
14
+ 'deleteRows',
15
+ 'selectLockedCells',
16
+ 'sort',
17
+ 'autoFilter',
18
+ 'pivotTables',
19
+ 'selectUnlockedCells',
20
+ ];
21
+ const ALLOWED_BY_DEFAULT = new Map(SHEET_PROTECTION_FLAGS.map(({ key, defaultForbidden }) => [key, !defaultForbidden]));
22
+ export class SheetProtectionRecords {
23
+ #locked = false;
24
+ #flags = {};
25
+ #legacyPasswordHash;
26
+ #credential;
27
+ legacy(reader) {
28
+ const protpwd = reader.u16();
29
+ this.#readFlags(reader);
30
+ this.#legacyPasswordHash = protpwd === 0 ? undefined : hex(protpwd, 4);
31
+ }
32
+ iso(reader) {
33
+ const spinCount = reader.u32();
34
+ this.#readFlags(reader);
35
+ const hashValue = toBase64(reader.bytes(reader.u32()));
36
+ const saltValue = toBase64(reader.bytes(reader.u32()));
37
+ this.#credential = { algorithmName: reader.wideString(), hashValue, saltValue, spinCount };
38
+ }
39
+ result() {
40
+ if (!this.#locked)
41
+ return undefined;
42
+ return {
43
+ flags: this.#flags,
44
+ ...(this.#credential === undefined ? {} : { credential: this.#credential }),
45
+ ...(this.#legacyPasswordHash === undefined
46
+ ? {}
47
+ : { legacyPasswordHash: this.#legacyPasswordHash }),
48
+ };
49
+ }
50
+ #readFlags(reader) {
51
+ this.#locked = reader.u32() !== 0;
52
+ const flags = {};
53
+ for (const key of FLAGS_IN_RECORD_ORDER) {
54
+ const allowed = reader.u32() !== 0;
55
+ if (allowed !== ALLOWED_BY_DEFAULT.get(key))
56
+ flags[key] = allowed;
57
+ }
58
+ this.#flags = flags;
59
+ }
60
+ }
@@ -1,30 +1,46 @@
1
+ import type { DateEpoch } from '../../core/date.ts';
1
2
  import type { CellValue } from '../../core/value.ts';
2
3
  import type { Worksheet } from '../../core/worksheet.ts';
3
4
  import { type XmlAttributes } from '../../xml/xml-scan.ts';
5
+ import type { CellMetadataIndex } from '../cell-metadata/metadata.ts';
4
6
  import { type XfStyle } from '../style/xf-style.ts';
5
7
  import { type SharedString } from './cell-value.ts';
8
+ /**
9
+ * The worksheet-body elements both readers expand from `<x/>` into an open and a close, so each
10
+ * commits from its close alone. A formatted-but-empty `<c/>` finalises once there, and a self-closing
11
+ * `<row/>` closes its row, where the streamer yields it and both readers end its style and its cells:
12
+ * a producer may write `<row r="2" hidden="1"/>`, and with no close the streamer lost the row and its
13
+ * `hidden` flag. The text-bearing `<f/>`/`<v/>`/`<t/>` stay out, so an empty one never commits text.
14
+ */
15
+ export declare const WORKSHEET_BODY_EMPTY_CLOSES: ReadonlySet<string>;
6
16
  export declare class CellAccumulator {
7
17
  #private;
8
18
  constructor(options: {
9
- readonly richRuns: boolean;
19
+ readonly dateEpoch: DateEpoch;
20
+ readonly definedNames: ReadonlySet<string>;
21
+ readonly cellMetadata: CellMetadataIndex;
10
22
  });
11
23
  /** This cell's `<c r>` address (`"B3"`), or '' when it carried none. */
12
24
  get ref(): string;
13
25
  /** This cell's own `<c s>` style index, or -1 when it carries none. */
14
26
  get styleIndex(): number;
15
- /** This cell's 1-based column, or -1 when its address was absent or unparseable. */
27
+ /** This cell's 1-based column, or -1 when its address was unparseable. */
16
28
  get col(): number;
17
29
  /**
18
- * The text gathered since the current element opened. A caller reads it for the elements it
19
- * captures itself (see {@link capture}); the machine reads it for its own.
30
+ * Open a `<row>`: the cells that follow belong to it, and the next one with no `r` of its own is
31
+ * its first column. A row past the grid opens no row, so none of its cells is placed, not even one
32
+ * whose own `r` names an in-grid cell. Both readers call this where they already tell the style
33
+ * resolver a row opened.
20
34
  */
21
- get capturedText(): string;
22
- /** Gather the current element's text for the caller's own use, the way `<v>` and `<t>` do. */
23
- capture(): void;
35
+ openRow(number: number, inGrid: boolean): void;
36
+ /** Whether an in-grid `<row>` is open. */
37
+ get rowOpen(): boolean;
38
+ /** Close the `<row>`: a `<c>` before the next one belongs to no row and is not placed. */
39
+ closeRow(): void;
24
40
  /**
25
41
  * Drive one element open, and return whether it was one of the cell machine's own. Every open
26
42
  * resets the capture state first, which is true of both readers and of every element, not just
27
- * these; a caller that captures its own text calls {@link capture} after this returns.
43
+ * these. A caller gathering text of its own uses a `TextCapture`, not this machine's buffer.
28
44
  */
29
45
  openElement(local: string, attrs: XmlAttributes, selfClosing: boolean): boolean;
30
46
  /** Feed one run of character data. Ignored unless something is capturing. */
@@ -37,6 +53,5 @@ export declare class CellAccumulator {
37
53
  */
38
54
  closeElement(local: string): 'cell' | 'claimed' | 'other';
39
55
  finalize(sheet: Worksheet, sharedStrings: readonly SharedString[], style: XfStyle | undefined): void;
40
- private cachedResult;
41
56
  decode(sharedStrings: readonly SharedString[], style: XfStyle | undefined): CellValue;
42
57
  }
@@ -1,20 +1,28 @@
1
- import { encodeAddress, tryDecodeCellRef } from '../../core/address.js';
2
- import { translateFormula, unmangleFunctions } from '../../core/formula.js';
3
- import { boolStrict, numInteger } from '../../xml/xml-scan.js';
1
+ import { encodeAddress, encodeRange, MAX_COLUMN, tryDecodeAnchoredRange, tryDecodeCellRef, } from '../../core/address.js';
2
+ import { translateFormula } from '../../core/formula-references.js';
3
+ import { unmangleFunctions } from '../../core/formula.js';
4
+ import { numInteger } from '../../xml/xml-attrs.js';
5
+ import { boolStrict } from '../../xml/xml-scan.js';
4
6
  import { applyXfToCell } from '../style/xf-style.js';
5
7
  import { decodeCellContent, decodeFormulaResult, } from './cell-value.js';
6
- import { RunAccumulator } from './rich-runs.js';
8
+ import { RunAccumulator } from './read-rich-runs.js';
9
+ export const WORKSHEET_BODY_EMPTY_CLOSES = new Set(['c', 'row']);
7
10
  export class CellAccumulator {
8
11
  #ref = '';
9
12
  #type = '';
10
13
  #style = -1;
11
14
  #col = -1;
12
15
  #row = -1;
16
+ #cellMetadataBlock = -1;
17
+ #valueMetadataBlock = -1;
18
+ #rowOpen = false;
19
+ #nextCol = 1;
13
20
  #formula = '';
14
21
  #formulaShared = false;
15
22
  #formulaSi = -1;
16
23
  #sharedClone = false;
17
24
  #dataTable = null;
25
+ #arrayRef = undefined;
18
26
  #valueText = '';
19
27
  #hasFormula = false;
20
28
  #hasValue = false;
@@ -22,8 +30,14 @@ export class CellAccumulator {
22
30
  #masters = new Map();
23
31
  #capture = false;
24
32
  #text = '';
33
+ #dateEpoch;
34
+ #definedNames;
35
+ #cellMetadata;
25
36
  constructor(options) {
26
- this.#runs = new RunAccumulator({ container: 'is', readRuns: options.richRuns });
37
+ this.#runs = new RunAccumulator({ container: 'is', readRuns: true });
38
+ this.#dateEpoch = options.dateEpoch;
39
+ this.#definedNames = options.definedNames;
40
+ this.#cellMetadata = options.cellMetadata;
27
41
  }
28
42
  get ref() {
29
43
  return this.#ref;
@@ -34,13 +48,24 @@ export class CellAccumulator {
34
48
  get col() {
35
49
  return this.#col;
36
50
  }
51
+ openRow(number, inGrid) {
52
+ this.#rowOpen = inGrid;
53
+ this.#row = inGrid ? number : -1;
54
+ this.#nextCol = 1;
55
+ }
56
+ get rowOpen() {
57
+ return this.#rowOpen;
58
+ }
59
+ closeRow() {
60
+ this.#rowOpen = false;
61
+ this.#row = -1;
62
+ }
37
63
  #beginCell(attrs) {
38
64
  this.#type = attrs.t ?? '';
39
65
  this.#style = numInteger(attrs.s, 0) ?? -1;
40
- const decoded = tryDecodeCellRef(attrs.r ?? '');
41
- this.#ref = decoded === undefined ? '' : (attrs.r ?? '');
42
- this.#col = decoded?.col ?? -1;
43
- this.#row = decoded?.row ?? -1;
66
+ this.#cellMetadataBlock = numInteger(attrs.cm, 1) ?? -1;
67
+ this.#valueMetadataBlock = numInteger(attrs.vm, 1) ?? -1;
68
+ this.#placeCell(attrs.r);
44
69
  this.#formula = '';
45
70
  this.#valueText = '';
46
71
  this.#runs.beginContainer();
@@ -50,6 +75,25 @@ export class CellAccumulator {
50
75
  this.#formulaSi = -1;
51
76
  this.#sharedClone = false;
52
77
  this.#dataTable = null;
78
+ this.#arrayRef = undefined;
79
+ }
80
+ #placeCell(ref) {
81
+ const decoded = this.#rowOpen && ref !== undefined ? tryDecodeCellRef(ref) : undefined;
82
+ if (decoded !== undefined) {
83
+ this.#ref = ref ?? '';
84
+ this.#col = decoded.col;
85
+ this.#row = decoded.row;
86
+ }
87
+ else if (ref === undefined && this.#rowOpen && this.#nextCol <= MAX_COLUMN) {
88
+ this.#col = this.#nextCol;
89
+ this.#ref = encodeAddress(this.#col, this.#row);
90
+ }
91
+ else {
92
+ this.#ref = '';
93
+ this.#col = -1;
94
+ }
95
+ if (this.#col > 0)
96
+ this.#nextCol = this.#col + 1;
53
97
  }
54
98
  #beginFormula(attrs, selfClosing) {
55
99
  this.#formulaShared = attrs.t === 'shared';
@@ -63,8 +107,15 @@ export class CellAccumulator {
63
107
  dtr: attrs.dtr,
64
108
  r1: attrs.r1,
65
109
  r2: attrs.r2,
110
+ del1: attrs.del1,
111
+ del2: attrs.del2,
66
112
  };
67
113
  }
114
+ if (attrs.t === 'array' && attrs.ref !== undefined && this.#col > 0) {
115
+ const range = tryDecodeAnchoredRange(attrs.ref, this.#col, this.#row);
116
+ if (range !== undefined)
117
+ this.#arrayRef = encodeRange(range);
118
+ }
68
119
  }
69
120
  #setFormula(text) {
70
121
  this.#formula = text;
@@ -74,12 +125,6 @@ export class CellAccumulator {
74
125
  this.#valueText = text;
75
126
  this.#hasValue = true;
76
127
  }
77
- get capturedText() {
78
- return this.#text;
79
- }
80
- capture() {
81
- this.#capture = true;
82
- }
83
128
  openElement(local, attrs, selfClosing) {
84
129
  this.#text = '';
85
130
  this.#capture = false;
@@ -95,6 +140,8 @@ export class CellAccumulator {
95
140
  return true;
96
141
  case 'v':
97
142
  this.#capture = !selfClosing;
143
+ if (selfClosing)
144
+ this.#setValue('');
98
145
  return true;
99
146
  default:
100
147
  return false;
@@ -143,7 +190,9 @@ export class CellAccumulator {
143
190
  ...(boolStrict(this.#dataTable.dtr) ? { dataTableRow: true } : {}),
144
191
  ...(this.#dataTable.r1 !== undefined ? { r1: this.#dataTable.r1 } : {}),
145
192
  ...(this.#dataTable.r2 !== undefined ? { r2: this.#dataTable.r2 } : {}),
146
- ...this.cachedResult(style),
193
+ ...(boolStrict(this.#dataTable.del1) ? { r1Deleted: true } : {}),
194
+ ...(boolStrict(this.#dataTable.del2) ? { r2Deleted: true } : {}),
195
+ ...this.#cachedResult(style),
147
196
  };
148
197
  }
149
198
  if (this.#hasFormula && this.#formulaShared && this.#formulaSi >= 0) {
@@ -155,17 +204,17 @@ export class CellAccumulator {
155
204
  const translated = translateFormula(master.formula, this.#col - master.col, this.#row - master.row);
156
205
  return {
157
206
  sharedFormula: encodeAddress(master.col, master.row),
158
- formula: unmangleFunctions(translated),
159
- ...this.cachedResult(style),
207
+ formula: unmangleFunctions(translated, this.#definedNames),
208
+ ...this.#cachedResult(style),
160
209
  };
161
210
  }
162
211
  }
163
212
  return this.decode(sharedStrings, style);
164
213
  }
165
- cachedResult(style) {
214
+ #cachedResult(style) {
166
215
  if (!this.#hasValue)
167
216
  return {};
168
- const result = decodeFormulaResult(this.#type, this.#valueText, style?.numFmt);
217
+ const result = decodeFormulaResult(this.#type, this.#valueText, style?.numFmt, this.#dateEpoch, this.#cellMetadata.valueErrors.get(this.#valueMetadataBlock));
169
218
  return result === undefined ? {} : { result };
170
219
  }
171
220
  decode(sharedStrings, style) {
@@ -173,11 +222,15 @@ export class CellAccumulator {
173
222
  type: this.#type,
174
223
  hasFormula: this.#hasFormula,
175
224
  formula: this.#formula,
225
+ arrayRef: this.#arrayRef,
226
+ dynamicArray: this.#cellMetadata.dynamicArrayCells.has(this.#cellMetadataBlock),
227
+ valueError: this.#cellMetadata.valueErrors.get(this.#valueMetadataBlock),
176
228
  hasValue: this.#hasValue,
177
229
  valueText: this.#valueText,
230
+ hasInlineString: this.#runs.opened,
178
231
  inlineText: this.#runs.plainText,
179
232
  richTextRuns: this.#runs.runs,
180
233
  };
181
- return decodeCellContent(raw, sharedStrings, style?.numFmt);
234
+ return decodeCellContent(raw, sharedStrings, style?.numFmt, this.#dateEpoch, this.#definedNames);
182
235
  }
183
236
  }