@office-kit/xlsx 0.8.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 (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +319 -0
  3. package/THIRD_PARTY_NOTICES.md +56 -0
  4. package/dist/cell/cell.d.ts +234 -0
  5. package/dist/cell/index.d.ts +4 -0
  6. package/dist/cell/rich-text.d.ts +37 -0
  7. package/dist/cell-D9CaNKnU.mjs +320 -0
  8. package/dist/cell-D9CaNKnU.mjs.map +1 -0
  9. package/dist/cell-style-BEDjMX1y.mjs +1579 -0
  10. package/dist/cell-style-BEDjMX1y.mjs.map +1 -0
  11. package/dist/cell.mjs +2 -0
  12. package/dist/chart/chart-xml.d.ts +16 -0
  13. package/dist/chart/chart.d.ts +735 -0
  14. package/dist/chart/cx/chartex-xml.d.ts +6 -0
  15. package/dist/chart/cx/chartex.d.ts +279 -0
  16. package/dist/chart/index.d.ts +6 -0
  17. package/dist/chart/user-shapes-xml.d.ts +4 -0
  18. package/dist/chart/user-shapes.d.ts +61 -0
  19. package/dist/chart.mjs +232 -0
  20. package/dist/chart.mjs.map +1 -0
  21. package/dist/chartsheet/chartsheet-xml.d.ts +17 -0
  22. package/dist/chartsheet/chartsheet.d.ts +121 -0
  23. package/dist/chartsheet/index.d.ts +2 -0
  24. package/dist/chartsheet-C3-tqkPy.mjs +23 -0
  25. package/dist/chartsheet-C3-tqkPy.mjs.map +1 -0
  26. package/dist/chartsheet.mjs +2 -0
  27. package/dist/colors-ovWAwnZI.mjs +67 -0
  28. package/dist/colors-ovWAwnZI.mjs.map +1 -0
  29. package/dist/compat/numbers.d.ts +14 -0
  30. package/dist/coordinate-96Ecci4d.mjs +276 -0
  31. package/dist/coordinate-96Ecci4d.mjs.map +1 -0
  32. package/dist/datetime-B2ySVlXt.mjs +71 -0
  33. package/dist/datetime-B2ySVlXt.mjs.map +1 -0
  34. package/dist/defined-names-CviWmtQg.mjs +89 -0
  35. package/dist/defined-names-CviWmtQg.mjs.map +1 -0
  36. package/dist/differential-D4dg-qtZ.mjs +37 -0
  37. package/dist/differential-D4dg-qtZ.mjs.map +1 -0
  38. package/dist/drawing/anchor.d.ts +63 -0
  39. package/dist/drawing/dml/colors.d.ts +109 -0
  40. package/dist/drawing/dml/dml-xml.d.ts +35 -0
  41. package/dist/drawing/dml/effect.d.ts +92 -0
  42. package/dist/drawing/dml/fill.d.ts +115 -0
  43. package/dist/drawing/dml/geometry.d.ts +113 -0
  44. package/dist/drawing/dml/line.d.ts +41 -0
  45. package/dist/drawing/dml/shape-properties.d.ts +33 -0
  46. package/dist/drawing/dml/text.d.ts +218 -0
  47. package/dist/drawing/drawing-xml.d.ts +5 -0
  48. package/dist/drawing/drawing.d.ts +117 -0
  49. package/dist/drawing/image.d.ts +40 -0
  50. package/dist/drawing/index.d.ts +14 -0
  51. package/dist/drawing-BxzLuryn.mjs +415 -0
  52. package/dist/drawing-BxzLuryn.mjs.map +1 -0
  53. package/dist/drawing.mjs +119 -0
  54. package/dist/drawing.mjs.map +1 -0
  55. package/dist/escape-DFTE7ZJc.mjs +51 -0
  56. package/dist/escape-DFTE7ZJc.mjs.map +1 -0
  57. package/dist/exceptions-D-CFwxgm.mjs +37 -0
  58. package/dist/exceptions-D-CFwxgm.mjs.map +1 -0
  59. package/dist/formula/tokenizer.d.ts +61 -0
  60. package/dist/formula/translate.d.ts +67 -0
  61. package/dist/inference-B3ES3KEJ.mjs +42 -0
  62. package/dist/inference-B3ES3KEJ.mjs.map +1 -0
  63. package/dist/io/browser.d.ts +41 -0
  64. package/dist/io/index.d.ts +7 -0
  65. package/dist/io/load.d.ts +46 -0
  66. package/dist/io/node-fs.d.ts +62 -0
  67. package/dist/io/node-save.d.ts +3 -0
  68. package/dist/io/node.d.ts +17 -0
  69. package/dist/io/save.d.ts +14 -0
  70. package/dist/io/sink.d.ts +54 -0
  71. package/dist/io/source.d.ts +14 -0
  72. package/dist/io.mjs +212 -0
  73. package/dist/io.mjs.map +1 -0
  74. package/dist/load-D5cbhoGx.mjs +1069 -0
  75. package/dist/load-D5cbhoGx.mjs.map +1 -0
  76. package/dist/manifest-Dps1-OpP.mjs +801 -0
  77. package/dist/manifest-Dps1-OpP.mjs.map +1 -0
  78. package/dist/node.d.ts +3 -0
  79. package/dist/node.mjs +308 -0
  80. package/dist/node.mjs.map +1 -0
  81. package/dist/packaging/core.d.ts +45 -0
  82. package/dist/packaging/custom.d.ts +62 -0
  83. package/dist/packaging/extended.d.ts +45 -0
  84. package/dist/packaging/index.d.ts +10 -0
  85. package/dist/packaging/manifest.d.ts +24 -0
  86. package/dist/packaging/relationships.d.ts +30 -0
  87. package/dist/packaging.mjs +2 -0
  88. package/dist/parser-DuLejQy1.mjs +156 -0
  89. package/dist/parser-DuLejQy1.mjs.map +1 -0
  90. package/dist/reader-D1fNW9k1.mjs +534 -0
  91. package/dist/reader-D1fNW9k1.mjs.map +1 -0
  92. package/dist/save-RohQtgEZ.mjs +745 -0
  93. package/dist/save-RohQtgEZ.mjs.map +1 -0
  94. package/dist/schema/core.d.ts +133 -0
  95. package/dist/schema/index.d.ts +3 -0
  96. package/dist/schema/serialize.d.ts +6 -0
  97. package/dist/schema.mjs +2 -0
  98. package/dist/serialize-55EnT30e.mjs +254 -0
  99. package/dist/serialize-55EnT30e.mjs.map +1 -0
  100. package/dist/serializer-BwbgHYJV.mjs +116 -0
  101. package/dist/serializer-BwbgHYJV.mjs.map +1 -0
  102. package/dist/streaming/index.d.ts +2 -0
  103. package/dist/streaming/read-only.d.ts +38 -0
  104. package/dist/streaming/write-only.d.ts +47 -0
  105. package/dist/streaming.mjs +612 -0
  106. package/dist/streaming.mjs.map +1 -0
  107. package/dist/styles/alignment.d.ts +33 -0
  108. package/dist/styles/alignment.schema.d.ts +3 -0
  109. package/dist/styles/borders.d.ts +40 -0
  110. package/dist/styles/borders.schema.d.ts +4 -0
  111. package/dist/styles/cell-style.d.ts +270 -0
  112. package/dist/styles/colors.d.ts +128 -0
  113. package/dist/styles/colors.schema.d.ts +3 -0
  114. package/dist/styles/differential.d.ts +41 -0
  115. package/dist/styles/fills.d.ts +54 -0
  116. package/dist/styles/fills.schema.d.ts +6 -0
  117. package/dist/styles/fonts.d.ts +44 -0
  118. package/dist/styles/fonts.schema.d.ts +3 -0
  119. package/dist/styles/index.d.ts +21 -0
  120. package/dist/styles/named-styles.d.ts +52 -0
  121. package/dist/styles/numbers.d.ts +39 -0
  122. package/dist/styles/numbers.schema.d.ts +3 -0
  123. package/dist/styles/protection.d.ts +9 -0
  124. package/dist/styles/protection.schema.d.ts +3 -0
  125. package/dist/styles/stylesheet-reader.d.ts +7 -0
  126. package/dist/styles/stylesheet-writer.d.ts +3 -0
  127. package/dist/styles/stylesheet.d.ts +95 -0
  128. package/dist/styles.mjs +4 -0
  129. package/dist/stylesheet-writer-C2eRmn22.mjs +8624 -0
  130. package/dist/stylesheet-writer-C2eRmn22.mjs.map +1 -0
  131. package/dist/table-DkX6UniA.mjs +113 -0
  132. package/dist/table-DkX6UniA.mjs.map +1 -0
  133. package/dist/tree-Bbs1C8Rc.mjs +192 -0
  134. package/dist/tree-Bbs1C8Rc.mjs.map +1 -0
  135. package/dist/units-rOMQqXh2.mjs +41 -0
  136. package/dist/units-rOMQqXh2.mjs.map +1 -0
  137. package/dist/user-shapes-DfmCGKB0.mjs +252 -0
  138. package/dist/user-shapes-DfmCGKB0.mjs.map +1 -0
  139. package/dist/utf8-D91g1XTG.mjs +143 -0
  140. package/dist/utf8-D91g1XTG.mjs.map +1 -0
  141. package/dist/utils/coordinate.d.ts +103 -0
  142. package/dist/utils/css.d.ts +18 -0
  143. package/dist/utils/datetime.d.ts +38 -0
  144. package/dist/utils/escape.d.ts +34 -0
  145. package/dist/utils/exceptions.d.ts +34 -0
  146. package/dist/utils/index.d.ts +11 -0
  147. package/dist/utils/inference.d.ts +24 -0
  148. package/dist/utils/stable-stringify.d.ts +7 -0
  149. package/dist/utils/units.d.ts +14 -0
  150. package/dist/utils/utf8.d.ts +1 -0
  151. package/dist/utils.mjs +39 -0
  152. package/dist/utils.mjs.map +1 -0
  153. package/dist/workbook/calc-properties.d.ts +47 -0
  154. package/dist/workbook/defined-names.d.ts +121 -0
  155. package/dist/workbook/file-recovery.d.ts +11 -0
  156. package/dist/workbook/file-sharing.d.ts +14 -0
  157. package/dist/workbook/file-version.d.ts +13 -0
  158. package/dist/workbook/function-groups.d.ts +10 -0
  159. package/dist/workbook/index.d.ts +24 -0
  160. package/dist/workbook/protection.d.ts +35 -0
  161. package/dist/workbook/shared-strings.d.ts +57 -0
  162. package/dist/workbook/smart-tags.d.ts +13 -0
  163. package/dist/workbook/views.d.ts +89 -0
  164. package/dist/workbook/workbook-properties.d.ts +57 -0
  165. package/dist/workbook/workbook.d.ts +643 -0
  166. package/dist/workbook-HGYNRBlV.mjs +636 -0
  167. package/dist/workbook-HGYNRBlV.mjs.map +1 -0
  168. package/dist/workbook.mjs +58 -0
  169. package/dist/workbook.mjs.map +1 -0
  170. package/dist/worksheet/auto-filter.d.ts +34 -0
  171. package/dist/worksheet/cell-range.d.ts +121 -0
  172. package/dist/worksheet/comments-xml.d.ts +24 -0
  173. package/dist/worksheet/comments.d.ts +13 -0
  174. package/dist/worksheet/conditional-formatting.d.ts +150 -0
  175. package/dist/worksheet/custom-sheet-views.d.ts +43 -0
  176. package/dist/worksheet/data-consolidate.d.ts +29 -0
  177. package/dist/worksheet/data-validations.d.ts +72 -0
  178. package/dist/worksheet/dimensions.d.ts +40 -0
  179. package/dist/worksheet/errors.d.ts +40 -0
  180. package/dist/worksheet/hyperlinks.d.ts +42 -0
  181. package/dist/worksheet/index.d.ts +46 -0
  182. package/dist/worksheet/ole-objects.d.ts +37 -0
  183. package/dist/worksheet/page-setup.d.ts +173 -0
  184. package/dist/worksheet/phonetic.d.ts +11 -0
  185. package/dist/worksheet/properties.d.ts +34 -0
  186. package/dist/worksheet/protected-ranges.d.ts +19 -0
  187. package/dist/worksheet/protection.d.ts +44 -0
  188. package/dist/worksheet/reader.d.ts +38 -0
  189. package/dist/worksheet/scenarios.d.ts +36 -0
  190. package/dist/worksheet/smart-tags.d.ts +23 -0
  191. package/dist/worksheet/sort-state.d.ts +28 -0
  192. package/dist/worksheet/table-xml.d.ts +5 -0
  193. package/dist/worksheet/table.d.ts +80 -0
  194. package/dist/worksheet/views.d.ts +47 -0
  195. package/dist/worksheet/web-publish.d.ts +21 -0
  196. package/dist/worksheet/worksheet.d.ts +935 -0
  197. package/dist/worksheet/writer.d.ts +72 -0
  198. package/dist/worksheet-CmCNoIgD.mjs +1726 -0
  199. package/dist/worksheet-CmCNoIgD.mjs.map +1 -0
  200. package/dist/worksheet.mjs +247 -0
  201. package/dist/worksheet.mjs.map +1 -0
  202. package/dist/writer-DspzfkNA.mjs +221 -0
  203. package/dist/writer-DspzfkNA.mjs.map +1 -0
  204. package/dist/xml/index.d.ts +10 -0
  205. package/dist/xml/iterparse.d.ts +22 -0
  206. package/dist/xml/namespaces.d.ts +91 -0
  207. package/dist/xml/parser.d.ts +7 -0
  208. package/dist/xml/serializer.d.ts +14 -0
  209. package/dist/xml/stream-writer.d.ts +39 -0
  210. package/dist/xml/tree.d.ts +37 -0
  211. package/dist/xml.mjs +140 -0
  212. package/dist/xml.mjs.map +1 -0
  213. package/dist/zip/decompression-guard.d.ts +70 -0
  214. package/dist/zip/index.d.ts +6 -0
  215. package/dist/zip/random-access-reader.d.ts +16 -0
  216. package/dist/zip/reader.d.ts +45 -0
  217. package/dist/zip/writer.d.ts +65 -0
  218. package/dist/zip/zip64-patch.d.ts +12 -0
  219. package/dist/zip.mjs +3 -0
  220. package/package.json +147 -0
@@ -0,0 +1,636 @@
1
+ import { o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
2
+ import { m as parseSheetRange, s as coordinateToTuple } from "./coordinate-96Ecci4d.mjs";
3
+ import { h as isFormulaValue } from "./cell-D9CaNKnU.mjs";
4
+ import { t as makeChartsheet } from "./chartsheet-C3-tqkPy.mjs";
5
+ import { a as makeChartDrawingItem, d as makeAbsoluteAnchor, o as makeDrawing } from "./drawing-BxzLuryn.mjs";
6
+ import { i as unescapeCellString, n as escapeXmlAttr, r as escapeXmlText, t as escapeCellString } from "./escape-DFTE7ZJc.mjs";
7
+ import { a as findChildren, ft as SHEET_MAIN_NS, i as findChild, jt as qname } from "./tree-Bbs1C8Rc.mjs";
8
+ import { t as parseXml } from "./parser-DuLejQy1.mjs";
9
+ import { Cn as parseRange, D as getCellHyperlink, Dn as rangeToString, E as getCellComment, L as getMergedRangeAt, Tn as rangeContainsCell, _ as countCellsByKind, at as makeWorksheet, bn as multiCellRangeContainsCell, nn as colorToHex, u as classifyCellValue, w as getCell, xt as setCellByCoord } from "./worksheet-CmCNoIgD.mjs";
10
+ import { _ as getCellNumberFormat, ft as makeStylesheet, g as getCellFont, h as getCellFill, m as getCellBorder, p as getCellAlignment, v as getCellProtection } from "./cell-style-BEDjMX1y.mjs";
11
+ //#region src/workbook/shared-strings.ts
12
+ const SST_TAG = `{${SHEET_MAIN_NS}}sst`;
13
+ const SI_TAG = `{${SHEET_MAIN_NS}}si`;
14
+ const T_TAG = `{${SHEET_MAIN_NS}}t`;
15
+ const R_TAG = `{${SHEET_MAIN_NS}}r`;
16
+ function makeSharedStrings() {
17
+ return {
18
+ entries: [],
19
+ index: /* @__PURE__ */ new Map()
20
+ };
21
+ }
22
+ /**
23
+ * Insert a string and return its index. Idempotent: calling with the same value
24
+ * twice gives the same index. Empty strings are deduped just like everything
25
+ * else.
26
+ */
27
+ function addSharedString(table, value) {
28
+ const cached = table.index.get(value);
29
+ if (cached !== void 0) return cached;
30
+ const id = table.entries.length;
31
+ table.entries.push(value);
32
+ table.index.set(value, id);
33
+ return id;
34
+ }
35
+ /** Look up a shared-string index by its literal text. Returns `undefined` for unknown values. */
36
+ function getSharedStringIndex(table, value) {
37
+ return table.index.get(value);
38
+ }
39
+ /**
40
+ * Read a shared-string by its 0-based index. Returns `undefined` for
41
+ * out-of-range. Rich-text entries surface their concatenated plain text so
42
+ * callers that want only the textual body don't need to know about the
43
+ * discriminated union.
44
+ */
45
+ function getSharedStringAt(table, index) {
46
+ const entry = table.entries[index];
47
+ if (entry === void 0) return void 0;
48
+ if (typeof entry === "string") return entry;
49
+ return entry.runs.map((r) => r.text).join("");
50
+ }
51
+ /** Number of unique entries in the SST. */
52
+ function sharedStringCount(table) {
53
+ return table.entries.length;
54
+ }
55
+ /** Concatenate every `<t>` text node found inside an arbitrary XmlNode tree. */
56
+ const collectText = (node) => {
57
+ if (node.children.length === 1) {
58
+ const only = node.children[0];
59
+ if (only && only.name === T_TAG) return unescapeCellString(only.text ?? "");
60
+ }
61
+ let out = "";
62
+ for (const child of node.children) if (child.name === T_TAG) out += child.text ?? "";
63
+ else if (child.name === R_TAG) {
64
+ const t = findChild(child, T_TAG);
65
+ if (t?.text) out += t.text;
66
+ }
67
+ return unescapeCellString(out);
68
+ };
69
+ /**
70
+ * Parse a `xl/sharedStrings.xml` payload. Returns the table directly (rather
71
+ * than just the array) so the worksheet writer can keep appending to it without
72
+ * rebuilding the index.
73
+ *
74
+ * Rich-text runs are preserved as their full per-run formatting so
75
+ * round-tripping a file with rich text doesn't drop the styling.
76
+ */
77
+ function parseSharedStringsXml(bytes) {
78
+ const root = parseXml(bytes);
79
+ if (root.name !== SST_TAG) throw new OpenXmlSchemaError(`parseSharedStringsXml: root is "${root.name}", expected sst`);
80
+ const table = makeSharedStrings();
81
+ for (const si of findChildren(root, SI_TAG)) {
82
+ const entry = parseSi(si);
83
+ const id = table.entries.length;
84
+ table.entries.push(entry);
85
+ if (typeof entry === "string" && !table.index.has(entry)) table.index.set(entry, id);
86
+ }
87
+ return table;
88
+ }
89
+ const parseSi = (si) => {
90
+ const runEls = findChildren(si, R_TAG);
91
+ if (runEls.length > 0) {
92
+ const runs = [];
93
+ for (const rEl of runEls) {
94
+ const text = unescapeCellString(findChild(rEl, T_TAG)?.text ?? "");
95
+ const rPrEl = findChild(rEl, qname(SHEET_MAIN_NS, "rPr"));
96
+ const font = rPrEl ? parseRunPr(rPrEl) : void 0;
97
+ runs.push(font !== void 0 ? {
98
+ text,
99
+ font
100
+ } : { text });
101
+ }
102
+ return {
103
+ kind: "rich-text",
104
+ runs: Object.freeze(runs)
105
+ };
106
+ }
107
+ return collectText(si);
108
+ };
109
+ const parseRunPr = (rPr) => {
110
+ const f = {};
111
+ for (const child of rPr.children) {
112
+ const local = child.name.replace(/^\{[^}]+\}/, "");
113
+ const valAttr = child.attrs["val"];
114
+ switch (local) {
115
+ case "rFont":
116
+ case "name":
117
+ if (valAttr !== void 0) f.name = valAttr;
118
+ break;
119
+ case "sz":
120
+ if (valAttr !== void 0) f.sz = Number.parseFloat(valAttr);
121
+ break;
122
+ case "b":
123
+ f.b = valAttr === void 0 ? true : valAttr !== "0" && valAttr !== "false";
124
+ break;
125
+ case "i":
126
+ f.i = valAttr === void 0 ? true : valAttr !== "0" && valAttr !== "false";
127
+ break;
128
+ case "u":
129
+ f.u = valAttr ?? "single";
130
+ break;
131
+ case "strike":
132
+ f.strike = valAttr === void 0 ? true : valAttr !== "0" && valAttr !== "false";
133
+ break;
134
+ case "vertAlign":
135
+ if (valAttr !== void 0) f.vertAlign = valAttr;
136
+ break;
137
+ case "family":
138
+ if (valAttr !== void 0) f.family = Number.parseInt(valAttr, 10);
139
+ break;
140
+ case "charset":
141
+ if (valAttr !== void 0) f.charset = Number.parseInt(valAttr, 10);
142
+ break;
143
+ case "scheme":
144
+ if (valAttr !== void 0) f.scheme = valAttr;
145
+ break;
146
+ case "color": {
147
+ const c = {};
148
+ if (child.attrs["rgb"] !== void 0) c.rgb = child.attrs["rgb"];
149
+ if (child.attrs["theme"] !== void 0) c.theme = Number.parseInt(child.attrs["theme"], 10);
150
+ if (child.attrs["indexed"] !== void 0) c.indexed = Number.parseInt(child.attrs["indexed"], 10);
151
+ if (child.attrs["tint"] !== void 0) c.tint = Number.parseFloat(child.attrs["tint"]);
152
+ if (child.attrs["auto"] !== void 0) c.auto = child.attrs["auto"] === "1" || child.attrs["auto"] === "true";
153
+ f.color = c;
154
+ break;
155
+ }
156
+ }
157
+ }
158
+ return Object.keys(f).length === 0 ? void 0 : Object.freeze(f);
159
+ };
160
+ const XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
161
+ /**
162
+ * Serialise a SharedStringsTable to its OOXML bytes. The `count` attribute
163
+ * tracks total references (we don't know that here so we report the same as
164
+ * `uniqueCount` — readers tolerate the discrepancy and Excel ignores `count` in
165
+ * practice). `uniqueCount` always matches `entries.length`.
166
+ */
167
+ function sharedStringsToBytes(table) {
168
+ return new TextEncoder().encode(serializeSharedStrings(table));
169
+ }
170
+ function serializeSharedStrings(table) {
171
+ const total = table.entries.length;
172
+ const parts = [XML_HEADER, `<sst xmlns="${SHEET_MAIN_NS}" count="${total}" uniqueCount="${total}">`];
173
+ for (const value of table.entries) parts.push(serializeSi(value));
174
+ parts.push("</sst>");
175
+ return parts.join("");
176
+ }
177
+ const serializeSi = (value) => {
178
+ if (typeof value === "string") return `<si><t${value.length > 0 && (value[0] === " " || value[value.length - 1] === " " || /[\t\n]/.test(value)) ? " xml:space=\"preserve\"" : ""}>${escapeXmlText(escapeCellString(value))}</t></si>`;
179
+ return `<si>${serializeRichTextRuns(value.runs)}</si>`;
180
+ };
181
+ /**
182
+ * Serialise a sequence of `<r>...<r>` runs — shared by the SST `<si>` writer
183
+ * and the worksheet's inline-string (`t="inlineStr"`) cell writer.
184
+ */
185
+ function serializeRichTextRuns(runs) {
186
+ const parts = [];
187
+ for (const run of runs) {
188
+ parts.push("<r>");
189
+ if (run.font) parts.push(serializeInlineFont(run.font));
190
+ const text = run.text;
191
+ const tAttr = text.length > 0 && (text[0] === " " || text[text.length - 1] === " " || /[\t\n]/.test(text)) ? " xml:space=\"preserve\"" : "";
192
+ parts.push(`<t${tAttr}>${escapeXmlText(escapeCellString(text))}</t>`);
193
+ parts.push("</r>");
194
+ }
195
+ return parts.join("");
196
+ }
197
+ const serializeInlineFont = (f) => {
198
+ const parts = ["<rPr>"];
199
+ if (f.name !== void 0) parts.push(`<rFont val="${escapeXmlAttr(f.name)}"/>`);
200
+ if (f.charset !== void 0) parts.push(`<charset val="${f.charset}"/>`);
201
+ if (f.family !== void 0) parts.push(`<family val="${f.family}"/>`);
202
+ if (f.b) parts.push("<b/>");
203
+ if (f.i) parts.push("<i/>");
204
+ if (f.strike) parts.push("<strike/>");
205
+ if (f.outline) parts.push("<outline/>");
206
+ if (f.shadow) parts.push("<shadow/>");
207
+ if (f.condense) parts.push("<condense/>");
208
+ if (f.extend) parts.push("<extend/>");
209
+ if (f.color) parts.push(serializeRunColor(f.color));
210
+ if (f.sz !== void 0) parts.push(`<sz val="${f.sz}"/>`);
211
+ if (f.u) parts.push(`<u val="${f.u}"/>`);
212
+ if (f.vertAlign) parts.push(`<vertAlign val="${f.vertAlign}"/>`);
213
+ if (f.scheme) parts.push(`<scheme val="${f.scheme}"/>`);
214
+ parts.push("</rPr>");
215
+ return parts.join("");
216
+ };
217
+ const serializeRunColor = (c) => {
218
+ const attrs = [];
219
+ if (c.rgb !== void 0) attrs.push(`rgb="${escapeXmlAttr(c.rgb)}"`);
220
+ else if (c.theme !== void 0) attrs.push(`theme="${c.theme}"`);
221
+ else if (c.indexed !== void 0) attrs.push(`indexed="${c.indexed}"`);
222
+ else if (c.auto !== void 0) attrs.push(`auto="${c.auto ? "1" : "0"}"`);
223
+ if (c.tint !== void 0) attrs.push(`tint="${c.tint}"`);
224
+ if (attrs.length === 0) {
225
+ const hex = colorToHex(c);
226
+ if (hex !== void 0) attrs.push(`rgb="${hex}"`);
227
+ }
228
+ return `<color${attrs.length > 0 ? ` ${attrs.join(" ")}` : ""}/>`;
229
+ };
230
+ //#endregion
231
+ //#region src/workbook/workbook.ts
232
+ /** Build an empty Workbook ready to host worksheets. */
233
+ function createWorkbook(opts) {
234
+ return {
235
+ sheets: [],
236
+ activeSheetIndex: 0,
237
+ styles: makeStylesheet(),
238
+ date1904: opts?.date1904 ?? false,
239
+ authors: [],
240
+ definedNames: []
241
+ };
242
+ }
243
+ /**
244
+ * Validate a sheet title against Excel's character + length rules. Returns the
245
+ * reason string when the title is rejected; `undefined` when valid. The same
246
+ * rules apply to worksheets and chartsheets.
247
+ *
248
+ * Rules:
249
+ * - Type must be `string`; non-empty; length ≤ 31.
250
+ * - May not contain any of `:`, `\`, `/`, `?`, `*`, `[`, `]`.
251
+ * - May not start or end with an apostrophe `'`.
252
+ * - May not be the literal `"History"` (case-insensitive — Excel
253
+ * reserves that name for the change-tracking sheet).
254
+ *
255
+ * Uniqueness is **not** checked here; pass through `addWorksheet` /
256
+ * `renameSheet` for the workbook-aware duplicate check.
257
+ */
258
+ function validateSheetTitle(title) {
259
+ if (typeof title !== "string") return "must be a string";
260
+ if (title.length === 0) return "must be 1..31 chars";
261
+ if (title.length > 31) return "must be 1..31 chars";
262
+ if (/[:\\/?*[\]]/.test(title)) return "must not contain : \\ / ? * [ ]";
263
+ if (title.startsWith("'") || title.endsWith("'")) return "must not start or end with an apostrophe";
264
+ if (title.toLowerCase() === "history") return "\"History\" is reserved by Excel";
265
+ }
266
+ const validateUniqueTitle = (wb, title, ignoreIndex) => {
267
+ const reason = validateSheetTitle(title);
268
+ if (reason) throw new OpenXmlSchemaError(`Worksheet title "${title}": ${reason}`);
269
+ const lower = title.toLowerCase();
270
+ for (let i = 0; i < wb.sheets.length; i++) {
271
+ if (i === ignoreIndex) continue;
272
+ const s = wb.sheets[i];
273
+ if (s && s.sheet.title.toLowerCase() === lower) throw new OpenXmlSchemaError(`Worksheet title "${title}" is already in use`);
274
+ }
275
+ };
276
+ const allocateSheetId = (wb) => {
277
+ const used = /* @__PURE__ */ new Set();
278
+ for (const s of wb.sheets) used.add(s.sheetId);
279
+ let n = 1;
280
+ while (used.has(n)) n++;
281
+ return n;
282
+ };
283
+ /** Add a Worksheet to the Workbook. Returns the sheet for further population. */
284
+ function addWorksheet(wb, title, opts) {
285
+ validateUniqueTitle(wb, title);
286
+ const sheet = makeWorksheet(title);
287
+ const ref = {
288
+ kind: "worksheet",
289
+ sheet,
290
+ sheetId: allocateSheetId(wb),
291
+ state: opts?.state ?? "visible"
292
+ };
293
+ if (opts?.index === void 0) wb.sheets.push(ref);
294
+ else {
295
+ if (opts.index < 0 || opts.index > wb.sheets.length) throw new OpenXmlSchemaError(`addWorksheet: index ${opts.index} out of range`);
296
+ wb.sheets.splice(opts.index, 0, ref);
297
+ }
298
+ return sheet;
299
+ }
300
+ /** Look up a Worksheet by title. Returns undefined for missing names or chartsheets. */
301
+ function getSheet(wb, title) {
302
+ for (const s of wb.sheets) if (s.kind === "worksheet" && s.sheet.title === title) return s.sheet;
303
+ }
304
+ /** Look up a Chartsheet by title. Returns undefined for missing names or worksheets. */
305
+ function getChartsheet(wb, title) {
306
+ for (const s of wb.sheets) if (s.kind === "chartsheet" && s.sheet.title === title) return s.sheet;
307
+ }
308
+ /** Add a Chartsheet to the Workbook. Returns the chartsheet for further population. */
309
+ function addChartsheet(wb, title, opts) {
310
+ validateUniqueTitle(wb, title);
311
+ const cs = makeChartsheet(title);
312
+ if (opts?.chart) cs.drawing = makeDrawing([makeChartDrawingItem(makeAbsoluteAnchor({
313
+ x: 0,
314
+ y: 0,
315
+ cx: 9144e3,
316
+ cy: 6858e3
317
+ }), opts.chart)]);
318
+ const ref = {
319
+ kind: "chartsheet",
320
+ sheet: cs,
321
+ sheetId: allocateSheetId(wb),
322
+ state: opts?.state ?? "visible"
323
+ };
324
+ if (opts?.index === void 0) wb.sheets.push(ref);
325
+ else {
326
+ if (opts.index < 0 || opts.index > wb.sheets.length) throw new OpenXmlSchemaError(`addChartsheet: index ${opts.index} out of range`);
327
+ wb.sheets.splice(opts.index, 0, ref);
328
+ }
329
+ return cs;
330
+ }
331
+ /** All worksheet titles, in display order. */
332
+ function sheetNames(wb) {
333
+ return wb.sheets.map((s) => s.sheet.title);
334
+ }
335
+ /** Remove a sheet by title. No-op if the title is not registered. */
336
+ function removeSheet(wb, title) {
337
+ const i = wb.sheets.findIndex((s) => s.sheet.title === title);
338
+ if (i < 0) return;
339
+ wb.sheets.splice(i, 1);
340
+ if (wb.activeSheetIndex >= wb.sheets.length) wb.activeSheetIndex = Math.max(0, wb.sheets.length - 1);
341
+ }
342
+ /** Set the active sheet by title; throws on unknown title. */
343
+ function setActiveSheet(wb, title) {
344
+ const i = wb.sheets.findIndex((s) => s.sheet.title === title);
345
+ if (i < 0) throw new OpenXmlSchemaError(`setActiveSheet: no sheet named "${title}"`);
346
+ wb.activeSheetIndex = i;
347
+ }
348
+ /**
349
+ * Rename a sheet from `oldTitle` to `newTitle`. Throws if no sheet matches
350
+ * `oldTitle`, or if `newTitle` collides with an existing sheet (Excel requires
351
+ * sheet names to be unique within a workbook).
352
+ */
353
+ function renameSheet(wb, oldTitle, newTitle) {
354
+ const i = wb.sheets.findIndex((s) => s.sheet.title === oldTitle);
355
+ if (i < 0) throw new OpenXmlSchemaError(`renameSheet: no sheet named "${oldTitle}"`);
356
+ if (oldTitle === newTitle) return;
357
+ validateUniqueTitle(wb, newTitle, i);
358
+ const ref = wb.sheets[i];
359
+ if (ref) ref.sheet.title = newTitle;
360
+ }
361
+ /**
362
+ * Set the visibility state on a sheet by title. Throws on unknown title.
363
+ * Refuses to hide the last visible sheet: an .xlsx with every sheet hidden
364
+ * fails to open in Excel ("Excel cannot use the object linking and embedding
365
+ * features because no sheet is visible"). Catching it here keeps the
366
+ * workbook recoverable instead of producing a save Excel will reject.
367
+ */
368
+ function setSheetState(wb, title, state) {
369
+ const ref = wb.sheets.find((s) => s.sheet.title === title);
370
+ if (!ref) throw new OpenXmlSchemaError(`setSheetState: no sheet named "${title}"`);
371
+ if (ref.state === state) return;
372
+ if (state !== "visible" && ref.state === "visible") {
373
+ let otherVisible = false;
374
+ for (const candidate of wb.sheets) if (candidate !== ref && candidate.state === "visible") {
375
+ otherVisible = true;
376
+ break;
377
+ }
378
+ if (!otherVisible) throw new OpenXmlSchemaError(`setSheetState: cannot hide "${title}" — it's the last visible sheet, and Excel refuses to open a workbook with every sheet hidden. Make another sheet visible first (or call showSheet()).`);
379
+ }
380
+ ref.state = state;
381
+ }
382
+ /** Look up the current visibility state. Throws on unknown title. */
383
+ function getSheetState(wb, title) {
384
+ const ref = wb.sheets.find((s) => s.sheet.title === title);
385
+ if (!ref) throw new OpenXmlSchemaError(`getSheetState: no sheet named "${title}"`);
386
+ return ref.state;
387
+ }
388
+ /**
389
+ * Move a sheet to a new tab-strip position. `toIndex` is clamped to `[0,
390
+ * sheets.length - 1]`. Adjusts `activeSheetIndex` so the same sheet stays
391
+ * active across the move.
392
+ */
393
+ function moveSheet(wb, title, toIndex) {
394
+ const from = wb.sheets.findIndex((s) => s.sheet.title === title);
395
+ if (from < 0) throw new OpenXmlSchemaError(`moveSheet: no sheet named "${title}"`);
396
+ if (!Number.isInteger(toIndex)) throw new OpenXmlSchemaError(`moveSheet: toIndex must be an integer; got ${toIndex}`);
397
+ const dest = Math.max(0, Math.min(wb.sheets.length - 1, toIndex));
398
+ if (from === dest) return;
399
+ const wasActive = wb.activeSheetIndex === from;
400
+ const [moved] = wb.sheets.splice(from, 1);
401
+ if (moved) wb.sheets.splice(dest, 0, moved);
402
+ if (wasActive) wb.activeSheetIndex = dest;
403
+ else {
404
+ let cur = wb.activeSheetIndex;
405
+ if (from < cur) cur -= 1;
406
+ if (dest <= cur) cur += 1;
407
+ wb.activeSheetIndex = Math.max(0, Math.min(wb.sheets.length - 1, cur));
408
+ }
409
+ }
410
+ function getWorkbookStats(wb) {
411
+ let worksheetCount = 0;
412
+ let chartsheetCount = 0;
413
+ let cellCount = 0;
414
+ let formulaCount = 0;
415
+ let commentCount = 0;
416
+ let hyperlinkCount = 0;
417
+ let mergedRangeCount = 0;
418
+ let tableCount = 0;
419
+ for (const ref of wb.sheets) if (ref.kind === "worksheet") {
420
+ worksheetCount++;
421
+ const ws = ref.sheet;
422
+ for (const rowMap of ws.rows.values()) for (const cell of rowMap.values()) {
423
+ cellCount++;
424
+ if (isFormulaValue(cell.value)) formulaCount++;
425
+ }
426
+ commentCount += ws.legacyComments.length;
427
+ hyperlinkCount += ws.hyperlinks.length;
428
+ mergedRangeCount += ws.mergedCells.length;
429
+ tableCount += ws.tables.length;
430
+ } else chartsheetCount++;
431
+ return {
432
+ worksheetCount,
433
+ chartsheetCount,
434
+ cellCount,
435
+ formulaCount,
436
+ commentCount,
437
+ hyperlinkCount,
438
+ mergedRangeCount,
439
+ tableCount,
440
+ definedNameCount: wb.definedNames.length,
441
+ customPropertyCount: wb.customProperties?.properties.length ?? 0
442
+ };
443
+ }
444
+ /**
445
+ * Workbook-wide value-kind histogram. Sums {@link countCellsByKind} across
446
+ * every Worksheet (chartsheets contribute no cells). Buckets have the same
447
+ * shape as the per-worksheet result; an empty workbook returns all-zero counts.
448
+ */
449
+ function getWorkbookCellsByKind(wb) {
450
+ const out = {
451
+ null: 0,
452
+ string: 0,
453
+ number: 0,
454
+ boolean: 0,
455
+ date: 0,
456
+ duration: 0,
457
+ error: 0,
458
+ "rich-text": 0,
459
+ formula: 0
460
+ };
461
+ for (const ws of iterWorksheets(wb)) {
462
+ const partial = countCellsByKind(ws);
463
+ out.null += partial.null;
464
+ out.string += partial.string;
465
+ out.number += partial.number;
466
+ out.boolean += partial.boolean;
467
+ out.date += partial.date;
468
+ out.duration += partial.duration;
469
+ out.error += partial.error;
470
+ out["rich-text"] += partial["rich-text"];
471
+ out.formula += partial.formula;
472
+ }
473
+ return out;
474
+ }
475
+ /**
476
+ * Resolve a sheet-qualified A1 address (`'Sheet1!A1'`) to its Cell, or
477
+ * `undefined` when the cell isn't materialised. Throws on malformed addresses,
478
+ * missing sheets, or range inputs.
479
+ */
480
+ function getCellAtAddress(wb, address) {
481
+ const { sheet: sheetTitle, range } = parseSheetRange(address);
482
+ if (range.includes(":")) throw new OpenXmlSchemaError(`getCellAtAddress: address "${address}" refers to a range, not a single cell`);
483
+ const ws = getSheet(wb, sheetTitle);
484
+ if (!ws) throw new OpenXmlSchemaError(`getCellAtAddress: sheet "${sheetTitle}" not found`);
485
+ const { col, row } = coordinateToTuple(range);
486
+ return getCell(ws, row, col);
487
+ }
488
+ /**
489
+ * Set a single cell by sheet-qualified A1 address. Throws on malformed
490
+ * addresses, missing sheets, or range inputs.
491
+ */
492
+ function setCellAtAddress(wb, address, value) {
493
+ const { sheet: sheetTitle, range } = parseSheetRange(address);
494
+ if (range.includes(":")) throw new OpenXmlSchemaError(`setCellAtAddress: address "${address}" refers to a range, not a single cell`);
495
+ const ws = getSheet(wb, sheetTitle);
496
+ if (!ws) throw new OpenXmlSchemaError(`setCellAtAddress: sheet "${sheetTitle}" not found`);
497
+ return setCellByCoord(ws, range, value);
498
+ }
499
+ function describeWorkbook(wb) {
500
+ let worksheetCount = 0;
501
+ let chartsheetCount = 0;
502
+ let cellCount = 0;
503
+ let formulaCount = 0;
504
+ let commentCount = 0;
505
+ let hyperlinkCount = 0;
506
+ let mergedRangeCount = 0;
507
+ let tableCount = 0;
508
+ const cellsByKind = {
509
+ null: 0,
510
+ string: 0,
511
+ number: 0,
512
+ boolean: 0,
513
+ date: 0,
514
+ duration: 0,
515
+ error: 0,
516
+ "rich-text": 0,
517
+ formula: 0
518
+ };
519
+ const sheets = wb.sheets.map((ref) => {
520
+ if (ref.kind === "chartsheet") {
521
+ chartsheetCount++;
522
+ return {
523
+ title: ref.sheet.title,
524
+ kind: "chartsheet",
525
+ state: ref.state,
526
+ cellCount: 0,
527
+ formulaCount: 0,
528
+ tableCount: 0,
529
+ drawingItemCount: ref.sheet.drawing?.items.length ?? 0
530
+ };
531
+ }
532
+ worksheetCount++;
533
+ const ws = ref.sheet;
534
+ let sheetCellCount = 0;
535
+ let sheetFormulaCount = 0;
536
+ for (const rowMap of ws.rows.values()) for (const cell of rowMap.values()) {
537
+ sheetCellCount++;
538
+ const bucket = classifyCellValue(cell.value);
539
+ cellsByKind[bucket]++;
540
+ if (isFormulaValue(cell.value)) sheetFormulaCount++;
541
+ }
542
+ cellCount += sheetCellCount;
543
+ formulaCount += sheetFormulaCount;
544
+ commentCount += ws.legacyComments.length;
545
+ hyperlinkCount += ws.hyperlinks.length;
546
+ mergedRangeCount += ws.mergedCells.length;
547
+ tableCount += ws.tables.length;
548
+ return {
549
+ title: ws.title,
550
+ kind: "worksheet",
551
+ state: ref.state,
552
+ cellCount: sheetCellCount,
553
+ formulaCount: sheetFormulaCount,
554
+ tableCount: ws.tables.length,
555
+ drawingItemCount: ws.drawing?.items.length ?? 0
556
+ };
557
+ });
558
+ return {
559
+ worksheetCount,
560
+ chartsheetCount,
561
+ cellCount,
562
+ formulaCount,
563
+ commentCount,
564
+ hyperlinkCount,
565
+ mergedRangeCount,
566
+ tableCount,
567
+ definedNameCount: wb.definedNames.length,
568
+ customPropertyCount: wb.customProperties?.properties.length ?? 0,
569
+ cellsByKind,
570
+ sheets
571
+ };
572
+ }
573
+ function getCellSummary(wb, sheetTitle, ref) {
574
+ const ws = getSheet(wb, sheetTitle);
575
+ if (!ws) throw new OpenXmlSchemaError(`getCellSummary: sheet "${sheetTitle}" not found`);
576
+ const { col, row } = coordinateToTuple(ref);
577
+ const cell = getCell(ws, row, col);
578
+ const probe = cell ?? {
579
+ row,
580
+ col,
581
+ value: null,
582
+ styleId: 0
583
+ };
584
+ const merged = getMergedRangeAt(ws, row, col);
585
+ const inTables = [];
586
+ for (const t of ws.tables) if (rangeContainsCell(parseRange(t.ref), row, col)) inTables.push(t.displayName);
587
+ let inDv = 0;
588
+ for (const dv of ws.dataValidations) if (multiCellRangeContainsCell(dv.sqref, row, col)) inDv++;
589
+ let inCf = 0;
590
+ for (const cf of ws.conditionalFormatting) if (multiCellRangeContainsCell(cf.sqref, row, col)) inCf++;
591
+ return {
592
+ ref,
593
+ sheet: sheetTitle,
594
+ exists: cell !== void 0,
595
+ value: cell?.value,
596
+ styleId: probe.styleId,
597
+ font: getCellFont(wb, probe),
598
+ fill: getCellFill(wb, probe),
599
+ border: getCellBorder(wb, probe),
600
+ alignment: getCellAlignment(wb, probe),
601
+ protection: getCellProtection(wb, probe),
602
+ numberFormat: getCellNumberFormat(wb, probe),
603
+ hyperlink: cell ? getCellHyperlink(ws, cell) : void 0,
604
+ comment: cell ? getCellComment(ws, cell) : void 0,
605
+ mergedRange: merged ? rangeToString(merged) : void 0,
606
+ inTables,
607
+ inDataValidations: inDv,
608
+ inConditionalFormatting: inCf
609
+ };
610
+ }
611
+ /**
612
+ * Iterate over every Worksheet in the workbook (skips chartsheets). Yields each
613
+ * worksheet in tab-strip order.
614
+ */
615
+ function* iterWorksheets(wb) {
616
+ for (const ref of wb.sheets) if (ref.kind === "worksheet") yield ref.sheet;
617
+ }
618
+ /** Currently active sheet (worksheet only), or undefined if the active slot is empty or a chartsheet. */
619
+ function getActiveSheet(wb) {
620
+ const ref = wb.sheets[wb.activeSheetIndex];
621
+ return ref?.kind === "worksheet" ? ref.sheet : void 0;
622
+ }
623
+ /** Read-only view onto the customXml/* pass-through parts. */
624
+ function listCustomXmlParts(wb) {
625
+ if (!wb.passthrough) return [];
626
+ const out = [];
627
+ for (const [path, content] of wb.passthrough) if (path.startsWith("customXml/")) out.push({
628
+ path,
629
+ content
630
+ });
631
+ return out;
632
+ }
633
+ //#endregion
634
+ export { sharedStringsToBytes as A, addSharedString as C, parseSharedStringsXml as D, makeSharedStrings as E, serializeRichTextRuns as O, validateSheetTitle as S, getSharedStringIndex as T, renameSheet as _, getActiveSheet as a, setSheetState as b, getChartsheet as c, getWorkbookCellsByKind as d, getWorkbookStats as f, removeSheet as g, moveSheet as h, describeWorkbook as i, sharedStringCount as k, getSheet as l, listCustomXmlParts as m, addWorksheet as n, getCellAtAddress as o, iterWorksheets as p, createWorkbook as r, getCellSummary as s, addChartsheet as t, getSheetState as u, setActiveSheet as v, getSharedStringAt as w, sheetNames as x, setCellAtAddress as y };
635
+
636
+ //# sourceMappingURL=workbook-HGYNRBlV.mjs.map