@shbernal/ts-xlsx 3.0.0 → 3.1.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 (213) hide show
  1. package/README.md +4 -1
  2. package/dist/bytes.d.ts +7 -0
  3. package/dist/bytes.js +22 -0
  4. package/dist/core/address.d.ts +60 -2
  5. package/dist/core/address.js +40 -24
  6. package/dist/core/autofilter.d.ts +4 -3
  7. package/dist/core/autofilter.js +31 -30
  8. package/dist/core/axis-handle.d.ts +2 -0
  9. package/dist/core/axis-handle.js +5 -2
  10. package/dist/core/cell.d.ts +4 -3
  11. package/dist/core/cell.js +4 -6
  12. package/dist/core/clone.d.ts +29 -0
  13. package/dist/core/clone.js +24 -0
  14. package/dist/core/color-resolution.js +2 -4
  15. package/dist/core/column.d.ts +1 -0
  16. package/dist/core/column.js +3 -0
  17. package/dist/core/comment-thread.js +2 -1
  18. package/dist/core/conditional-formatting-overlay.d.ts +2 -1
  19. package/dist/core/conditional-formatting-overlay.js +2 -2
  20. package/dist/core/conditional-formatting.d.ts +9 -1
  21. package/dist/core/conditional-formatting.js +34 -18
  22. package/dist/core/containers.d.ts +12 -0
  23. package/dist/core/containers.js +5 -0
  24. package/dist/core/data-validation-overlay.d.ts +2 -1
  25. package/dist/core/data-validation-overlay.js +4 -4
  26. package/dist/core/data-validation.d.ts +6 -0
  27. package/dist/core/data-validation.js +15 -4
  28. package/dist/core/date-format.d.ts +20 -0
  29. package/dist/core/date-format.js +160 -0
  30. package/dist/core/date.d.ts +43 -8
  31. package/dist/core/date.js +18 -2
  32. package/dist/core/formula.d.ts +26 -0
  33. package/dist/core/formula.js +20 -4
  34. package/dist/core/grid-edits.d.ts +2 -3
  35. package/dist/core/grid-edits.js +69 -70
  36. package/dist/core/grid-shift.d.ts +58 -9
  37. package/dist/core/grid-shift.js +26 -4
  38. package/dist/core/image.d.ts +13 -9
  39. package/dist/core/image.js +7 -5
  40. package/dist/core/internal.d.ts +8 -2
  41. package/dist/core/limits.d.ts +23 -0
  42. package/dist/core/limits.js +4 -0
  43. package/dist/core/merge.d.ts +5 -4
  44. package/dist/core/merge.js +18 -19
  45. package/dist/core/pivot-table.js +63 -45
  46. package/dist/core/protection.js +2 -11
  47. package/dist/core/range.js +34 -30
  48. package/dist/core/row-input.js +2 -2
  49. package/dist/core/row.d.ts +1 -0
  50. package/dist/core/row.js +3 -0
  51. package/dist/core/style.d.ts +85 -70
  52. package/dist/core/style.js +92 -28
  53. package/dist/core/table-style.d.ts +1 -1
  54. package/dist/core/table-style.js +4 -4
  55. package/dist/core/table.d.ts +27 -9
  56. package/dist/core/table.js +51 -34
  57. package/dist/core/theme.js +6 -5
  58. package/dist/core/value.d.ts +9 -0
  59. package/dist/core/value.js +36 -34
  60. package/dist/core/workbook-media.d.ts +34 -0
  61. package/dist/core/workbook-media.js +44 -0
  62. package/dist/core/workbook-styles.d.ts +67 -1
  63. package/dist/core/workbook-vba.js +3 -2
  64. package/dist/core/workbook.d.ts +23 -2
  65. package/dist/core/workbook.js +24 -40
  66. package/dist/core/worksheet-comments.d.ts +2 -1
  67. package/dist/core/worksheet-comments.js +20 -13
  68. package/dist/core/worksheet-merges.d.ts +44 -0
  69. package/dist/core/worksheet-merges.js +59 -0
  70. package/dist/core/worksheet-model.d.ts +9 -1
  71. package/dist/core/worksheet-model.js +24 -9
  72. package/dist/core/worksheet.d.ts +55 -6
  73. package/dist/core/worksheet.js +36 -44
  74. package/dist/customui/ribbon.js +2 -1
  75. package/dist/entries/core.d.ts +18 -13
  76. package/dist/entries/core.js +12 -6
  77. package/dist/entries/xlsx.d.ts +1 -1
  78. package/dist/errors.d.ts +64 -0
  79. package/dist/errors.js +22 -0
  80. package/dist/hex.d.ts +8 -0
  81. package/dist/hex.js +3 -0
  82. package/dist/io/csv/delimiter.d.ts +9 -0
  83. package/dist/io/csv/delimiter.js +6 -0
  84. package/dist/io/csv/read.js +11 -4
  85. package/dist/io/csv/write.d.ts +9 -2
  86. package/dist/io/csv/write.js +9 -38
  87. package/dist/io/opc/inflate.js +14 -0
  88. package/dist/io/opc/namespaces.d.ts +16 -0
  89. package/dist/io/opc/namespaces.js +4 -0
  90. package/dist/io/opc/part-paths.d.ts +9 -0
  91. package/dist/io/opc/part-paths.js +1 -1
  92. package/dist/io/opc/read-opc.d.ts +54 -14
  93. package/dist/io/opc/read-opc.js +42 -20
  94. package/dist/io/opc/read-options.d.ts +5 -1
  95. package/dist/io/opc/sniff-format.d.ts +3 -3
  96. package/dist/io/opc/sniff-format.js +2 -2
  97. package/dist/io/style/xf-style.d.ts +23 -1
  98. package/dist/io/style/xf-style.js +8 -0
  99. package/dist/io/xlsb/formula.d.ts +2 -2
  100. package/dist/io/xlsb/formula.js +49 -34
  101. package/dist/io/xlsb/primitives.js +8 -14
  102. package/dist/io/xlsb/ptg-functions.d.ts +19 -10
  103. package/dist/io/xlsb/ptg-functions.js +385 -596
  104. package/dist/io/xlsb/read-styles.js +45 -81
  105. package/dist/io/xlsb/read-worksheet.d.ts +20 -1
  106. package/dist/io/xlsb/read-worksheet.js +73 -89
  107. package/dist/io/xlsb/read.d.ts +6 -3
  108. package/dist/io/xlsb/read.js +44 -23
  109. package/dist/io/xlsb/record-stream.d.ts +30 -0
  110. package/dist/io/xlsb/record-stream.js +20 -0
  111. package/dist/io/xlsb/record-types.d.ts +1 -5
  112. package/dist/io/xlsb/record-types.js +1 -5
  113. package/dist/io/xlsx/cell-accumulator.d.ts +8 -1
  114. package/dist/io/xlsx/cell-accumulator.js +32 -9
  115. package/dist/io/xlsx/cell-style-resolution.d.ts +25 -0
  116. package/dist/io/xlsx/cell-style-resolution.js +29 -0
  117. package/dist/io/xlsx/cell-value.d.ts +5 -3
  118. package/dist/io/xlsx/cell-value.js +13 -15
  119. package/dist/io/xlsx/color-xml.js +3 -2
  120. package/dist/io/xlsx/column-budget.d.ts +26 -0
  121. package/dist/io/xlsx/column-budget.js +22 -0
  122. package/dist/io/xlsx/comments.d.ts +6 -2
  123. package/dist/io/xlsx/comments.js +36 -32
  124. package/dist/io/xlsx/conditional-formatting.d.ts +6 -3
  125. package/dist/io/xlsx/conditional-formatting.js +30 -26
  126. package/dist/io/xlsx/data-validation.js +29 -27
  127. package/dist/io/xlsx/edit-vba.d.ts +7 -2
  128. package/dist/io/xlsx/edit-vba.js +14 -21
  129. package/dist/io/xlsx/font-xml.d.ts +7 -0
  130. package/dist/io/xlsx/font-xml.js +104 -0
  131. package/dist/io/xlsx/hyperlinks.d.ts +37 -5
  132. package/dist/io/xlsx/hyperlinks.js +22 -13
  133. package/dist/io/xlsx/images.js +11 -13
  134. package/dist/io/xlsx/namespaces.d.ts +16 -0
  135. package/dist/io/xlsx/namespaces.js +7 -0
  136. package/dist/io/xlsx/package-plan.d.ts +14 -2
  137. package/dist/io/xlsx/package-plan.js +39 -11
  138. package/dist/io/xlsx/pivot.js +8 -7
  139. package/dist/io/xlsx/read-parts.d.ts +59 -0
  140. package/dist/io/xlsx/read-parts.js +252 -0
  141. package/dist/io/xlsx/read-pivot.js +2 -1
  142. package/dist/io/xlsx/read-repair.d.ts +26 -0
  143. package/dist/io/xlsx/read-repair.js +39 -0
  144. package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +6 -3
  145. package/dist/io/xlsx/read-rows.d.ts +18 -5
  146. package/dist/io/xlsx/read-rows.js +45 -31
  147. package/dist/io/xlsx/read-shared-strings.js +3 -2
  148. package/dist/io/xlsx/read-styles.d.ts +1 -6
  149. package/dist/io/xlsx/read-styles.js +6 -71
  150. package/dist/io/xlsx/read-workbook-xml.d.ts +36 -0
  151. package/dist/io/xlsx/read-workbook-xml.js +170 -0
  152. package/dist/io/xlsx/read-worksheet.d.ts +2 -1
  153. package/dist/io/xlsx/read-worksheet.js +35 -164
  154. package/dist/io/xlsx/read.d.ts +5 -12
  155. package/dist/io/xlsx/read.js +73 -406
  156. package/dist/io/xlsx/rich-text.js +1 -1
  157. package/dist/io/xlsx/row-position.d.ts +18 -0
  158. package/dist/io/xlsx/row-position.js +11 -0
  159. package/dist/io/xlsx/row-xml.d.ts +128 -0
  160. package/dist/io/xlsx/row-xml.js +203 -0
  161. package/dist/io/xlsx/shared-formulas.js +2 -2
  162. package/dist/io/xlsx/sheet-properties.d.ts +10 -1
  163. package/dist/io/xlsx/sheet-properties.js +145 -9
  164. package/dist/io/xlsx/style-elements.d.ts +43 -0
  165. package/dist/io/xlsx/style-elements.js +156 -0
  166. package/dist/io/xlsx/styles.d.ts +12 -3
  167. package/dist/io/xlsx/styles.js +5 -207
  168. package/dist/io/xlsx/tables.js +10 -14
  169. package/dist/io/xlsx/theme-xml.d.ts +26 -4
  170. package/dist/io/xlsx/theme-xml.js +107 -69
  171. package/dist/io/xlsx/threaded-comments.d.ts +8 -10
  172. package/dist/io/xlsx/threaded-comments.js +2 -1
  173. package/dist/io/xlsx/workbook-xml.d.ts +54 -4
  174. package/dist/io/xlsx/workbook-xml.js +60 -34
  175. package/dist/io/xlsx/worksheet-xml.d.ts +23 -70
  176. package/dist/io/xlsx/worksheet-xml.js +48 -229
  177. package/dist/io/xlsx/write-stream.d.ts +65 -16
  178. package/dist/io/xlsx/write-stream.js +50 -20
  179. package/dist/io/xlsx/write.d.ts +1 -2
  180. package/dist/io/xlsx/write.js +114 -74
  181. package/dist/rel-type.d.ts +16 -0
  182. package/dist/rel-type.js +6 -0
  183. package/dist/token-set.d.ts +13 -0
  184. package/dist/token-set.js +4 -1
  185. package/dist/vba/bytes.d.ts +14 -5
  186. package/dist/vba/bytes.js +16 -6
  187. package/dist/vba/cfb-format.d.ts +8 -0
  188. package/dist/vba/cfb-format.js +1 -0
  189. package/dist/vba/cfb-writer.d.ts +9 -0
  190. package/dist/vba/cfb-writer.js +12 -9
  191. package/dist/vba/cfb.d.ts +13 -1
  192. package/dist/vba/cfb.js +73 -51
  193. package/dist/vba/codepage.js +2 -1
  194. package/dist/vba/errors.d.ts +7 -0
  195. package/dist/vba/ms-ovba.js +51 -16
  196. package/dist/vba/project-editor.js +35 -40
  197. package/dist/vba/project.d.ts +11 -1
  198. package/dist/vba/project.js +27 -8
  199. package/dist/vba/vba-encoding.js +4 -5
  200. package/dist/xml/xml-attrs.d.ts +37 -0
  201. package/dist/xml/xml-attrs.js +30 -0
  202. package/dist/xml/xml-chars.d.ts +40 -0
  203. package/dist/xml/xml-chars.js +12 -0
  204. package/dist/xml/xml-namespaces.d.ts +31 -0
  205. package/dist/xml/xml-namespaces.js +50 -0
  206. package/dist/xml/xml-read.d.ts +72 -10
  207. package/dist/xml/xml-read.js +94 -18
  208. package/dist/xml/xml-scan.d.ts +15 -37
  209. package/dist/xml/xml-scan.js +12 -40
  210. package/dist/xml/xml.d.ts +28 -27
  211. package/dist/xml/xml.js +24 -24
  212. package/package.json +12 -7
  213. /package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +0 -0
@@ -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';
5
+ import { contentTypeResolver, openSpreadsheetPackage, readPartRelationships, } from '../opc/read-opc.js';
6
+ import { readXlsbPackage } from '../xlsb/read.js';
7
+ import { applyNotes } from './comments.js';
14
8
  import { conditionalFormattingPass } from './conditional-formatting.js';
15
9
  import { applyDataValidations, dataValidationPass, extendedDataValidationPass, } from './data-validation.js';
16
10
  import { applyHyperlinks, sheetHyperlinkPass } from './hyperlinks.js';
17
- import { drawingHasUnmodeledContent, parseDrawing } from './images.js';
18
- import { parsePivotTable } from './read-pivot.js';
11
+ import { SHARED_STRINGS_PART, STYLES_PART } from './part-names.js';
12
+ import { readRootPreservedReferences, readSheetBackground, readSheetComments, readSheetCommentThreads, readSheetImages, readSheetPivotTables, readSheetPreservedReferences, readSheetPrinterSettings, readSheetTables, readWorkbookPersons, externalReferenceRegistrationsPass, pivotCacheRegistrationsPass, readWorkbookPreservedReferences, readWorkbookTheme, worksheetReferencePass, } from './read-parts.js';
13
+ import { admitting, repairSheetName } from './read-repair.js';
19
14
  import { parseSharedStrings } from './read-shared-strings.js';
20
15
  import { parseStyleTable } from './read-styles.js';
16
+ import { applyAppProperties, applyCoreProperties, definedNamesPass, workbookPropertiesPass, workbookProtectionPass, workbookSheetsPass, workbookViewPass, } from './read-workbook-xml.js';
21
17
  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
18
  export { parseStyleTable } from './read-styles.js';
19
+ export { workbookPropertiesPass, workbookSheetsPass, workbookViewPass, } from './read-workbook-xml.js';
26
20
  export function readXlsx(data, options = {}) {
27
- const { files, pkg, workbookXml } = openSpreadsheetPackage(data, options.maxUncompressedBytes);
28
- const { partText } = pkg;
21
+ const { files, pkg, documentPath, workbookXml } = openSpreadsheetPackage(data, options.maxUncompressedBytes);
22
+ const { partText, partBytes } = pkg;
29
23
  if (workbookXml === undefined) {
30
- if (files[XLSB_WORKBOOK_PART] !== undefined)
31
- return readXlsbPackage(files);
24
+ if (partBytes(documentPath) !== undefined)
25
+ return readXlsbPackage(files, documentPath);
32
26
  throw new UnsupportedFormatError('unknown');
33
27
  }
34
28
  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') ?? '';
29
+ const workbookRels = readPartRelationships(documentPath, partText);
30
+ const sharedStrings = parseSharedStrings(workbookRels.relatedTextOrPath('sharedStrings', SHARED_STRINGS_PART));
31
+ const stylesXml = workbookRels.relatedTextOrPath('styles', STYLES_PART);
38
32
  const { cellXfs: xfStyles, namedStyles, defaultFont, preserved } = parseStyleTable(stylesXml);
39
33
  const workbook = new Workbook();
34
+ const context = {
35
+ pkg,
36
+ workbook,
37
+ contentTypeOf,
38
+ sharedStrings,
39
+ xfStyles,
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,88 @@ 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);
65
72
  const sheetOrder = [];
66
- for (const { name, relId, state } of parseWorkbookSheets(workbookXml)) {
73
+ const takenSheetNames = new Set();
74
+ for (const { name, relId, state } of sheets.result()) {
67
75
  const target = workbookRels.byId(relId)?.target;
68
- const sheet = workbook.addWorksheet(name, state === undefined ? undefined : { state });
69
- sheetOrder.push(name);
76
+ const sheet = workbook.addWorksheet(repairSheetName(name, takenSheetNames), state === undefined ? undefined : { state });
77
+ takenSheetNames.add(sheet.name.toLowerCase());
78
+ sheetOrder.push(sheet.name);
70
79
  readSheet(sheet, target === undefined ? undefined : workbookRels.pathOf(target), context);
71
80
  }
72
- readWorkbookPreservedReferences(workbookXml, workbookRels, pkg, contentTypeOf, workbook);
73
- readRootPreservedReferences(pkg, contentTypeOf, workbook);
74
- for (const name of parseWorkbookDefinedNames(workbookXml, sheetOrder)) {
75
- workbook.defineName(name);
81
+ readWorkbookPreservedReferences(context, workbookRels, {
82
+ cacheIdByRelId: pivotCaches.result(),
83
+ externalIndexByRelId: externalReferences.result(),
84
+ });
85
+ readRootPreservedReferences(context);
86
+ for (const name of definedNames.result(sheetOrder)) {
87
+ admitting(() => {
88
+ workbook.defineName(name);
89
+ });
76
90
  }
77
91
  return workbook;
78
92
  }
79
93
  function readSheet(sheet, path, context) {
80
- const { pkg, workbook, contentTypeOf, sharedStrings, xfStyles, imageIdByMediaPath } = context;
94
+ const { pkg, workbook, sharedStrings, xfStyles } = context;
81
95
  const { partText } = pkg;
82
96
  const sheetXml = path === undefined ? undefined : partText(path);
83
97
  const hyperlinks = sheetHyperlinkPass();
84
98
  const validations = dataValidationPass();
85
99
  const extendedValidations = extendedDataValidationPass();
86
100
  const formattings = conditionalFormattingPass();
101
+ const references = worksheetReferencePass();
87
102
  if (sheetXml !== undefined) {
88
103
  parseXmlPasses(sheetXml, [
89
- worksheetPass(sheet, sharedStrings, xfStyles),
104
+ worksheetPass(sheet, sharedStrings, xfStyles, workbook.dateEpoch),
90
105
  hyperlinks,
91
106
  validations,
92
107
  extendedValidations,
93
108
  formattings,
109
+ references,
94
110
  ]);
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
+ for (const cf of formattings.result()) {
119
+ admitting(() => {
120
+ sheet.addConditionalFormatting(cf);
121
+ });
122
+ }
104
123
  }
105
- const threads = readSheetCommentThreads(sheetRels, pkg, workbook);
124
+ const threads = readSheetCommentThreads(context, sheetRels);
106
125
  if (threads.length > 0)
107
126
  sheet[INTERNAL].restoreCommentThreads(threads);
108
- const comments = readSheetComments(sheetRels, pkg);
127
+ const comments = readSheetComments(sheetRels);
109
128
  if (comments !== undefined)
110
129
  applyNotes(sheet, comments);
111
- readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
112
- readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
130
+ readSheetImages(context, sheetRels, sheet);
131
+ readSheetBackground(context, sheetRels, sheet);
113
132
  if (sheetXml !== undefined) {
114
- readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet);
133
+ readSheetPreservedReferences(context, sheetRels, references.result(), sheet);
115
134
  }
116
- readSheetTables(sheetRels, pkg, sheet);
117
- readSheetPivotTables(sheetRels, pkg, sheet);
118
- const printerSettings = readSheetPrinterSettings(sheetRels, pkg);
135
+ readSheetTables(context, sheetRels, sheet);
136
+ readSheetPivotTables(context, sheetRels, sheet);
137
+ const printerSettings = readSheetPrinterSettings(sheetRels);
119
138
  if (printerSettings !== undefined)
120
139
  sheet.pageSetup.printerSettings = printerSettings;
121
140
  }
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
- }
@@ -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,18 @@
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.
10
+ */
11
+ readonly inGrid: boolean;
12
+ }
13
+ /** Tracks where the reader is in `<sheetData>`, so a `<row>` with no `r` still has a number. */
14
+ export declare class RowPositionTracker {
15
+ #private;
16
+ /** Open the next `<row>`. A declared `r` wins and re-anchors the count, exactly as position does. */
17
+ open(attrs: XmlAttributes): RowPosition;
18
+ }
@@ -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
+ }