@rowsncolumns/toolkit 24.4.3 → 24.4.4

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 (86) hide show
  1. package/dist/cjs/excel-parser/interface.d.ts +5 -1
  2. package/dist/cjs/excel-parser/interface.d.ts.map +1 -1
  3. package/dist/cjs/excel-parser/plugins/base/index.d.ts +2 -0
  4. package/dist/cjs/excel-parser/plugins/base/index.d.ts.map +1 -1
  5. package/dist/cjs/excel-parser/plugins/base/index.js +3 -0
  6. package/dist/cjs/excel-parser/plugins/xls/index.d.ts +55 -9
  7. package/dist/cjs/excel-parser/plugins/xls/index.d.ts.map +1 -1
  8. package/dist/cjs/excel-parser/plugins/xls/index.js +487 -24
  9. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  10. package/dist/cjs/excel-parser/plugins/xlsb/index.js +12 -5
  11. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  12. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  13. package/dist/cjs/excel-parser/plugins/xlsx/chartex.js +244 -0
  14. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  15. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  16. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.js +295 -0
  17. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +9 -1
  18. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  19. package/dist/cjs/excel-parser/plugins/xlsx/index.js +251 -104
  20. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  21. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  22. package/dist/cjs/excel-parser/plugins/xlsx/styles.js +90 -4
  23. package/dist/cjs/excel-parser/registry.d.ts +7 -0
  24. package/dist/cjs/excel-parser/registry.d.ts.map +1 -1
  25. package/dist/cjs/excel-parser/registry.js +28 -1
  26. package/dist/cjs/excel-parser/types.d.ts +10 -1
  27. package/dist/cjs/excel-parser/types.d.ts.map +1 -1
  28. package/dist/cjs/excel-parser/workbook.d.ts +2 -0
  29. package/dist/cjs/excel-parser/workbook.d.ts.map +1 -1
  30. package/dist/cjs/excel-parser/workbook.js +20 -14
  31. package/dist/cjs/excel-parser/worker.js +128 -130
  32. package/dist/cjs/exporter/xlsx/chart-builder.d.ts.map +1 -1
  33. package/dist/cjs/exporter/xlsx/chart-builder.js +5 -33
  34. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts +36 -0
  35. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  36. package/dist/cjs/exporter/xlsx/chartex-builder.js +109 -0
  37. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts +61 -0
  38. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  39. package/dist/cjs/exporter/xlsx/form-controls-builder.js +197 -0
  40. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  41. package/dist/cjs/exporter/xlsx/xlsx-export.js +431 -193
  42. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  43. package/dist/esm/excel-parser/interface.d.ts +5 -1
  44. package/dist/esm/excel-parser/interface.d.ts.map +1 -1
  45. package/dist/esm/excel-parser/plugins/base/index.d.ts +2 -0
  46. package/dist/esm/excel-parser/plugins/base/index.d.ts.map +1 -1
  47. package/dist/esm/excel-parser/plugins/base/index.js +3 -0
  48. package/dist/esm/excel-parser/plugins/xls/index.d.ts +55 -9
  49. package/dist/esm/excel-parser/plugins/xls/index.d.ts.map +1 -1
  50. package/dist/esm/excel-parser/plugins/xls/index.js +429 -23
  51. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  52. package/dist/esm/excel-parser/plugins/xlsb/index.js +10 -3
  53. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  54. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  55. package/dist/esm/excel-parser/plugins/xlsx/chartex.js +199 -0
  56. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  57. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  58. package/dist/esm/excel-parser/plugins/xlsx/form-controls.js +246 -0
  59. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +9 -1
  60. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  61. package/dist/esm/excel-parser/plugins/xlsx/index.js +92 -6
  62. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  63. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  64. package/dist/esm/excel-parser/plugins/xlsx/styles.js +80 -0
  65. package/dist/esm/excel-parser/registry.d.ts +7 -0
  66. package/dist/esm/excel-parser/registry.d.ts.map +1 -1
  67. package/dist/esm/excel-parser/registry.js +18 -1
  68. package/dist/esm/excel-parser/types.d.ts +10 -1
  69. package/dist/esm/excel-parser/types.d.ts.map +1 -1
  70. package/dist/esm/excel-parser/workbook.d.ts +2 -0
  71. package/dist/esm/excel-parser/workbook.d.ts.map +1 -1
  72. package/dist/esm/excel-parser/workbook.js +16 -10
  73. package/dist/esm/excel-parser/worker.js +10 -18
  74. package/dist/esm/exporter/xlsx/chart-builder.d.ts.map +1 -1
  75. package/dist/esm/exporter/xlsx/chart-builder.js +0 -28
  76. package/dist/esm/exporter/xlsx/chartex-builder.d.ts +36 -0
  77. package/dist/esm/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  78. package/dist/esm/exporter/xlsx/chartex-builder.js +97 -0
  79. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts +61 -0
  80. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  81. package/dist/esm/exporter/xlsx/form-controls-builder.js +173 -0
  82. package/dist/esm/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  83. package/dist/esm/exporter/xlsx/xlsx-export.js +228 -19
  84. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  85. package/package.json +3 -3
  86. package/xlsx.d.ts +14 -0
@@ -0,0 +1,244 @@
1
+ import { __assign, __awaiter, __generator, __read, __spreadArray, __values } from "tslib";
2
+ import { generateSelectionsFromFormula, uuid } from "@rowsncolumns/utils";
3
+ import { get } from "lodash-es";
4
+ import { extractChartPosition, } from "./charts";
5
+ /**
6
+ * Excel 2016+ "chartex" charts (`xl/charts/chartEx{N}.xml`, namespace
7
+ * `http://schemas.microsoft.com/office/drawing/2014/chartex`): treemap,
8
+ * sunburst, histogram / pareto, box & whisker, waterfall, funnel. They are
9
+ * anchored through an `mc:AlternateContent` whose `Choice` graphic frame
10
+ * carries `<cx:chart r:id>` instead of `<c:chart>`, and their data lives in
11
+ * `<cx:chartData><cx:data>` dimensions (`strDim type="cat"` for the
12
+ * hierarchy, `numDim type="size"|"val"` for the numbers) referenced by the
13
+ * series through `<cx:dataId>`.
14
+ *
15
+ * The exporter counterpart is `exporter/xlsx/chartex-builder.ts`.
16
+ */
17
+ export var CHART_EX_REL_TYPE = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
18
+ export var CHART_EX_GRAPHIC_URI = "http://schemas.microsoft.com/office/drawing/2014/chartex";
19
+ var asArray = function (value) {
20
+ return value == null ? [] : Array.isArray(value) ? value : [value];
21
+ };
22
+ /** Read a child by local name, tolerating any namespace prefix. */
23
+ var child = function (node, localName) {
24
+ var e_1, _a;
25
+ if (!node || typeof node !== "object")
26
+ return undefined;
27
+ if (node[localName] !== undefined)
28
+ return node[localName];
29
+ try {
30
+ for (var _b = __values(Object.keys(node)), _c = _b.next(); !_c.done; _c = _b.next()) {
31
+ var key = _c.value;
32
+ var colon = key.indexOf(":");
33
+ if (colon >= 0 && key.slice(colon + 1) === localName)
34
+ return node[key];
35
+ }
36
+ }
37
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
38
+ finally {
39
+ try {
40
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
41
+ }
42
+ finally { if (e_1) throw e_1.error; }
43
+ }
44
+ return undefined;
45
+ };
46
+ var textOf = function (node) {
47
+ if (node == null)
48
+ return undefined;
49
+ if (typeof node === "object") {
50
+ var inner = node.t$;
51
+ return inner == null ? undefined : String(inner);
52
+ }
53
+ return String(node);
54
+ };
55
+ /**
56
+ * `<cx:chart r:id>` inside an anchor's `mc:AlternateContent` choice (Excel
57
+ * also writes a plain `xdr:graphicFrame` for some producers — both forms are
58
+ * checked). Returns the `cx:chart` node or undefined for non-chartex anchors.
59
+ */
60
+ export function getChartExReferenceFromAnchor(anchor) {
61
+ var e_2, _a, e_3, _b, e_4, _c;
62
+ var frames = [];
63
+ try {
64
+ for (var _d = __values(asArray(child(anchor, "AlternateContent"))), _e = _d.next(); !_e.done; _e = _d.next()) {
65
+ var alternate = _e.value;
66
+ try {
67
+ for (var _f = (e_3 = void 0, __values(asArray(child(alternate, "Choice")))), _g = _f.next(); !_g.done; _g = _f.next()) {
68
+ var choice = _g.value;
69
+ frames.push.apply(frames, __spreadArray([], __read(asArray(child(choice, "graphicFrame"))), false));
70
+ }
71
+ }
72
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
73
+ finally {
74
+ try {
75
+ if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
76
+ }
77
+ finally { if (e_3) throw e_3.error; }
78
+ }
79
+ }
80
+ }
81
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
82
+ finally {
83
+ try {
84
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
85
+ }
86
+ finally { if (e_2) throw e_2.error; }
87
+ }
88
+ frames.push.apply(frames, __spreadArray([], __read(asArray(child(anchor, "graphicFrame"))), false));
89
+ try {
90
+ for (var frames_1 = __values(frames), frames_1_1 = frames_1.next(); !frames_1_1.done; frames_1_1 = frames_1.next()) {
91
+ var frame = frames_1_1.value;
92
+ var graphicData = child(child(frame, "graphic"), "graphicData");
93
+ if (!graphicData)
94
+ continue;
95
+ var uri = get(graphicData, "a$.uri");
96
+ var cxChart = child(graphicData, "chart");
97
+ if (uri === CHART_EX_GRAPHIC_URI && cxChart)
98
+ return cxChart;
99
+ // A `cx:`-prefixed chart element without the uri attribute (defensive).
100
+ if (cxChart && Object.keys(graphicData).some(function (k) { return k.startsWith("cx:"); })) {
101
+ return cxChart;
102
+ }
103
+ }
104
+ }
105
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
106
+ finally {
107
+ try {
108
+ if (frames_1_1 && !frames_1_1.done && (_c = frames_1.return)) _c.call(frames_1);
109
+ }
110
+ finally { if (e_4) throw e_4.error; }
111
+ }
112
+ return undefined;
113
+ }
114
+ /** `layoutId` → engine chart type. Unknown layouts are not imported. */
115
+ var CHART_TYPE_BY_LAYOUT = {
116
+ treemap: "treemap",
117
+ sunburst: "sunburst",
118
+ waterfall: "waterfall",
119
+ funnel: "funnel",
120
+ boxWhisker: "boxplot",
121
+ // `clusteredColumn` is a histogram / pareto only when it carries `<cx:binning>`.
122
+ };
123
+ var sourcesFromRef = function (ref, hostSheetId, resolveSheetId) {
124
+ if (!ref)
125
+ return [];
126
+ var selections = generateSelectionsFromFormula("=".concat(ref));
127
+ return selections.map(function (sel) {
128
+ var _a;
129
+ return (__assign(__assign({}, sel.range), { sheetId: (_a = (sel.sheetName ? resolveSheetId === null || resolveSheetId === void 0 ? void 0 : resolveSheetId(sel.sheetName) : undefined)) !== null && _a !== void 0 ? _a : hostSheetId }));
130
+ });
131
+ };
132
+ var chartData = function (sources) {
133
+ return ({ sources: sources });
134
+ };
135
+ /**
136
+ * Split a multi-column hierarchy range (Excel lays the treemap hierarchy out
137
+ * as columns, top level first, leaf last) into `parentLabels` (one entry per
138
+ * parent column) and `labels` (the leaf column).
139
+ */
140
+ export var splitHierarchyRange = function (range) {
141
+ var parentLabels = [];
142
+ for (var c = range.startColumnIndex; c < range.endColumnIndex; c++) {
143
+ parentLabels.push(__assign(__assign({}, range), { startColumnIndex: c, endColumnIndex: c }));
144
+ }
145
+ return {
146
+ parentLabels: parentLabels,
147
+ labels: __assign(__assign({}, range), { startColumnIndex: range.endColumnIndex, endColumnIndex: range.endColumnIndex }),
148
+ };
149
+ };
150
+ var dimensionRef = function (data, dimTag, type) {
151
+ var _a, _b;
152
+ var dims = asArray(child(data, dimTag)).filter(function (dim) { return get(dim, "a$.type") === type; });
153
+ var dim = (_a = dims[0]) !== null && _a !== void 0 ? _a : (dimTag === "numDim" ? asArray(child(data, dimTag))[0] : undefined);
154
+ var f = child(dim, "f");
155
+ return ((_b = textOf(Array.isArray(f) ? f[0] : f)) === null || _b === void 0 ? void 0 : _b.trim()) || undefined;
156
+ };
157
+ /** Parse a `cx:chartSpace` DOM into an `EmbeddedChart` spec (null when unsupported). */
158
+ export function parseChartExSpec(chartSpaceDom, sheetId, resolveSheetId) {
159
+ var _a, _b, _c, _d, _e;
160
+ var chartSpace = (_a = child(chartSpaceDom, "chartSpace")) !== null && _a !== void 0 ? _a : chartSpaceDom;
161
+ var chart = child(chartSpace, "chart");
162
+ if (!chart)
163
+ return null;
164
+ var region = child(child(chart, "plotArea"), "plotAreaRegion");
165
+ var series = asArray(child(region, "series"))[0];
166
+ if (!series)
167
+ return null;
168
+ var layoutId = String((_b = get(series, "a$.layoutId")) !== null && _b !== void 0 ? _b : "");
169
+ // Excel nests `<cx:binning>` in `<cx:layoutPr>`; tolerate it directly on the series too.
170
+ var binning = (_c = child(child(series, "layoutPr"), "binning")) !== null && _c !== void 0 ? _c : child(series, "binning");
171
+ var chartType = layoutId === "clusteredColumn" && binning
172
+ ? "histogram"
173
+ : CHART_TYPE_BY_LAYOUT[layoutId];
174
+ if (!chartType)
175
+ return null;
176
+ var dataId = String((_d = get(child(series, "dataId"), "a$.val")) !== null && _d !== void 0 ? _d : "0");
177
+ var data = (_e = asArray(child(child(chartSpace, "chartData"), "data")).find(function (d) { return String(get(d, "a$.id")) === dataId; })) !== null && _e !== void 0 ? _e : asArray(child(child(chartSpace, "chartData"), "data"))[0];
178
+ if (!data)
179
+ return null;
180
+ var title = textOf(child(child(child(child(chart, "title"), "tx"), "txData"), "v"));
181
+ var catRef = dimensionRef(data, "strDim", "cat");
182
+ var catSources = sourcesFromRef(catRef, sheetId, resolveSheetId);
183
+ if (chartType === "treemap" || chartType === "sunburst") {
184
+ var sizeRef = dimensionRef(data, "numDim", "size");
185
+ var sizeSources = sourcesFromRef(sizeRef, sheetId, resolveSheetId);
186
+ if (!catSources.length || !sizeSources.length)
187
+ return null;
188
+ var hierarchy = splitHierarchyRange(catSources[0]);
189
+ return __assign(__assign({ chartType: chartType }, (title ? { title: title } : {})), { labels: [chartData([hierarchy.labels])], parentLabels: hierarchy.parentLabels.map(function (range) { return chartData([range]); }), sizeData: [chartData(sizeSources)] });
190
+ }
191
+ var valRef = dimensionRef(data, "numDim", "val");
192
+ var valSources = sourcesFromRef(valRef, sheetId, resolveSheetId);
193
+ if (!valSources.length)
194
+ return null;
195
+ var spec = __assign(__assign(__assign({ chartType: chartType }, (title ? { title: title } : {})), { series: [chartData(valSources)] }), (catSources.length ? { domains: [chartData(catSources)] } : {}));
196
+ if (chartType === "histogram") {
197
+ var binCount = Number(get(child(binning, "binCount"), "a$.val"));
198
+ if (Number.isFinite(binCount) && binCount > 0)
199
+ spec.binCount = binCount;
200
+ }
201
+ return spec;
202
+ }
203
+ /** Resolve + parse one chartex part referenced from a drawing anchor. */
204
+ export function processChartEx(chartTarget, drawingPath, anchor, sheetId, zipParser, xmlParser, sheetDimensions, resolveSheetId) {
205
+ return __awaiter(this, void 0, void 0, function () {
206
+ var chartPath, drawingDir, content, _a, spec, position;
207
+ return __generator(this, function (_b) {
208
+ switch (_b.label) {
209
+ case 0:
210
+ chartPath = chartTarget;
211
+ drawingDir = drawingPath.substring(0, drawingPath.lastIndexOf("/"));
212
+ if (chartPath.startsWith("/")) {
213
+ chartPath = chartPath.slice(1);
214
+ }
215
+ else if (chartPath.startsWith("../")) {
216
+ chartPath = "xl/".concat(chartPath.replace("../", ""));
217
+ }
218
+ else if (!chartPath.startsWith("xl/")) {
219
+ chartPath = "".concat(drawingDir, "/").concat(chartPath);
220
+ }
221
+ _b.label = 1;
222
+ case 1:
223
+ _b.trys.push([1, 3, , 4]);
224
+ return [4 /*yield*/, zipParser.getText(chartPath)];
225
+ case 2:
226
+ content = _b.sent();
227
+ return [3 /*break*/, 4];
228
+ case 3:
229
+ _a = _b.sent();
230
+ return [2 /*return*/, null];
231
+ case 4:
232
+ if (!content)
233
+ return [2 /*return*/, null];
234
+ spec = parseChartExSpec(xmlParser.parse(content), sheetId, resolveSheetId);
235
+ if (!spec)
236
+ return [2 /*return*/, null];
237
+ position = extractChartPosition(anchor, sheetId, sheetDimensions);
238
+ if (!position)
239
+ return [2 /*return*/, null];
240
+ return [2 /*return*/, { chartId: uuid(), spec: spec, position: position }];
241
+ }
242
+ });
243
+ });
244
+ }
@@ -0,0 +1,70 @@
1
+ import type { EmbeddedObject } from "@rowsncolumns/spreadsheet";
2
+ export declare const CTRL_PROP_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp";
3
+ export declare const VML_DRAWING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";
4
+ type CellAnchor = {
5
+ col: number;
6
+ colOff: number;
7
+ row: number;
8
+ rowOff: number;
9
+ };
10
+ /**
11
+ * `<controlPr><anchor><from>…</from><to>…</to></anchor>` → the engine's
12
+ * pixel overlay position (1-based anchor cell, EMU offsets → px, size from
13
+ * the cell span at the grid defaults — the same approximation the drawing
14
+ * importer uses for `twoCellAnchor`s).
15
+ */
16
+ export declare const controlAnchorToOverlayPosition: (from: CellAnchor, to: CellAnchor | undefined) => {
17
+ anchorCell: {
18
+ rowIndex: number;
19
+ columnIndex: number;
20
+ };
21
+ offsetXPixels?: number;
22
+ offsetYPixels?: number;
23
+ widthPixels?: number;
24
+ heightPixels?: number;
25
+ };
26
+ /**
27
+ * Parse an `xl/ctrlProps/ctrlPropN.xml` part: `objectType`, every other
28
+ * `formControlPr` attribute verbatim, and the literal `itemLst` items.
29
+ */
30
+ export declare const parseFormControlPr: (ctrlPropDom: any) => {
31
+ objectType: string;
32
+ properties: Record<string, string>;
33
+ listItems?: string[];
34
+ } | undefined;
35
+ /**
36
+ * Captions live only in the legacy VML part: `<v:shape id="_x0000_s1025">
37
+ * … <v:textbox><div>Check Box 1</div></v:textbox>`. Returns shapeId → text.
38
+ * VML is scanned textually — Excel's VML is not reliably well-formed XML.
39
+ */
40
+ export declare const parseVmlControlCaptions: (vml: string | undefined) => Map<number, string>;
41
+ export type RawWorksheetControl = {
42
+ shapeId?: number;
43
+ name?: string;
44
+ relId?: string;
45
+ controlProperties: Record<string, string>;
46
+ moveWithCells?: boolean;
47
+ sizeWithCells?: boolean;
48
+ from?: CellAnchor;
49
+ to?: CellAnchor;
50
+ };
51
+ /**
52
+ * `<controls>` from a worksheet DOM, whether wrapped in
53
+ * `<mc:AlternateContent><mc:Choice Requires="x14">` (Excel) or bare.
54
+ */
55
+ export declare const readWorksheetControls: (sheetDom: any) => RawWorksheetControl[];
56
+ /**
57
+ * Assemble the sheet's form controls. `loadCtrlProp` resolves a control's
58
+ * `r:id` to its parsed `ctrlProp` DOM (undefined when the part is missing —
59
+ * the control is then skipped, Excel would repair it the same way).
60
+ */
61
+ export declare const buildFormControlEmbeds: ({ controls, sheetId, ctrlProps, captions, }: {
62
+ controls: RawWorksheetControl[];
63
+ sheetId: number;
64
+ ctrlProps: Map<string, ReturnType<typeof parseFormControlPr>>;
65
+ captions: Map<number, string>;
66
+ }) => EmbeddedObject[];
67
+ /** The `r:id` of a worksheet's `<legacyDrawing>` (VML part), if any. */
68
+ export declare const readLegacyDrawingRelId: (sheetDom: any) => string | undefined;
69
+ export {};
70
+ //# sourceMappingURL=form-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-controls.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/form-controls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,cAAc,EACf,MAAM,2BAA2B,CAAC;AAgBnC,eAAO,MAAM,kBAAkB,iFACiD,CAAC;AACjF,eAAO,MAAM,oBAAoB,mFACiD,CAAC;AA6CnF,KAAK,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAe/E;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GACzC,MAAM,UAAU,EAChB,IAAI,UAAU,GAAG,SAAS;gBAKZ;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE;oBACrC,MAAM;oBACN,MAAM;kBACR,MAAM;mBACL,MAAM;CAiBxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,aAAa,GAAG,KACf;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GAAG,SAkBH,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,MAAM,GAAG,SAAS,KACtB,GAAG,CAAC,MAAM,EAAE,MAAM,CAwBpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU,GAAG,KAAG,mBAAmB,EA+BxE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,6CAKpC;IACD,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC;IAC9D,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,KAAG,cAAc,EA+BjB,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,GAAI,UAAU,GAAG,KAAG,MAAM,GAAG,SAK/D,CAAC"}
@@ -0,0 +1,295 @@
1
+ import { __assign, __read, __rest, __spreadArray, __values } from "tslib";
2
+ /**
3
+ * Excel form controls (`<controls>` in the worksheet + `xl/ctrlProps/*` +
4
+ * the legacy VML shape). Parsed into `EmbeddedObject`s with an
5
+ * {@link EmbedFormControlSpec} so the exporter can write the same three
6
+ * parts back (`exporter/xlsx/form-controls-builder.ts`). The grid does not
7
+ * run the control; the spec is a faithful, opaque carrier of what Excel
8
+ * stored.
9
+ */
10
+ var EMU_PER_PIXEL = 9525;
11
+ /** Grid defaults used to size a control from its cell-span anchor. */
12
+ var DEFAULT_COLUMN_WIDTH_PX = 100;
13
+ var DEFAULT_ROW_HEIGHT_PX = 20;
14
+ export var CTRL_PROP_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp";
15
+ export var VML_DRAWING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";
16
+ var asArray = function (value) {
17
+ return value == null ? [] : Array.isArray(value) ? value : [value];
18
+ };
19
+ /** Read a child by local name, tolerating any namespace prefix. */
20
+ var childByLocalName = function (node, localName) {
21
+ var e_1, _a;
22
+ if (!node || typeof node !== "object")
23
+ return undefined;
24
+ if (node[localName] !== undefined)
25
+ return node[localName];
26
+ try {
27
+ for (var _b = __values(Object.keys(node)), _c = _b.next(); !_c.done; _c = _b.next()) {
28
+ var key = _c.value;
29
+ var colon = key.indexOf(":");
30
+ if (colon >= 0 && key.slice(colon + 1) === localName) {
31
+ return node[key];
32
+ }
33
+ }
34
+ }
35
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
36
+ finally {
37
+ try {
38
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
39
+ }
40
+ finally { if (e_1) throw e_1.error; }
41
+ }
42
+ return undefined;
43
+ };
44
+ /** Text of a leaf element (`t$` when it carries attributes, else the value). */
45
+ var textOf = function (node) {
46
+ if (node == null)
47
+ return undefined;
48
+ if (typeof node === "object") {
49
+ var inner = node.t$;
50
+ return inner == null ? undefined : String(inner);
51
+ }
52
+ return String(node);
53
+ };
54
+ var numberOf = function (node) {
55
+ var text = textOf(node);
56
+ var value = text == null ? Number.NaN : Number(text);
57
+ return Number.isFinite(value) ? value : 0;
58
+ };
59
+ var attrs = function (node) {
60
+ var e_2, _a;
61
+ var raw = node === null || node === void 0 ? void 0 : node.a$;
62
+ var out = {};
63
+ if (!raw || typeof raw !== "object")
64
+ return out;
65
+ try {
66
+ for (var _b = __values(Object.entries(raw)), _c = _b.next(); !_c.done; _c = _b.next()) {
67
+ var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
68
+ if (value == null)
69
+ continue;
70
+ out[key] = String(value);
71
+ }
72
+ }
73
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
74
+ finally {
75
+ try {
76
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
77
+ }
78
+ finally { if (e_2) throw e_2.error; }
79
+ }
80
+ return out;
81
+ };
82
+ var readCellAnchor = function (node) {
83
+ if (!node)
84
+ return undefined;
85
+ var col = childByLocalName(node, "col");
86
+ var row = childByLocalName(node, "row");
87
+ if (col === undefined || row === undefined)
88
+ return undefined;
89
+ return {
90
+ col: numberOf(col),
91
+ colOff: numberOf(childByLocalName(node, "colOff")),
92
+ row: numberOf(row),
93
+ rowOff: numberOf(childByLocalName(node, "rowOff")),
94
+ };
95
+ };
96
+ /**
97
+ * `<controlPr><anchor><from>…</from><to>…</to></anchor>` → the engine's
98
+ * pixel overlay position (1-based anchor cell, EMU offsets → px, size from
99
+ * the cell span at the grid defaults — the same approximation the drawing
100
+ * importer uses for `twoCellAnchor`s).
101
+ */
102
+ export var controlAnchorToOverlayPosition = function (from, to) {
103
+ var offsetXPixels = Math.round(from.colOff / EMU_PER_PIXEL);
104
+ var offsetYPixels = Math.round(from.rowOff / EMU_PER_PIXEL);
105
+ var overlay = {
106
+ anchorCell: { rowIndex: from.row + 1, columnIndex: from.col + 1 },
107
+ };
108
+ if (offsetXPixels)
109
+ overlay.offsetXPixels = offsetXPixels;
110
+ if (offsetYPixels)
111
+ overlay.offsetYPixels = offsetYPixels;
112
+ if (to) {
113
+ var width = (to.col - from.col) * DEFAULT_COLUMN_WIDTH_PX +
114
+ (to.colOff - from.colOff) / EMU_PER_PIXEL;
115
+ var height = (to.row - from.row) * DEFAULT_ROW_HEIGHT_PX +
116
+ (to.rowOff - from.rowOff) / EMU_PER_PIXEL;
117
+ if (width > 0)
118
+ overlay.widthPixels = Math.round(width);
119
+ if (height > 0)
120
+ overlay.heightPixels = Math.round(height);
121
+ }
122
+ return overlay;
123
+ };
124
+ /**
125
+ * Parse an `xl/ctrlProps/ctrlPropN.xml` part: `objectType`, every other
126
+ * `formControlPr` attribute verbatim, and the literal `itemLst` items.
127
+ */
128
+ export var parseFormControlPr = function (ctrlPropDom) {
129
+ var e_3, _a;
130
+ var root = childByLocalName(ctrlPropDom, "formControlPr");
131
+ if (!root)
132
+ return undefined;
133
+ var _b = attrs(root), objectType = _b.objectType, properties = __rest(_b, ["objectType"]);
134
+ if (!objectType)
135
+ return undefined;
136
+ try {
137
+ // Namespace declarations ride along as attributes in fast-xml-parser.
138
+ for (var _c = __values(Object.keys(properties)), _d = _c.next(); !_d.done; _d = _c.next()) {
139
+ var key = _d.value;
140
+ if (key === "xmlns" || key.startsWith("xmlns:"))
141
+ delete properties[key];
142
+ }
143
+ }
144
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
145
+ finally {
146
+ try {
147
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
148
+ }
149
+ finally { if (e_3) throw e_3.error; }
150
+ }
151
+ var itemLst = childByLocalName(root, "itemLst");
152
+ var listItems = asArray(childByLocalName(itemLst, "item"))
153
+ .map(function (item) { return attrs(item).val; })
154
+ .filter(function (val) { return typeof val === "string"; });
155
+ return __assign({ objectType: objectType, properties: properties }, (listItems.length ? { listItems: listItems } : {}));
156
+ };
157
+ /**
158
+ * Captions live only in the legacy VML part: `<v:shape id="_x0000_s1025">
159
+ * … <v:textbox><div>Check Box 1</div></v:textbox>`. Returns shapeId → text.
160
+ * VML is scanned textually — Excel's VML is not reliably well-formed XML.
161
+ */
162
+ export var parseVmlControlCaptions = function (vml) {
163
+ var captions = new Map();
164
+ if (!vml)
165
+ return captions;
166
+ var shapeRe = /<v:shape\b([^>]*)>([\s\S]*?)<\/v:shape>/g;
167
+ var match;
168
+ while ((match = shapeRe.exec(vml))) {
169
+ var idMatch = /\bid="_x0000_s(\d+)"/.exec(match[1]);
170
+ if (!idMatch)
171
+ continue;
172
+ var body = match[2];
173
+ if (!/<x:ClientData\b/.test(body))
174
+ continue;
175
+ var textbox = /<v:textbox\b[^>]*>([\s\S]*?)<\/v:textbox>/.exec(body);
176
+ if (!textbox)
177
+ continue;
178
+ var text = textbox[1]
179
+ .replace(/<br\s*\/?>/gi, "\n")
180
+ .replace(/<[^>]+>/g, "")
181
+ .replace(/&amp;/g, "&")
182
+ .replace(/&lt;/g, "<")
183
+ .replace(/&gt;/g, ">")
184
+ .replace(/&quot;/g, '"')
185
+ .replace(/&#(\d+);/g, function (_, code) { return String.fromCodePoint(Number(code)); })
186
+ .trim();
187
+ if (text)
188
+ captions.set(Number(idMatch[1]), text);
189
+ }
190
+ return captions;
191
+ };
192
+ /**
193
+ * `<controls>` from a worksheet DOM, whether wrapped in
194
+ * `<mc:AlternateContent><mc:Choice Requires="x14">` (Excel) or bare.
195
+ */
196
+ export var readWorksheetControls = function (sheetDom) {
197
+ var e_4, _a, e_5, _b;
198
+ var _c;
199
+ var worksheet = (_c = childByLocalName(sheetDom, "worksheet")) !== null && _c !== void 0 ? _c : sheetDom;
200
+ var controls = childByLocalName(worksheet, "controls");
201
+ if (!controls)
202
+ return [];
203
+ var controlNodes = __spreadArray([], __read(asArray(childByLocalName(controls, "control"))), false);
204
+ try {
205
+ for (var _d = __values(asArray(childByLocalName(controls, "AlternateContent"))), _e = _d.next(); !_e.done; _e = _d.next()) {
206
+ var alternate = _e.value;
207
+ try {
208
+ for (var _f = (e_5 = void 0, __values(asArray(childByLocalName(alternate, "Choice")))), _g = _f.next(); !_g.done; _g = _f.next()) {
209
+ var choice = _g.value;
210
+ controlNodes.push.apply(controlNodes, __spreadArray([], __read(asArray(childByLocalName(choice, "control"))), false));
211
+ }
212
+ }
213
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
214
+ finally {
215
+ try {
216
+ if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
217
+ }
218
+ finally { if (e_5) throw e_5.error; }
219
+ }
220
+ }
221
+ }
222
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
223
+ finally {
224
+ try {
225
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
226
+ }
227
+ finally { if (e_4) throw e_4.error; }
228
+ }
229
+ return controlNodes.map(function (node) {
230
+ var _a, _b;
231
+ var a = attrs(node);
232
+ var controlPr = childByLocalName(node, "controlPr");
233
+ var anchor = childByLocalName(controlPr, "anchor");
234
+ var anchorAttrs = attrs(anchor);
235
+ var shapeId = Number(a.shapeId);
236
+ return __assign(__assign(__assign(__assign(__assign(__assign(__assign({}, (Number.isFinite(shapeId) && a.shapeId ? { shapeId: shapeId } : {})), (a.name ? { name: a.name } : {})), (((_a = a["r:id"]) !== null && _a !== void 0 ? _a : a.id) ? { relId: (_b = a["r:id"]) !== null && _b !== void 0 ? _b : a.id } : {})), { controlProperties: attrs(controlPr) }), (anchorAttrs.moveWithCells !== undefined
237
+ ? { moveWithCells: anchorAttrs.moveWithCells === "1" || anchorAttrs.moveWithCells === "true" }
238
+ : {})), (anchorAttrs.sizeWithCells !== undefined
239
+ ? { sizeWithCells: anchorAttrs.sizeWithCells === "1" || anchorAttrs.sizeWithCells === "true" }
240
+ : {})), { from: readCellAnchor(childByLocalName(anchor, "from")), to: readCellAnchor(childByLocalName(anchor, "to")) });
241
+ });
242
+ };
243
+ /**
244
+ * Assemble the sheet's form controls. `loadCtrlProp` resolves a control's
245
+ * `r:id` to its parsed `ctrlProp` DOM (undefined when the part is missing —
246
+ * the control is then skipped, Excel would repair it the same way).
247
+ */
248
+ export var buildFormControlEmbeds = function (_a) {
249
+ var controls = _a.controls, sheetId = _a.sheetId, ctrlProps = _a.ctrlProps, captions = _a.captions;
250
+ var embeds = [];
251
+ controls.forEach(function (control, index) {
252
+ var _a;
253
+ var parsed = control.relId ? ctrlProps.get(control.relId) : undefined;
254
+ if (!parsed || !control.from)
255
+ return;
256
+ var spec = {
257
+ type: "formControl",
258
+ objectType: parsed.objectType,
259
+ properties: parsed.properties,
260
+ };
261
+ if (control.name)
262
+ spec.name = control.name;
263
+ if (control.shapeId !== undefined)
264
+ spec.shapeId = control.shapeId;
265
+ var caption = control.shapeId !== undefined ? captions.get(control.shapeId) : undefined;
266
+ if (caption)
267
+ spec.text = caption;
268
+ if (parsed.listItems)
269
+ spec.listItems = parsed.listItems;
270
+ if (Object.keys(control.controlProperties).length) {
271
+ spec.controlProperties = control.controlProperties;
272
+ }
273
+ if (control.moveWithCells !== undefined)
274
+ spec.moveWithCells = control.moveWithCells;
275
+ if (control.sizeWithCells !== undefined)
276
+ spec.sizeWithCells = control.sizeWithCells;
277
+ embeds.push({
278
+ embedId: "control-".concat(sheetId, "-").concat((_a = control.shapeId) !== null && _a !== void 0 ? _a : index + 1),
279
+ spec: spec,
280
+ position: {
281
+ sheetId: sheetId,
282
+ overlayPosition: controlAnchorToOverlayPosition(control.from, control.to),
283
+ },
284
+ });
285
+ });
286
+ return embeds;
287
+ };
288
+ /** The `r:id` of a worksheet's `<legacyDrawing>` (VML part), if any. */
289
+ export var readLegacyDrawingRelId = function (sheetDom) {
290
+ var _a, _b;
291
+ var worksheet = (_a = childByLocalName(sheetDom, "worksheet")) !== null && _a !== void 0 ? _a : sheetDom;
292
+ var legacy = childByLocalName(worksheet, "legacyDrawing");
293
+ var a = attrs(legacy);
294
+ return (_b = a["r:id"]) !== null && _b !== void 0 ? _b : a.id;
295
+ };
@@ -1,5 +1,5 @@
1
1
  import type { CellFormat, ConditionalFormatRule, DataValidationRuleRecord, EmbeddedChart, EmbeddedObject, NamedRange, ProtectedRange, Sheet, Slicer, SpreadsheetTheme, TableView } from "@rowsncolumns/spreadsheet";
2
- import type { CommentThread, TextFormat, TextFormatRun } from "@rowsncolumns/common-types";
2
+ import type { NamedCellStyle, CommentThread, TextFormat, TextFormatRun } from "@rowsncolumns/common-types";
3
3
  import { XMLParser } from "fast-xml-parser";
4
4
  import type { IWorkbookPlugin } from "../../interface";
5
5
  import type { ExternalLink, ProcessSheetDataForSheetOptions, ProcessSheetDataResult, SheetCatalogEntry, WorkbookProperties } from "../../types";
@@ -252,6 +252,8 @@ export declare class XlsxPlugin extends BaseWorkbookPlugin implements IWorkbookP
252
252
  getSheetData(rid: string): Promise<any>;
253
253
  getStyles(): any;
254
254
  getTheme(): SpreadsheetTheme;
255
+ /** `<cellStyles>` resolved to cell formats (toolbar "Workbook styles" gallery). */
256
+ getNamedCellStyles(): NamedCellStyle[];
255
257
  /**
256
258
  * The workbook default font — styles.xml fonts[0], the font every cell
257
259
  * without an explicit font inherits. Exporters pass this through so the
@@ -294,6 +296,12 @@ export declare class XlsxPlugin extends BaseWorkbookPlugin implements IWorkbookP
294
296
  releaseSheetCaches(sheetId: number): void;
295
297
  private processOneSheet;
296
298
  getDrawings(): Promise<EmbeddedObjectWithPosition[]>;
299
+ /**
300
+ * Form controls: `<controls><control r:id>` → `xl/ctrlProps/ctrlPropN.xml`
301
+ * (+ the caption from the sheet's legacy VML part), as `formControl`
302
+ * embeds. Nothing is rendered interactively — they round-trip.
303
+ */
304
+ _getFormControls(rid: string, sheetId: number, sheetData: any): Promise<EmbeddedObject[]>;
297
305
  getCharts(): Promise<EmbeddedChart[]>;
298
306
  /**
299
307
  * Phase D1 — extract every pivot table across every worksheet.