@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,13 +1,14 @@
1
- import { mangleFormula, quoteSheetName } from '../../core/formula.js';
1
+ import { formulaNamesInScope, mangleFormula, quoteSheetName } from '../../core/formula.js';
2
2
  import { WORKBOOK_PROTECTION_CREDENTIAL_ATTRS } from '../../core/workbook-protection.js';
3
3
  import { isVisibility } from '../../core/worksheet.js';
4
- import { checkedToken, escapeAttr, escapeText, numAttr, textAttr, XML_DECLARATION, } from '../../xml/xml.js';
4
+ import { AuthoringError, InternalError, quoted } from '../../errors.js';
5
+ import { isRelType } from '../../rel-type.js';
6
+ import { assertWritableDate, checkedToken, escapeAttr, escapeText, numAttr, textAttr, XML_DECLARATION, } from '../../xml/xml.js';
5
7
  import { extensionOf, THEME_PART_PATH } from '../opc/part-paths.js';
6
- import { relationship, relationshipsPart } from '../opc/rels.js';
7
8
  import { imageContentType } from './images.js';
8
9
  import { SLICER_CACHES_EXT_URI } from './namespaces.js';
9
- import { APP_PROPS_PART, commentsPart, CORE_PROPS_PART, drawingPart, PERSONS_PART, pivotCacheDefinitionPart, pivotCacheRecordsPart, pivotTablePart, SHARED_STRINGS_PART, STYLES_PART, tablePart, targetFromWorkbook, threadedCommentsPart, WORKBOOK_PART, worksheetPart, } from './part-names.js';
10
- import { NS, REL } from './relationships.js';
10
+ import { APP_PROPS_PART, commentsPart, CORE_PROPS_PART, drawingPart, METADATA_PART, PERSONS_PART, pivotCacheDefinitionPart, pivotCacheRecordsPart, pivotTablePart, RICH_VALUE_STRUCTURES_PART, RICH_VALUES_PART, SHARED_STRINGS_PART, STYLES_PART, tablePart, threadedCommentsPart, WORKBOOK_PART, worksheetPart, } from './part-names.js';
11
+ import { NS } from './relationships.js';
11
12
  import { x14Ext } from './x14-ext.js';
12
13
  const CT = {
13
14
  workbook: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml',
@@ -28,16 +29,20 @@ const CT = {
28
29
  pivotCacheRecords: 'application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml',
29
30
  threadedComments: 'application/vnd.ms-excel.threadedcomments+xml',
30
31
  person: 'application/vnd.ms-excel.person+xml',
32
+ sheetMetadata: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml',
33
+ richValues: 'application/vnd.ms-excel.rdrichvalue+xml',
34
+ richValueStructures: 'application/vnd.ms-excel.rdrichvaluestructure+xml',
31
35
  };
32
- export function contentTypesXml(sheetCount, tables, commentNumbers, drawingNumbers, printerSettingsNumbers, mediaExtensions, hasSharedStrings, preservedParts, pivots, preservedWorkbookRefs, threadedCommentNumbers, hasPersons) {
33
- const extensionDefaults = buildExtensionDefaults(commentNumbers, printerSettingsNumbers, mediaExtensions, preservedParts);
36
+ export function contentTypesXml(inputs) {
37
+ const extensionDefaults = buildExtensionDefaults(inputs);
34
38
  return (XML_DECLARATION +
35
39
  `<Types xmlns="${NS.contentTypes}">` +
36
40
  contentTypeDefaults(extensionDefaults) +
37
- contentTypeOverrides(sheetCount, tables, drawingNumbers, commentNumbers, hasSharedStrings, preservedParts, pivots, preservedWorkbookRefs, extensionDefaults, threadedCommentNumbers, hasPersons) +
41
+ contentTypeOverrides(inputs, extensionDefaults) +
38
42
  '</Types>');
39
43
  }
40
- function buildExtensionDefaults(commentNumbers, printerSettingsNumbers, mediaExtensions, preservedParts) {
44
+ function buildExtensionDefaults(inputs) {
45
+ const { commentNumbers, printerSettingsNumbers, mediaExtensions, preservedParts } = inputs;
41
46
  const defaults = new Map();
42
47
  const add = (extension, contentType) => {
43
48
  const key = extension.toLowerCase();
@@ -54,25 +59,25 @@ function buildExtensionDefaults(commentNumbers, printerSettingsNumbers, mediaExt
54
59
  add(ext, imageContentType(ext));
55
60
  for (const part of preservedParts) {
56
61
  const ext = extensionOf(part.path);
57
- if (ext.toLowerCase() === 'xml')
62
+ if (ext === 'xml')
58
63
  continue;
59
64
  add(ext, part.contentType);
60
65
  }
61
66
  return defaults;
62
67
  }
63
68
  function isMacroEnabled(preservedWorkbookRefs) {
64
- return preservedWorkbookRefs.some((ref) => ref.relType.endsWith('/vbaProject'));
69
+ return preservedWorkbookRefs.some((ref) => isRelType(ref.relType, 'vbaProject'));
65
70
  }
66
71
  function contentTypeDefaults(extensionDefaults) {
67
72
  return [...extensionDefaults.values()]
68
73
  .map(({ extension, contentType }) => defaultType(extension, contentType))
69
74
  .join('');
70
75
  }
71
- function contentTypeOverrides(sheetCount, tables, drawingNumbers, commentNumbers, hasSharedStrings, preservedParts, pivots, preservedWorkbookRefs, extensionDefaults, threadedCommentNumbers, hasPersons) {
76
+ function contentTypeOverrides(inputs, extensionDefaults) {
77
+ const { sheetCount, tables, drawingNumbers, commentNumbers, threadedCommentNumbers, pivots, hasSharedStrings, hasPersons, hasCellMetadata, hasRichValues, preservedParts, preservedWorkbookRefs, } = inputs;
72
78
  const preservedOverrides = preservedParts
73
79
  .filter((part) => part.path !== THEME_PART_PATH)
74
- .filter((part) => extensionDefaults.get(extensionOf(part.path).toLowerCase())?.contentType !==
75
- part.contentType)
80
+ .filter((part) => extensionDefaults.get(extensionOf(part.path))?.contentType !== part.contentType)
76
81
  .map((part) => override(part.path, part.contentType));
77
82
  return [
78
83
  override(WORKBOOK_PART, isMacroEnabled(preservedWorkbookRefs) ? CT.macroEnabledWorkbook : CT.workbook),
@@ -88,37 +93,43 @@ function contentTypeOverrides(sheetCount, tables, drawingNumbers, commentNumbers
88
93
  override(STYLES_PART, CT.styles),
89
94
  ...(hasSharedStrings ? [override(SHARED_STRINGS_PART, CT.sharedStrings)] : []),
90
95
  ...(hasPersons ? [override(PERSONS_PART, CT.person)] : []),
96
+ ...(hasCellMetadata ? [override(METADATA_PART, CT.sheetMetadata)] : []),
97
+ ...(hasRichValues
98
+ ? [
99
+ override(RICH_VALUES_PART, CT.richValues),
100
+ override(RICH_VALUE_STRUCTURES_PART, CT.richValueStructures),
101
+ ]
102
+ : []),
91
103
  override(CORE_PROPS_PART, CT.core),
92
104
  override(APP_PROPS_PART, CT.app),
93
105
  ...preservedOverrides,
94
106
  ].join('');
95
107
  }
96
108
  function override(partPath, contentType) {
97
- return `<Override PartName="/${partPath}" ContentType="${contentType}"/>`;
109
+ return `<Override PartName="/${escapeAttr(partPath)}" ContentType="${escapeAttr(contentType)}"/>`;
98
110
  }
99
111
  function defaultType(extension, contentType) {
100
- return `<Default Extension="${extension}" ContentType="${contentType}"/>`;
112
+ return `<Default Extension="${escapeAttr(extension)}" ContentType="${escapeAttr(contentType)}"/>`;
101
113
  }
102
- export function rootRelsXml(rootRefs) {
103
- return relationshipsPart([
104
- relationship('rId1', REL.officeDocument, WORKBOOK_PART),
105
- relationship('rId2', REL.coreProps, CORE_PROPS_PART),
106
- relationship('rId3', REL.extProps, APP_PROPS_PART),
107
- ...rootRefs.map((ref, i) => relationship(`rId${4 + i}`, ref.relType, ref.entryPath)),
108
- ]);
109
- }
110
- export function workbookXml(workbook, preservedRels, pivots) {
114
+ export function workbookXml(workbook, plan, pivots) {
115
+ const preservedRels = plan.preservedWorkbookRels;
111
116
  const sheets = workbook.worksheets;
112
117
  const entries = sheets
113
118
  .map((sheet, i) => {
119
+ const relId = plan.sheetRelIds[i];
120
+ if (relId === undefined) {
121
+ throw new InternalError(`worksheet ${i + 1} of ${sheets.length} has no relationship id: the plan was drawn for ` +
122
+ `${plan.sheetRelIds.length} sheet(s)`);
123
+ }
114
124
  const state = sheet.state === 'visible'
115
125
  ? ''
116
126
  : ` state="${checkedToken(sheet.state, isVisibility, 'sheet visibility')}"`;
117
- return `<sheet name="${escapeAttr(sheet.name)}" sheetId="${sheet.id}"${state} r:id="rId${i + 1}"/>`;
127
+ return `<sheet name="${escapeAttr(sheet.name)}" sheetId="${sheet.id}"${state} r:id="${relId}"/>`;
118
128
  })
119
129
  .join('');
120
130
  return (XML_DECLARATION +
121
131
  `<workbook xmlns="${NS.main}" xmlns:r="${NS.docRels}">` +
132
+ workbookPrXml(workbook) +
122
133
  workbookProtectionXml(workbook) +
123
134
  bookViewsXml(workbook) +
124
135
  `<sheets>${entries}</sheets>` +
@@ -129,6 +140,11 @@ export function workbookXml(workbook, preservedRels, pivots) {
129
140
  workbookExtLstXml(preservedRels) +
130
141
  '</workbook>');
131
142
  }
143
+ function workbookPrXml(workbook) {
144
+ const attrs = (workbook.dateEpoch === 1904 ? ' date1904="1"' : '') +
145
+ (workbook.codeName === undefined ? '' : ` codeName="${escapeAttr(workbook.codeName)}"`);
146
+ return attrs === '' ? '' : `<workbookPr${attrs}/>`;
147
+ }
132
148
  function bookViewsXml(workbook) {
133
149
  const view = workbook.view;
134
150
  const activeTab = workbook.activeTabIndex;
@@ -146,23 +162,23 @@ function bookViewsXml(workbook) {
146
162
  function externalReferencesXml(preservedRels) {
147
163
  const links = preservedRels
148
164
  .filter((ref) => ref.externalReferenceIndex !== undefined)
149
- .sort((a, b) => a.externalReferenceIndex - b.externalReferenceIndex);
165
+ .sort((a, b) => (a.externalReferenceIndex ?? 0) - (b.externalReferenceIndex ?? 0));
150
166
  if (links.length === 0)
151
167
  return '';
152
168
  const entries = links.map((ref) => `<externalReference r:id="${ref.relId}"/>`).join('');
153
169
  return `<externalReferences>${entries}</externalReferences>`;
154
170
  }
155
171
  function workbookExtLstXml(preservedRels) {
156
- const caches = preservedRels.filter((ref) => ref.relType.endsWith('/slicerCache'));
172
+ const caches = preservedRels.filter((ref) => isRelType(ref.relType, 'slicerCache'));
157
173
  if (caches.length === 0)
158
174
  return '';
159
175
  const entries = caches.map((ref) => `<x14:slicerCache r:id="${ref.relId}"/>`).join('');
160
176
  return `<extLst>${x14Ext(SLICER_CACHES_EXT_URI, `<x14:slicerCaches>${entries}</x14:slicerCaches>`)}</extLst>`;
161
177
  }
162
178
  function pivotCachesXml(preservedRels, pivots) {
163
- const preserved = preservedRels
164
- .filter((ref) => ref.pivotCacheId !== undefined)
165
- .map((ref) => `<pivotCache cacheId="${escapeAttr(ref.pivotCacheId)}" r:id="${ref.relId}"/>`);
179
+ const preserved = preservedRels.flatMap((ref) => ref.pivotCacheId === undefined
180
+ ? []
181
+ : [`<pivotCache cacheId="${escapeAttr(ref.pivotCacheId)}" r:id="${ref.relId}"/>`]);
166
182
  const generated = pivots.map((pivot) => `<pivotCache cacheId="${escapeAttr(pivot.cacheId)}" r:id="${pivot.workbookRelId}"/>`);
167
183
  const entries = [...preserved, ...generated];
168
184
  if (entries.length === 0)
@@ -193,16 +209,24 @@ const EXCEL_CALC_ID = '171027';
193
209
  function calcPrXml(workbook) {
194
210
  return workbook.fullCalcOnLoad ? `<calcPr calcId="${EXCEL_CALC_ID}" fullCalcOnLoad="1"/>` : '';
195
211
  }
212
+ function localSheetId(sheets, name, scope) {
213
+ const wanted = scope.toLowerCase();
214
+ const index = sheets.findIndex((sheet) => sheet.name.toLowerCase() === wanted);
215
+ if (index === -1) {
216
+ throw new AuthoringError(`defined name ${quoted(name)} is scoped to worksheet ${quoted(scope)}, which this workbook does not contain`);
217
+ }
218
+ return index;
219
+ }
196
220
  function definedNamesXml(workbook) {
197
221
  const sheets = workbook.worksheets;
198
222
  const userEntries = workbook.definedNames.map((name) => {
199
223
  const scopeAttr = name.scope === undefined
200
224
  ? ''
201
- : ` localSheetId="${sheets.findIndex((sheet) => sheet.name === name.scope)}"`;
225
+ : ` localSheetId="${localSheetId(sheets, name.name, name.scope)}"`;
202
226
  const commentAttr = textAttr('comment', name.comment);
203
227
  const hiddenAttr = name.hidden ? ' hidden="1"' : '';
204
228
  return (`<definedName name="${escapeAttr(name.name)}"${scopeAttr}${commentAttr}${hiddenAttr}>` +
205
- `${escapeText(mangleFormula(name.refersTo))}</definedName>`);
229
+ `${escapeText(mangleFormula(name.refersTo, formulaNamesInScope(workbook.definedNames, name.scope)))}</definedName>`);
206
230
  });
207
231
  const filterEntries = sheets.flatMap((sheet, index) => sheet.autoFilter === undefined
208
232
  ? []
@@ -219,24 +243,6 @@ function filterDatabaseRefersTo(sheetName, range) {
219
243
  const absolute = range.replace(/([A-Z]+)(\d+)/g, '$$$1$$$2');
220
244
  return `${quoteSheetName(sheetName)}!${absolute}`;
221
245
  }
222
- export const FIXED_WORKBOOK_REL_COUNT = 2;
223
- export function workbookRelsXml(sheetCount, hasSharedStrings, personsRelId, preservedRels, pivots) {
224
- return relationshipsPart([
225
- ...Array.from({ length: sheetCount }, (_, i) => relationship(`rId${i + 1}`, REL.worksheet, targetFromWorkbook(worksheetPart(i + 1)))),
226
- relationship(`rId${sheetCount + 1}`, REL.styles, 'styles.xml'),
227
- relationship(`rId${sheetCount + FIXED_WORKBOOK_REL_COUNT}`, REL.theme, targetFromWorkbook(THEME_PART_PATH)),
228
- ...(hasSharedStrings
229
- ? [
230
- relationship(`rId${sheetCount + FIXED_WORKBOOK_REL_COUNT + 1}`, REL.sharedStrings, targetFromWorkbook(SHARED_STRINGS_PART)),
231
- ]
232
- : []),
233
- ...(personsRelId === null
234
- ? []
235
- : [relationship(personsRelId, REL.person, targetFromWorkbook(PERSONS_PART))]),
236
- ...preservedRels.map((ref) => relationship(ref.relId, ref.relType, escapeAttr(targetFromWorkbook(ref.entryPath)))),
237
- ...pivots.map((pivot) => relationship(pivot.workbookRelId, REL.pivotCacheDefinition, targetFromWorkbook(pivotCacheDefinitionPart(pivot.number)))),
238
- ]);
239
- }
240
246
  export function corePropsXml(properties) {
241
247
  const parts = [];
242
248
  if (properties.title !== undefined) {
@@ -248,10 +254,10 @@ export function corePropsXml(properties) {
248
254
  if (properties.lastModifiedBy !== undefined) {
249
255
  parts.push(`<cp:lastModifiedBy>${escapeText(properties.lastModifiedBy)}</cp:lastModifiedBy>`);
250
256
  }
251
- if (properties.created) {
257
+ if (properties.created !== undefined) {
252
258
  parts.push(w3cdtf('created', properties.created));
253
259
  }
254
- if (properties.modified) {
260
+ if (properties.modified !== undefined) {
255
261
  parts.push(w3cdtf('modified', properties.modified));
256
262
  }
257
263
  return (XML_DECLARATION +
@@ -261,7 +267,9 @@ export function corePropsXml(properties) {
261
267
  '</cp:coreProperties>');
262
268
  }
263
269
  function w3cdtf(element, date) {
264
- return `<dcterms:${element} xsi:type="dcterms:W3CDTF">${date.toISOString()}</dcterms:${element}>`;
270
+ assertWritableDate(date, `the document property ${quoted(element)}`);
271
+ const stamp = date.toISOString().replace(/\.\d{3}Z$/, 'Z');
272
+ return `<dcterms:${element} xsi:type="dcterms:W3CDTF">${stamp}</dcterms:${element}>`;
265
273
  }
266
274
  export function appPropsXml(properties) {
267
275
  const company = properties.company === undefined ? '' : `<Company>${escapeText(properties.company)}</Company>`;
@@ -1,46 +1,11 @@
1
- import { type Cell } from '../../core/cell.ts';
2
- import type { ColumnProperties, RowProperties, Worksheet } from '../../core/worksheet.ts';
1
+ import type { DateEpoch } from '../../core/date.ts';
2
+ import type { Worksheet } from '../../core/worksheet.ts';
3
+ import type { WorkbookMetadataTable } from './cell-metadata.ts';
3
4
  import { type HyperlinkPlan } from './hyperlinks.ts';
4
- import type { BackgroundPlan, CommentPlan, DrawingPlan, PivotPlan, PreservedReferencePlan, PrinterSettingsPlan, TablePlan, ThreadedCommentPlan } from './package-plan.ts';
5
- import { type SharedFormulaRole } from './shared-formulas.ts';
5
+ import type { TablePlan } from './package-plan.ts';
6
+ import { type FlushedSheet } from './row-xml.ts';
6
7
  import type { SharedStringTable } from './shared-strings.ts';
7
8
  import type { StyleRegistry } from './styles.ts';
8
- /**
9
- * The used-cell extent of a sheet: the top-left/bottom-right grid bounds that fold into the
10
- * `<dimension>`. Rows carrying only formatting (a row height, an outline level) do not extend the
11
- * used range, matching how Excel records `<dimension>`, so {@link add} ignores them. A fresh extent
12
- * holds the `Infinity`/`-Infinity` sentinels; {@link isEmpty} reports that no used cell has been seen.
13
- */
14
- export declare class Extent {
15
- top: number;
16
- left: number;
17
- bottom: number;
18
- right: number;
19
- constructor(seed?: Extent);
20
- /** Whether no used cell has been folded in yet, in which case the dimension is the lone cell `A1`. */
21
- get isEmpty(): boolean;
22
- /** Fold a rendered row's used-column span into the extent. `minCol` is `Infinity` when the row
23
- * carried no cells (only formatting), which extends nothing. */
24
- add(row: number, minCol: number, maxCol: number): void;
25
- }
26
- /**
27
- * A worksheet's eagerly-serialised rows: each row's `<row>` XML tagged with its number (so it merges
28
- * into ascending order with the sheet's remaining live rows, whatever order it was committed in), plus
29
- * the used-cell {@link Extent} they span. The buffered pass folds that extent into the sheet's dimension.
30
- */
31
- export interface FlushedSheet {
32
- readonly rows: ReadonlyArray<{
33
- readonly number: number;
34
- readonly xml: string;
35
- }>;
36
- readonly extent: Extent;
37
- /**
38
- * The deepest row outline level among the flushed rows. Carried across the eviction because
39
- * `<sheetFormatPr outlineLevelRow>` is derived from every row on the sheet, and a flushed row's
40
- * properties are gone from the model by the time the header is serialised.
41
- */
42
- readonly maxRowOutlineLevel: number;
43
- }
44
9
  export interface SheetReferences {
45
10
  readonly drawingRelId: string | null;
46
11
  readonly legacyDrawingRelId: string | null;
@@ -49,38 +14,29 @@ export interface SheetReferences {
49
14
  readonly legacyDrawingHFRelId: string | null;
50
15
  readonly slicerRelIds: readonly string[];
51
16
  }
52
- export declare function worksheetXml(sheet: Worksheet, tables: readonly TablePlan[], styles: StyleRegistry, references: SheetReferences, hyperlinks: readonly HyperlinkPlan[], sharedStrings: SharedStringTable | null, active: boolean, flushed?: FlushedSheet): string;
53
17
  /**
54
- * A column's style facets are defaults its cells inherit unless they override them; the writer
55
- * composes each cell's full style up front (cell over row over column, per facet) so a cell that
56
- * overrides one facet still carries the column's others, rather than silently dropping them. Frozen
57
- * once by the streaming writer at its first flush so every eagerly-rendered row sees the same defaults.
18
+ * Everything one worksheet part is rendered from: the sheet itself, the parts of the package plan
19
+ * that belong to it, and the two registries a sheet pass interns into.
20
+ *
21
+ * One object for the reason {@link SheetReferences} is one object, applied to the layer above it: a
22
+ * run of positional arguments carrying two `readonly …[]`s, two nullable references and a bare
23
+ * boolean is a run whose order the call site cannot be read against. `active:` is the clearest of
24
+ * them -- as a positional it needed a comment at the call site to say which boolean it was.
58
25
  */
59
- export declare function buildColumnDefaults(sheet: Worksheet): Map<number, ColumnProperties>;
60
- /** The whole-sheet context a single row needs to serialise: the column defaults it inherits, the
61
- * style/string tables it interns into, the shared-formula roles its cells play, and the collapsed
62
- * outline summaries whose toggle it must stamp. The streaming writer supplies empty shared-formula
63
- * and collapsed-summary sets, since those are whole-sheet derivations a flushed row cannot join. */
64
- export interface RowRenderContext {
65
- readonly columnDefaults: ReadonlyMap<number, ColumnProperties>;
26
+ export interface WorksheetXmlInputs {
27
+ readonly sheet: Worksheet;
28
+ readonly tables: readonly TablePlan[];
66
29
  readonly styles: StyleRegistry;
30
+ readonly references: SheetReferences;
31
+ readonly hyperlinks: readonly HyperlinkPlan[];
67
32
  readonly sharedStrings: SharedStringTable | null;
68
- readonly sharedRoles: ReadonlyMap<string, SharedFormulaRole>;
69
- readonly collapsedSummaries: ReadonlySet<number>;
33
+ readonly cellMetadata: WorkbookMetadataTable;
34
+ readonly dateEpoch: DateEpoch;
35
+ /** The defined names a bare name in this sheet's formulas resolves to; see `formulaNamesInScope`. */
36
+ readonly formulaNames: ReadonlySet<string>;
37
+ /** Whether this is the workbook's one selected sheet. */
38
+ readonly active: boolean;
39
+ /** The rows the streaming writer already serialised and evicted, absent on the buffered path. */
40
+ readonly flushed?: FlushedSheet | undefined;
70
41
  }
71
- /**
72
- * Serialise one row to its `<row>` element, or '' when the row has neither data nor its own
73
- * formatting. Returns the used-column bounds (`Infinity`/`-Infinity` when nothing was rendered) so a
74
- * caller can fold them into the sheet dimension. Shared by the buffered sheet pass and the streaming
75
- * writer's eager flush, so both emit byte-identical rows.
76
- */
77
- export declare function renderRow(entry: {
78
- readonly number: number;
79
- readonly cells: readonly Cell[];
80
- readonly properties: RowProperties | undefined;
81
- }, ctx: RowRenderContext): {
82
- xml: string;
83
- minCol: number;
84
- maxCol: number;
85
- };
86
- export declare function worksheetRelsXml(tables: readonly TablePlan[], drawing: DrawingPlan | null, comments: CommentPlan | null, threadedComments: ThreadedCommentPlan | null, printerSettings: PrinterSettingsPlan | null, background: BackgroundPlan | null, hyperlinks: readonly HyperlinkPlan[], preservedReferences: readonly PreservedReferencePlan[], pivots: readonly PivotPlan[]): string;
42
+ export declare function worksheetXml(inputs: WorksheetXmlInputs): string;