@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,47 +1,49 @@
1
- import { decodeRange } from '../../core/address.js';
2
- import { unmangleFunctions } from '../../core/formula.js';
3
1
  import { INTERNAL } from '../../core/internal.js';
4
- import { WORKBOOK_PROTECTION_CREDENTIAL_ATTRS, } from '../../core/workbook-protection.js';
5
2
  import { Workbook } from '../../core/workbook.js';
6
- import { isVisibility } from '../../core/worksheet.js';
7
- import { capturedText, openElements, parseXml, parseXmlPasses } from '../../xml/xml-read.js';
8
- import { boolStrict, enumToken, localName, numInteger } from '../../xml/xml-scan.js';
3
+ import { parseXmlPasses } from '../../xml/xml-read.js';
9
4
  import { UnsupportedFormatError } from '../opc/errors.js';
10
- import { extensionOf, resolveRelativePart } from '../opc/part-paths.js';
11
- import { capturePartClosure, contentTypeResolver, openSpreadsheetPackage, parseRelationshipRecords, readPartRelationships, } from '../opc/read-opc.js';
12
- import { readXlsbPackage, XLSB_WORKBOOK_PART } from '../xlsb/read.js';
13
- import { applyNotes, parseComments } from './comments.js';
14
- import { conditionalFormattingPass } from './conditional-formatting.js';
5
+ import { contentTypeResolver, openSpreadsheetPackage, readPartRelationships, } from '../opc/read-opc.js';
6
+ import { admitArrayRanges, admitting, repairedSheetNames } from '../read-policy/read-repair.js';
7
+ import { readXlsbPackage } from '../xlsb/read.js';
8
+ import { readCellMetadata } from './cell-metadata.js';
9
+ import { applyConditionalFormattings, conditionalFormattingPass } from './conditional-formatting.js';
15
10
  import { applyDataValidations, dataValidationPass, extendedDataValidationPass, } from './data-validation.js';
16
11
  import { applyHyperlinks, sheetHyperlinkPass } from './hyperlinks.js';
17
- import { drawingHasUnmodeledContent, parseDrawing } from './images.js';
18
- import { parsePivotTable } from './read-pivot.js';
12
+ import { SHARED_STRINGS_PART, STYLES_PART } from './part-names.js';
13
+ import { applyNotes } from './read-comments.js';
14
+ import { readRootPreservedReferences, readSheetBackground, readSheetComments, readSheetCommentThreads, readSheetImages, readSheetPivotTables, readSheetPreservedReferences, readSheetPrinterSettings, readSheetTables, readWorkbookPersons, externalReferenceRegistrationsPass, pivotCacheRegistrationsPass, readWorkbookPreservedReferences, readWorkbookTheme, worksheetReferencePass, } from './read-parts.js';
19
15
  import { parseSharedStrings } from './read-shared-strings.js';
20
16
  import { parseStyleTable } from './read-styles.js';
17
+ import { applyAppProperties, applyCoreProperties, definedNamesPass, workbookPropertiesPass, workbookProtectionPass, workbookSheetsPass, workbookViewPass, } from './read-workbook-xml.js';
21
18
  import { worksheetPass } from './read-worksheet.js';
22
- import { parseTable } from './tables.js';
23
- import { parseThemeColorScheme, parseThemeFontScheme } from './theme-xml.js';
24
- import { buildCommentThreads, parsePersons, parseThreadedComments } from './threaded-comments.js';
25
- export { parseStyleTable } from './read-styles.js';
26
19
  export function readXlsx(data, options = {}) {
27
- const { files, pkg, workbookXml } = openSpreadsheetPackage(data, options.maxUncompressedBytes);
28
- const { partText } = pkg;
20
+ const { files, pkg, documentPath, workbookXml } = openSpreadsheetPackage(data, options.maxUncompressedBytes);
21
+ const { partText, partBytes } = pkg;
29
22
  if (workbookXml === undefined) {
30
- if (files[XLSB_WORKBOOK_PART] !== undefined)
31
- return readXlsbPackage(files);
23
+ if (partBytes(documentPath) !== undefined)
24
+ return readXlsbPackage(files, documentPath);
32
25
  throw new UnsupportedFormatError('unknown');
33
26
  }
34
27
  const contentTypeOf = contentTypeResolver(partText('[Content_Types].xml') ?? '');
35
- const workbookRels = readPartRelationships('xl/workbook.xml', partText);
36
- const sharedStrings = parseSharedStrings(partText('xl/sharedStrings.xml') ?? '');
37
- const stylesXml = partText('xl/styles.xml') ?? '';
28
+ const workbookRels = readPartRelationships(documentPath, partText);
29
+ const sharedStrings = parseSharedStrings(workbookRels.relatedTextOrPath('sharedStrings', SHARED_STRINGS_PART));
30
+ const stylesXml = workbookRels.relatedTextOrPath('styles', STYLES_PART);
38
31
  const { cellXfs: xfStyles, namedStyles, defaultFont, preserved } = parseStyleTable(stylesXml);
39
32
  const workbook = new Workbook();
33
+ const context = {
34
+ pkg,
35
+ workbook,
36
+ contentTypeOf,
37
+ sharedStrings,
38
+ xfStyles,
39
+ cellMetadata: readCellMetadata(workbookRels),
40
+ imageIdByMediaPath: new Map(),
41
+ };
40
42
  workbook[INTERNAL].restoreDifferentialStyles([...preserved.dxfs]);
41
43
  workbook[INTERNAL].restoreIndexedColors([...preserved.indexedColors]);
42
44
  workbook[INTERNAL].restoreMruColors([...preserved.mruColors]);
43
45
  workbook[INTERNAL].restoreTableStyles(preserved.tableStyles);
44
- readWorkbookTheme(workbookRels, pkg, contentTypeOf, workbook);
46
+ readWorkbookTheme(context, workbookRels);
45
47
  if (namedStyles.length > 1)
46
48
  workbook[INTERNAL].restoreNamedStyles(namedStyles);
47
49
  workbook[INTERNAL].restoreDefaultFont(defaultFont);
@@ -51,423 +53,84 @@ export function readXlsx(data, options = {}) {
51
53
  const app = partText('docProps/app.xml');
52
54
  if (app !== undefined)
53
55
  applyAppProperties(workbook, app);
54
- workbook.protection = parseWorkbookProtection(workbookXml);
55
- applyWorkbookView(workbook.view, workbookXml);
56
- readWorkbookPersons(workbookRels, pkg, workbook);
57
- const context = {
58
- pkg,
59
- workbook,
60
- contentTypeOf,
61
- sharedStrings,
62
- xfStyles,
63
- imageIdByMediaPath: new Map(),
64
- };
56
+ const protection = workbookProtectionPass();
57
+ const sheets = workbookSheetsPass();
58
+ const definedNames = definedNamesPass();
59
+ const pivotCaches = pivotCacheRegistrationsPass();
60
+ const externalReferences = externalReferenceRegistrationsPass();
61
+ parseXmlPasses(workbookXml, [
62
+ protection,
63
+ workbookPropertiesPass(workbook),
64
+ workbookViewPass(workbook.view),
65
+ sheets,
66
+ definedNames,
67
+ pivotCaches,
68
+ externalReferences,
69
+ ]);
70
+ workbook.protection = protection.result();
71
+ readWorkbookPersons(context, workbookRels);
72
+ const sheetContext = { ...context, definedNames: definedNames.spellings() };
65
73
  const sheetOrder = [];
66
- for (const { name, relId, state } of parseWorkbookSheets(workbookXml)) {
74
+ for (const { name, relId, state } of repairedSheetNames(sheets.result())) {
67
75
  const target = workbookRels.byId(relId)?.target;
68
76
  const sheet = workbook.addWorksheet(name, state === undefined ? undefined : { state });
69
- sheetOrder.push(name);
70
- readSheet(sheet, target === undefined ? undefined : workbookRels.pathOf(target), context);
77
+ sheetOrder.push(sheet.name);
78
+ readSheet(sheet, target === undefined ? undefined : workbookRels.pathOf(target), sheetContext);
71
79
  }
72
- readWorkbookPreservedReferences(workbookXml, workbookRels, pkg, contentTypeOf, workbook);
73
- readRootPreservedReferences(pkg, contentTypeOf, workbook);
74
- for (const name of parseWorkbookDefinedNames(workbookXml, sheetOrder)) {
75
- workbook.defineName(name);
80
+ readWorkbookPreservedReferences(context, workbookRels, {
81
+ cacheIdByRelId: pivotCaches.result(),
82
+ externalIndexByRelId: externalReferences.result(),
83
+ });
84
+ readRootPreservedReferences(context);
85
+ for (const name of definedNames.result(sheetOrder)) {
86
+ admitting(() => {
87
+ workbook.defineName(name);
88
+ });
76
89
  }
77
90
  return workbook;
78
91
  }
79
92
  function readSheet(sheet, path, context) {
80
- const { pkg, workbook, contentTypeOf, sharedStrings, xfStyles, imageIdByMediaPath } = context;
93
+ const { pkg, workbook, sharedStrings, xfStyles, definedNames, cellMetadata } = context;
81
94
  const { partText } = pkg;
82
95
  const sheetXml = path === undefined ? undefined : partText(path);
83
96
  const hyperlinks = sheetHyperlinkPass();
84
- const validations = dataValidationPass();
85
- const extendedValidations = extendedDataValidationPass();
86
- const formattings = conditionalFormattingPass();
97
+ const validations = dataValidationPass(definedNames);
98
+ const extendedValidations = extendedDataValidationPass(definedNames);
99
+ const formattings = conditionalFormattingPass(definedNames, (fragment) => workbook[INTERNAL].adoptDifferentialStyle(fragment));
100
+ const references = worksheetReferencePass();
87
101
  if (sheetXml !== undefined) {
88
102
  parseXmlPasses(sheetXml, [
89
- worksheetPass(sheet, sharedStrings, xfStyles),
103
+ worksheetPass(sheet, sharedStrings, xfStyles, workbook.dateEpoch, definedNames, cellMetadata),
90
104
  hyperlinks,
91
105
  validations,
92
106
  extendedValidations,
93
107
  formattings,
108
+ references,
94
109
  ]);
110
+ admitArrayRanges(sheet);
95
111
  }
96
112
  if (path === undefined)
97
113
  return;
98
- const sheetRels = readPartRelationships(path, partText);
114
+ const sheetRels = readPartRelationships(path, partText, pkg.partBytes);
99
115
  if (sheetXml !== undefined) {
100
116
  applyHyperlinks(sheet, hyperlinks.result(), (id) => sheetRels.byId(id)?.target);
101
117
  applyDataValidations(sheet, [...validations.result(), ...extendedValidations.result()]);
102
- for (const cf of formattings.result())
103
- sheet.addConditionalFormatting(cf);
118
+ applyConditionalFormattings(sheet, formattings.result());
104
119
  }
105
- const threads = readSheetCommentThreads(sheetRels, pkg, workbook);
120
+ const threads = readSheetCommentThreads(context, sheetRels);
106
121
  if (threads.length > 0)
107
122
  sheet[INTERNAL].restoreCommentThreads(threads);
108
- const comments = readSheetComments(sheetRels, pkg);
123
+ const comments = readSheetComments(sheetRels);
109
124
  if (comments !== undefined)
110
125
  applyNotes(sheet, comments);
111
- readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
112
- readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
126
+ readSheetImages(context, sheetRels, sheet);
127
+ readSheetBackground(context, sheetRels, sheet);
113
128
  if (sheetXml !== undefined) {
114
- readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet);
129
+ readSheetPreservedReferences(context, sheetRels, references.result(), sheet);
115
130
  }
116
- readSheetTables(sheetRels, pkg, sheet);
117
- readSheetPivotTables(sheetRels, pkg, sheet);
118
- const printerSettings = readSheetPrinterSettings(sheetRels, pkg);
131
+ readSheetTables(context, sheetRels, sheet, definedNames);
132
+ readSheetPivotTables(context, sheetRels, sheet);
133
+ const printerSettings = readSheetPrinterSettings(sheetRels);
119
134
  if (printerSettings !== undefined)
120
135
  sheet.pageSetup.printerSettings = printerSettings;
121
136
  }
122
- function readSheetComments(sheetRels, pkg) {
123
- const commentsPath = sheetRels.targetPath('comments');
124
- if (commentsPath === undefined)
125
- return undefined;
126
- const commentsXml = pkg.partText(commentsPath);
127
- if (commentsXml === undefined)
128
- return undefined;
129
- return parseComments(commentsXml);
130
- }
131
- function readWorkbookPersons(workbookRels, pkg, workbook) {
132
- const path = workbookRels.targetPath('person');
133
- const xml = path === undefined ? undefined : pkg.partText(path);
134
- if (xml !== undefined)
135
- workbook[INTERNAL].restorePersons(parsePersons(xml));
136
- }
137
- function readWorkbookTheme(workbookRels, pkg, contentTypeOf, workbook) {
138
- const entryPath = workbookRels.targetPath('theme');
139
- if (entryPath === undefined)
140
- return;
141
- const parts = capturePartClosure(entryPath, pkg.partText, pkg.partBytes, contentTypeOf);
142
- if (parts === undefined)
143
- return;
144
- const xml = pkg.partText(entryPath) ?? '';
145
- workbook[INTERNAL].restoreThemePart({ entryPath, parts }, { colors: parseThemeColorScheme(xml), fonts: parseThemeFontScheme(xml) });
146
- }
147
- function readSheetCommentThreads(sheetRels, pkg, workbook) {
148
- const path = sheetRels.targetPath('threadedComment');
149
- const xml = path === undefined ? undefined : pkg.partText(path);
150
- if (xml === undefined)
151
- return [];
152
- return buildCommentThreads(parseThreadedComments(xml), (id) => workbook.getPerson(id));
153
- }
154
- function readSheetPrinterSettings(sheetRels, pkg) {
155
- const path = sheetRels.targetPath('printerSettings');
156
- return path === undefined ? undefined : pkg.partBytes(path);
157
- }
158
- function internImage(workbook, pkg, imageIdByMediaPath, mediaPath) {
159
- const known = imageIdByMediaPath.get(mediaPath);
160
- if (known !== undefined)
161
- return known;
162
- const bytes = pkg.partBytes(mediaPath);
163
- if (bytes === undefined)
164
- return undefined;
165
- const id = workbook.addImage({ buffer: bytes, extension: extensionOf(mediaPath) });
166
- imageIdByMediaPath.set(mediaPath, id);
167
- return id;
168
- }
169
- function readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
170
- const { partText } = pkg;
171
- const drawingPath = sheetRels.targetPath('drawing');
172
- if (drawingPath === undefined)
173
- return;
174
- const drawingXml = partText(drawingPath);
175
- if (drawingXml === undefined)
176
- return;
177
- if (drawingHasUnmodeledContent(drawingXml))
178
- return;
179
- const drawingRels = readPartRelationships(drawingPath, partText);
180
- for (const anchor of parseDrawing(drawingXml)) {
181
- const embedded = drawingRels.byId(anchor.embed);
182
- if (embedded === undefined)
183
- continue;
184
- const mediaPath = drawingRels.pathOf(embedded.target);
185
- const id = internImage(workbook, pkg, imageIdByMediaPath, mediaPath);
186
- if (id === undefined)
187
- continue;
188
- const rot = anchor.rotation !== undefined ? { rotation: anchor.rotation } : {};
189
- if (anchor.to !== undefined) {
190
- const mode = anchor.editAs !== undefined ? { editAs: anchor.editAs } : {};
191
- sheet.addImageAnchor(id, { from: anchor.from, to: anchor.to, ...mode, ...rot });
192
- }
193
- else if (anchor.ext !== undefined) {
194
- sheet.addImageAnchor(id, { from: anchor.from, ext: anchor.ext, ...rot });
195
- }
196
- }
197
- }
198
- function readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
199
- const mediaPath = sheetRels.targetPath('image');
200
- if (mediaPath === undefined)
201
- return;
202
- const id = internImage(workbook, pkg, imageIdByMediaPath, mediaPath);
203
- if (id !== undefined)
204
- sheet.addBackgroundImage(id);
205
- }
206
- function readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet) {
207
- const { partText, partBytes } = pkg;
208
- const capture = (element, relType, target) => {
209
- const entryPath = sheetRels.pathOf(target);
210
- const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
211
- if (parts !== undefined)
212
- sheet[INTERNAL].addPreservedReference({ element, relType, entryPath, parts });
213
- };
214
- const referenceElements = sheet.images.length === 0 ? ['drawing', 'legacyDrawingHF'] : ['legacyDrawingHF'];
215
- for (const element of referenceElements) {
216
- const relId = worksheetReferenceRelId(sheetXml, element);
217
- const record = relId === undefined ? undefined : sheetRels.byId(relId);
218
- if (record !== undefined && !record.external)
219
- capture(element, record.type, record.target);
220
- }
221
- for (const record of sheetRels.records) {
222
- if (record.external)
223
- continue;
224
- if (isPreservedSheetRelType(record.type))
225
- capture(undefined, record.type, record.target);
226
- }
227
- }
228
- function isPreservedSheetRelType(type) {
229
- return type.endsWith('/pivotTable') || type.endsWith('/slicer');
230
- }
231
- function readWorkbookPreservedReferences(workbookXml, workbookRels, pkg, contentTypeOf, workbook) {
232
- const { partText, partBytes } = pkg;
233
- const cacheIdByRelId = parsePivotCacheRegistrations(workbookXml);
234
- const externalIndexByRelId = parseExternalReferenceRegistrations(workbookXml);
235
- for (const record of workbookRels.records) {
236
- if (record.external || !isPreservedWorkbookRelType(record.type))
237
- continue;
238
- const entryPath = workbookRels.pathOf(record.target);
239
- const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
240
- if (parts === undefined)
241
- continue;
242
- const cacheId = cacheIdByRelId.get(record.id);
243
- const externalReferenceIndex = externalIndexByRelId.get(record.id);
244
- workbook[INTERNAL].addPreservedReference({
245
- relType: record.type,
246
- entryPath,
247
- parts,
248
- ...(cacheId !== undefined ? { pivotCacheId: cacheId } : {}),
249
- ...(externalReferenceIndex !== undefined ? { externalReferenceIndex } : {}),
250
- });
251
- }
252
- }
253
- function readRootPreservedReferences(pkg, contentTypeOf, workbook) {
254
- const { partText, partBytes } = pkg;
255
- const relsXml = partText('_rels/.rels');
256
- if (relsXml === undefined)
257
- return;
258
- for (const record of parseRelationshipRecords(relsXml)) {
259
- if (record.external || isRegeneratedRootRelType(record.type))
260
- continue;
261
- const entryPath = resolveRelativePart('', record.target);
262
- const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
263
- if (parts === undefined)
264
- continue;
265
- workbook[INTERNAL].addPreservedRootReference({ relType: record.type, entryPath, parts });
266
- }
267
- }
268
- function isRegeneratedRootRelType(type) {
269
- return (type.endsWith('/officeDocument') ||
270
- type.endsWith('/core-properties') ||
271
- type.endsWith('/extended-properties'));
272
- }
273
- function isPreservedWorkbookRelType(type) {
274
- return (type.endsWith('/pivotCacheDefinition') ||
275
- type.endsWith('/slicerCache') ||
276
- type.endsWith('/vbaProject') ||
277
- type.endsWith('/externalLink'));
278
- }
279
- function parsePivotCacheRegistrations(workbookXml) {
280
- const byRelId = new Map();
281
- for (const { attrs } of openElements(workbookXml, 'pivotCache')) {
282
- if (attrs['r:id'] !== undefined && attrs.cacheId !== undefined) {
283
- byRelId.set(attrs['r:id'], attrs.cacheId);
284
- }
285
- }
286
- return byRelId;
287
- }
288
- function parseExternalReferenceRegistrations(workbookXml) {
289
- const byRelId = new Map();
290
- let index = 0;
291
- for (const { attrs } of openElements(workbookXml, 'externalReference')) {
292
- if (attrs['r:id'] !== undefined)
293
- byRelId.set(attrs['r:id'], index++);
294
- }
295
- return byRelId;
296
- }
297
- function worksheetReferenceRelId(sheetXml, element) {
298
- for (const { attrs } of openElements(sheetXml, element)) {
299
- if (attrs['r:id'] !== undefined)
300
- return attrs['r:id'];
301
- }
302
- return undefined;
303
- }
304
- function readSheetTables(sheetRels, pkg, sheet) {
305
- for (const tablePath of sheetRels.targetPaths('table')) {
306
- const tableXml = pkg.partText(tablePath);
307
- if (tableXml === undefined)
308
- continue;
309
- const options = parseTable(tableXml);
310
- if (options !== undefined)
311
- sheet.addTable(options);
312
- }
313
- dropMergesInsideTables(sheet);
314
- }
315
- function readSheetPivotTables(sheetRels, pkg, sheet) {
316
- const { partText } = pkg;
317
- for (const tablePath of sheetRels.targetPaths('pivotTable')) {
318
- const tableXml = partText(tablePath);
319
- if (tableXml === undefined)
320
- continue;
321
- const cachePath = readPartRelationships(tablePath, partText).targetPath('pivotCacheDefinition');
322
- const cacheXml = cachePath === undefined ? '' : (partText(cachePath) ?? '');
323
- sheet[INTERNAL].addLoadedPivotTable(parsePivotTable(tableXml, cacheXml));
324
- }
325
- }
326
- function dropMergesInsideTables(sheet) {
327
- const regions = sheet.tables.map((table) => table.region);
328
- if (regions.length === 0)
329
- return;
330
- for (const range of [...sheet.merges]) {
331
- const { top, left, bottom, right } = decodeRange(range);
332
- if (top === undefined || left === undefined || bottom === undefined || right === undefined)
333
- continue;
334
- const overlaps = regions.some((region) => left <= region.right &&
335
- right >= region.left &&
336
- top <= region.bottom &&
337
- bottom >= region.top);
338
- if (overlaps)
339
- sheet.unmergeCells(range);
340
- }
341
- }
342
- export function parseWorkbookSheets(xml) {
343
- const sheets = [];
344
- for (const { attrs } of openElements(xml, 'sheet')) {
345
- const entry = {
346
- name: attrs.name ?? '',
347
- relId: attrs['r:id'] ?? '',
348
- };
349
- const state = enumToken(attrs.state, isVisibility);
350
- if (state !== undefined && state !== 'visible')
351
- entry.state = state;
352
- sheets.push(entry);
353
- }
354
- return sheets;
355
- }
356
- function parseWorkbookProtection(xml) {
357
- let result;
358
- parseXml(xml, {
359
- onOpen(name, attrs) {
360
- if (localName(name) !== 'workbookProtection')
361
- return;
362
- const protection = {};
363
- if (boolStrict(attrs.lockStructure))
364
- protection.lockStructure = true;
365
- if (boolStrict(attrs.lockWindows))
366
- protection.lockWindows = true;
367
- if (boolStrict(attrs.lockRevision))
368
- protection.lockRevision = true;
369
- const credentials = {};
370
- for (const key of WORKBOOK_PROTECTION_CREDENTIAL_ATTRS) {
371
- const value = attrs[key];
372
- if (value !== undefined)
373
- credentials[key] = value;
374
- }
375
- if (Object.keys(credentials).length > 0)
376
- protection.credentials = credentials;
377
- result = protection;
378
- },
379
- });
380
- return result;
381
- }
382
- export function applyWorkbookView(view, xml) {
383
- for (const { attrs } of openElements(xml, 'workbookView')) {
384
- const x = numInteger(attrs.xWindow);
385
- if (x !== undefined)
386
- view.x = x;
387
- const y = numInteger(attrs.yWindow);
388
- if (y !== undefined)
389
- view.y = y;
390
- const width = numInteger(attrs.windowWidth, 0);
391
- if (width !== undefined)
392
- view.width = width;
393
- const height = numInteger(attrs.windowHeight, 0);
394
- if (height !== undefined)
395
- view.height = height;
396
- const activeTab = numInteger(attrs.activeTab, 0);
397
- if (activeTab !== undefined)
398
- view.activeTab = activeTab;
399
- const visibility = enumToken(attrs.visibility, isVisibility);
400
- if (visibility !== undefined && visibility !== 'visible')
401
- view.visibility = visibility;
402
- if (boolStrict(attrs.minimized))
403
- view.minimized = true;
404
- return;
405
- }
406
- }
407
- function parseWorkbookDefinedNames(xml, sheetOrder) {
408
- const names = [];
409
- let capture = false;
410
- let refersTo = '';
411
- let pending;
412
- parseXml(xml, {
413
- onOpen(name, attrs) {
414
- if (localName(name) !== 'definedName' || attrs.name === undefined)
415
- return;
416
- if (attrs.name === '_xlnm._FilterDatabase')
417
- return;
418
- capture = true;
419
- refersTo = '';
420
- const scopeIndex = numInteger(attrs.localSheetId, 0) ?? -1;
421
- const scope = sheetOrder[scopeIndex];
422
- pending = { name: attrs.name };
423
- if (scope !== undefined)
424
- pending.scope = scope;
425
- if (attrs.comment !== undefined)
426
- pending.comment = attrs.comment;
427
- if (boolStrict(attrs.hidden))
428
- pending.hidden = true;
429
- },
430
- onText(chunk) {
431
- if (capture)
432
- refersTo += chunk;
433
- },
434
- onClose(name) {
435
- if (localName(name) !== 'definedName' || pending === undefined)
436
- return;
437
- names.push({ ...pending, refersTo: unmangleFunctions(refersTo) });
438
- capture = false;
439
- pending = undefined;
440
- },
441
- });
442
- return names;
443
- }
444
- const CORE_PROPERTY_LOCAL_NAMES = new Set([
445
- 'title',
446
- 'creator',
447
- 'lastModifiedBy',
448
- 'created',
449
- 'modified',
450
- ]);
451
- function applyCoreProperties(workbook, xml) {
452
- for (const { local, text } of capturedText(xml, CORE_PROPERTY_LOCAL_NAMES)) {
453
- if (local === 'title')
454
- workbook.properties.title = text;
455
- else if (local === 'creator')
456
- workbook.properties.creator = text;
457
- else if (local === 'lastModifiedBy')
458
- workbook.properties.lastModifiedBy = text;
459
- else {
460
- const date = new Date(text);
461
- if (!Number.isNaN(date.getTime())) {
462
- if (local === 'created')
463
- workbook.properties.created = date;
464
- else
465
- workbook.properties.modified = date;
466
- }
467
- }
468
- }
469
- }
470
- function applyAppProperties(workbook, xml) {
471
- for (const { text } of capturedText(xml, 'Company'))
472
- workbook.properties.company = text;
473
- }
@@ -28,6 +28,9 @@ export declare const REL: {
28
28
  readonly pivotTable: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable";
29
29
  readonly pivotCacheDefinition: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition";
30
30
  readonly pivotCacheRecords: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords";
31
+ readonly sheetMetadata: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata";
32
+ readonly rdRichValue: "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValue";
33
+ readonly rdRichValueStructure: "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValueStructure";
31
34
  readonly threadedComment: "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment";
32
35
  readonly person: "http://schemas.microsoft.com/office/2017/10/relationships/person";
33
36
  };
@@ -13,6 +13,7 @@ export const NS = {
13
13
  xsi: 'http://www.w3.org/2001/XMLSchema-instance',
14
14
  };
15
15
  const MS_OFFICE_2017_RELS_NS = 'http://schemas.microsoft.com/office/2017/10/relationships';
16
+ const RICH_DATA_RELS_NS = 'http://schemas.microsoft.com/office/2017/06/relationships';
16
17
  export const REL = {
17
18
  worksheet: `${NS.docRels}/worksheet`,
18
19
  styles: `${NS.docRels}/styles`,
@@ -31,6 +32,9 @@ export const REL = {
31
32
  pivotTable: `${NS.docRels}/pivotTable`,
32
33
  pivotCacheDefinition: `${NS.docRels}/pivotCacheDefinition`,
33
34
  pivotCacheRecords: `${NS.docRels}/pivotCacheRecords`,
35
+ sheetMetadata: `${NS.docRels}/sheetMetadata`,
36
+ rdRichValue: `${RICH_DATA_RELS_NS}/rdRichValue`,
37
+ rdRichValueStructure: `${RICH_DATA_RELS_NS}/rdRichValueStructure`,
34
38
  threadedComment: `${MS_OFFICE_2017_RELS_NS}/threadedComment`,
35
39
  person: `${MS_OFFICE_2017_RELS_NS}/person`,
36
40
  };
@@ -1,5 +1,5 @@
1
1
  import { textElement } from '../../xml/xml.js';
2
- import { fontXml } from './styles.js';
2
+ import { fontXml } from './font-xml.js';
3
3
  export function richTextRunsXml(runs) {
4
4
  return runs
5
5
  .filter((run) => run.text !== '')
@@ -0,0 +1,20 @@
1
+ import { type XmlAttributes } from '../../xml/xml-scan.ts';
2
+ /** One `<row>`, as the reader that opened it needs to see it. */
3
+ export interface RowPosition {
4
+ /** The row's 1-based number, inferred from position when the element declares no `r`. */
5
+ readonly number: number;
6
+ /**
7
+ * Whether that number names a row the grid has. A row past the ceiling is dropped whole by both
8
+ * readers rather than clamped: an `r` names one row, so there is nothing to fold it onto, and
9
+ * clamping would silently move its formatting to the last row of the sheet. Its cells go with it,
10
+ * even one whose own `r` is in the grid, because `CellAccumulator` places no cell outside an
11
+ * in-grid row.
12
+ */
13
+ readonly inGrid: boolean;
14
+ }
15
+ /** Tracks where the reader is in `<sheetData>`, so a `<row>` with no `r` still has a number. */
16
+ export declare class RowPositionTracker {
17
+ #private;
18
+ /** Open the next `<row>`. A declared `r` wins and re-anchors the count, exactly as position does. */
19
+ open(attrs: XmlAttributes): RowPosition;
20
+ }
@@ -0,0 +1,11 @@
1
+ import { MAX_ROW } from '../../core/address.js';
2
+ import { numInteger } from '../../xml/xml-attrs.js';
3
+ import {} from '../../xml/xml-scan.js';
4
+ export class RowPositionTracker {
5
+ #last = 0;
6
+ open(attrs) {
7
+ const number = numInteger(attrs.r, 1) ?? this.#last + 1;
8
+ this.#last = number;
9
+ return { number, inGrid: number <= MAX_ROW };
10
+ }
11
+ }