@rowsncolumns/toolkit 24.4.2 → 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 (166) hide show
  1. package/dist/cjs/excel-parser/cfb-decryptor.d.ts +6 -0
  2. package/dist/cjs/excel-parser/cfb-decryptor.d.ts.map +1 -1
  3. package/dist/cjs/excel-parser/cfb-decryptor.js +6 -0
  4. package/dist/cjs/excel-parser/helpers.d.ts +9 -1
  5. package/dist/cjs/excel-parser/helpers.d.ts.map +1 -1
  6. package/dist/cjs/excel-parser/helpers.js +37 -0
  7. package/dist/cjs/excel-parser/interface.d.ts +15 -2
  8. package/dist/cjs/excel-parser/interface.d.ts.map +1 -1
  9. package/dist/cjs/excel-parser/plugins/base/index.d.ts +2 -0
  10. package/dist/cjs/excel-parser/plugins/base/index.d.ts.map +1 -1
  11. package/dist/cjs/excel-parser/plugins/base/index.js +3 -0
  12. package/dist/cjs/excel-parser/plugins/ods/index.d.ts +19 -0
  13. package/dist/cjs/excel-parser/plugins/ods/index.d.ts.map +1 -1
  14. package/dist/cjs/excel-parser/plugins/ods/index.js +676 -304
  15. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts +43 -1
  16. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  17. package/dist/cjs/excel-parser/plugins/ods/styles.js +343 -45
  18. package/dist/cjs/excel-parser/plugins/xls/index.d.ts +55 -1
  19. package/dist/cjs/excel-parser/plugins/xls/index.d.ts.map +1 -1
  20. package/dist/cjs/excel-parser/plugins/xls/index.js +518 -6
  21. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts +4 -0
  22. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  23. package/dist/cjs/excel-parser/plugins/xlsb/index.js +33 -14
  24. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  25. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  26. package/dist/cjs/excel-parser/plugins/xlsx/chartex.js +244 -0
  27. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts +10 -0
  28. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  29. package/dist/cjs/excel-parser/plugins/xlsx/charts.js +68 -9
  30. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
  31. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  32. package/dist/cjs/excel-parser/plugins/xlsx/drawing.js +155 -20
  33. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  34. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  35. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.js +295 -0
  36. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +35 -2
  37. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  38. package/dist/cjs/excel-parser/plugins/xlsx/index.js +737 -257
  39. package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  40. package/dist/cjs/excel-parser/plugins/xlsx/pivots.js +125 -37
  41. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
  42. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
  43. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.js +4 -1
  44. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  45. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  46. package/dist/cjs/excel-parser/plugins/xlsx/styles.js +102 -6
  47. package/dist/cjs/excel-parser/registry.d.ts +7 -0
  48. package/dist/cjs/excel-parser/registry.d.ts.map +1 -1
  49. package/dist/cjs/excel-parser/registry.js +29 -0
  50. package/dist/cjs/excel-parser/types.d.ts +17 -2
  51. package/dist/cjs/excel-parser/types.d.ts.map +1 -1
  52. package/dist/cjs/excel-parser/workbook.d.ts +3 -0
  53. package/dist/cjs/excel-parser/workbook.d.ts.map +1 -1
  54. package/dist/cjs/excel-parser/workbook.js +24 -14
  55. package/dist/cjs/excel-parser/worker.js +131 -131
  56. package/dist/cjs/exporter/ods/ods-export.d.ts.map +1 -1
  57. package/dist/cjs/exporter/ods/ods-export.js +432 -175
  58. package/dist/cjs/exporter/xlsx/chart-builder.d.ts.map +1 -1
  59. package/dist/cjs/exporter/xlsx/chart-builder.js +215 -39
  60. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts +36 -0
  61. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  62. package/dist/cjs/exporter/xlsx/chartex-builder.js +109 -0
  63. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts +61 -0
  64. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  65. package/dist/cjs/exporter/xlsx/form-controls-builder.js +197 -0
  66. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts +8 -0
  67. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  68. package/dist/cjs/exporter/xlsx/pivot-builder.js +141 -42
  69. package/dist/cjs/exporter/xlsx/style-builder.js +9 -3
  70. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
  71. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
  72. package/dist/cjs/exporter/xlsx/threaded-comments-builder.js +15 -3
  73. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts +11 -2
  74. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  75. package/dist/cjs/exporter/xlsx/xlsx-export.js +991 -297
  76. package/dist/cjs/helpers/implicit-intersection.d.ts +16 -0
  77. package/dist/cjs/helpers/implicit-intersection.d.ts.map +1 -0
  78. package/dist/cjs/helpers/implicit-intersection.js +197 -0
  79. package/dist/cjs/print-settings.d.ts +105 -0
  80. package/dist/cjs/print-settings.d.ts.map +1 -0
  81. package/dist/cjs/print-settings.js +494 -0
  82. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  83. package/dist/esm/excel-parser/cfb-decryptor.d.ts +6 -0
  84. package/dist/esm/excel-parser/cfb-decryptor.d.ts.map +1 -1
  85. package/dist/esm/excel-parser/cfb-decryptor.js +6 -0
  86. package/dist/esm/excel-parser/helpers.d.ts +9 -1
  87. package/dist/esm/excel-parser/helpers.d.ts.map +1 -1
  88. package/dist/esm/excel-parser/helpers.js +34 -0
  89. package/dist/esm/excel-parser/interface.d.ts +15 -2
  90. package/dist/esm/excel-parser/interface.d.ts.map +1 -1
  91. package/dist/esm/excel-parser/plugins/base/index.d.ts +2 -0
  92. package/dist/esm/excel-parser/plugins/base/index.d.ts.map +1 -1
  93. package/dist/esm/excel-parser/plugins/base/index.js +3 -0
  94. package/dist/esm/excel-parser/plugins/ods/index.d.ts +19 -0
  95. package/dist/esm/excel-parser/plugins/ods/index.d.ts.map +1 -1
  96. package/dist/esm/excel-parser/plugins/ods/index.js +347 -33
  97. package/dist/esm/excel-parser/plugins/ods/styles.d.ts +43 -1
  98. package/dist/esm/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  99. package/dist/esm/excel-parser/plugins/ods/styles.js +276 -2
  100. package/dist/esm/excel-parser/plugins/xls/index.d.ts +55 -1
  101. package/dist/esm/excel-parser/plugins/xls/index.d.ts.map +1 -1
  102. package/dist/esm/excel-parser/plugins/xls/index.js +441 -3
  103. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts +4 -0
  104. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  105. package/dist/esm/excel-parser/plugins/xlsb/index.js +30 -9
  106. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  107. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  108. package/dist/esm/excel-parser/plugins/xlsx/chartex.js +199 -0
  109. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts +10 -0
  110. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  111. package/dist/esm/excel-parser/plugins/xlsx/charts.js +69 -6
  112. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
  113. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  114. package/dist/esm/excel-parser/plugins/xlsx/drawing.js +99 -0
  115. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  116. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  117. package/dist/esm/excel-parser/plugins/xlsx/form-controls.js +246 -0
  118. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +35 -2
  119. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  120. package/dist/esm/excel-parser/plugins/xlsx/index.js +454 -32
  121. package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  122. package/dist/esm/excel-parser/plugins/xlsx/pivots.js +86 -6
  123. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
  124. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
  125. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.js +2 -0
  126. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  127. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  128. package/dist/esm/excel-parser/plugins/xlsx/styles.js +92 -2
  129. package/dist/esm/excel-parser/registry.d.ts +7 -0
  130. package/dist/esm/excel-parser/registry.d.ts.map +1 -1
  131. package/dist/esm/excel-parser/registry.js +19 -0
  132. package/dist/esm/excel-parser/types.d.ts +17 -2
  133. package/dist/esm/excel-parser/types.d.ts.map +1 -1
  134. package/dist/esm/excel-parser/workbook.d.ts +3 -0
  135. package/dist/esm/excel-parser/workbook.d.ts.map +1 -1
  136. package/dist/esm/excel-parser/workbook.js +19 -10
  137. package/dist/esm/excel-parser/worker.js +12 -18
  138. package/dist/esm/exporter/ods/ods-export.d.ts.map +1 -1
  139. package/dist/esm/exporter/ods/ods-export.js +306 -35
  140. package/dist/esm/exporter/xlsx/chart-builder.d.ts.map +1 -1
  141. package/dist/esm/exporter/xlsx/chart-builder.js +161 -28
  142. package/dist/esm/exporter/xlsx/chartex-builder.d.ts +36 -0
  143. package/dist/esm/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  144. package/dist/esm/exporter/xlsx/chartex-builder.js +97 -0
  145. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts +61 -0
  146. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  147. package/dist/esm/exporter/xlsx/form-controls-builder.js +173 -0
  148. package/dist/esm/exporter/xlsx/pivot-builder.d.ts +8 -0
  149. package/dist/esm/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  150. package/dist/esm/exporter/xlsx/pivot-builder.js +104 -19
  151. package/dist/esm/exporter/xlsx/style-builder.js +9 -3
  152. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
  153. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
  154. package/dist/esm/exporter/xlsx/threaded-comments-builder.js +15 -3
  155. package/dist/esm/exporter/xlsx/xlsx-export.d.ts +11 -2
  156. package/dist/esm/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  157. package/dist/esm/exporter/xlsx/xlsx-export.js +675 -64
  158. package/dist/esm/helpers/implicit-intersection.d.ts +16 -0
  159. package/dist/esm/helpers/implicit-intersection.d.ts.map +1 -0
  160. package/dist/esm/helpers/implicit-intersection.js +184 -0
  161. package/dist/esm/print-settings.d.ts +105 -0
  162. package/dist/esm/print-settings.d.ts.map +1 -0
  163. package/dist/esm/print-settings.js +422 -0
  164. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  165. package/package.json +3 -3
  166. package/xlsx.d.ts +14 -0
@@ -0,0 +1,199 @@
1
+ import { generateSelectionsFromFormula, uuid } from "@rowsncolumns/utils";
2
+ import { get } from "lodash-es";
3
+ import { extractChartPosition, } from "./charts";
4
+ /**
5
+ * Excel 2016+ "chartex" charts (`xl/charts/chartEx{N}.xml`, namespace
6
+ * `http://schemas.microsoft.com/office/drawing/2014/chartex`): treemap,
7
+ * sunburst, histogram / pareto, box & whisker, waterfall, funnel. They are
8
+ * anchored through an `mc:AlternateContent` whose `Choice` graphic frame
9
+ * carries `<cx:chart r:id>` instead of `<c:chart>`, and their data lives in
10
+ * `<cx:chartData><cx:data>` dimensions (`strDim type="cat"` for the
11
+ * hierarchy, `numDim type="size"|"val"` for the numbers) referenced by the
12
+ * series through `<cx:dataId>`.
13
+ *
14
+ * The exporter counterpart is `exporter/xlsx/chartex-builder.ts`.
15
+ */
16
+ export const CHART_EX_REL_TYPE = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
17
+ export const CHART_EX_GRAPHIC_URI = "http://schemas.microsoft.com/office/drawing/2014/chartex";
18
+ const asArray = (value) => value == null ? [] : Array.isArray(value) ? value : [value];
19
+ /** Read a child by local name, tolerating any namespace prefix. */
20
+ const child = (node, localName) => {
21
+ if (!node || typeof node !== "object")
22
+ return undefined;
23
+ if (node[localName] !== undefined)
24
+ return node[localName];
25
+ for (const key of Object.keys(node)) {
26
+ const colon = key.indexOf(":");
27
+ if (colon >= 0 && key.slice(colon + 1) === localName)
28
+ return node[key];
29
+ }
30
+ return undefined;
31
+ };
32
+ const textOf = (node) => {
33
+ if (node == null)
34
+ return undefined;
35
+ if (typeof node === "object") {
36
+ const inner = node.t$;
37
+ return inner == null ? undefined : String(inner);
38
+ }
39
+ return String(node);
40
+ };
41
+ /**
42
+ * `<cx:chart r:id>` inside an anchor's `mc:AlternateContent` choice (Excel
43
+ * also writes a plain `xdr:graphicFrame` for some producers — both forms are
44
+ * checked). Returns the `cx:chart` node or undefined for non-chartex anchors.
45
+ */
46
+ export function getChartExReferenceFromAnchor(anchor) {
47
+ const frames = [];
48
+ for (const alternate of asArray(child(anchor, "AlternateContent"))) {
49
+ for (const choice of asArray(child(alternate, "Choice"))) {
50
+ frames.push(...asArray(child(choice, "graphicFrame")));
51
+ }
52
+ }
53
+ frames.push(...asArray(child(anchor, "graphicFrame")));
54
+ for (const frame of frames) {
55
+ const graphicData = child(child(frame, "graphic"), "graphicData");
56
+ if (!graphicData)
57
+ continue;
58
+ const uri = get(graphicData, "a$.uri");
59
+ const cxChart = child(graphicData, "chart");
60
+ if (uri === CHART_EX_GRAPHIC_URI && cxChart)
61
+ return cxChart;
62
+ // A `cx:`-prefixed chart element without the uri attribute (defensive).
63
+ if (cxChart && Object.keys(graphicData).some((k) => k.startsWith("cx:"))) {
64
+ return cxChart;
65
+ }
66
+ }
67
+ return undefined;
68
+ }
69
+ /** `layoutId` → engine chart type. Unknown layouts are not imported. */
70
+ const CHART_TYPE_BY_LAYOUT = {
71
+ treemap: "treemap",
72
+ sunburst: "sunburst",
73
+ waterfall: "waterfall",
74
+ funnel: "funnel",
75
+ boxWhisker: "boxplot",
76
+ // `clusteredColumn` is a histogram / pareto only when it carries `<cx:binning>`.
77
+ };
78
+ const sourcesFromRef = (ref, hostSheetId, resolveSheetId) => {
79
+ if (!ref)
80
+ return [];
81
+ const selections = generateSelectionsFromFormula(`=${ref}`);
82
+ return selections.map((sel) => ({
83
+ ...sel.range,
84
+ sheetId: (sel.sheetName ? resolveSheetId?.(sel.sheetName) : undefined) ??
85
+ hostSheetId,
86
+ }));
87
+ };
88
+ const chartData = (sources) => ({ sources });
89
+ /**
90
+ * Split a multi-column hierarchy range (Excel lays the treemap hierarchy out
91
+ * as columns, top level first, leaf last) into `parentLabels` (one entry per
92
+ * parent column) and `labels` (the leaf column).
93
+ */
94
+ export const splitHierarchyRange = (range) => {
95
+ const parentLabels = [];
96
+ for (let c = range.startColumnIndex; c < range.endColumnIndex; c++) {
97
+ parentLabels.push({ ...range, startColumnIndex: c, endColumnIndex: c });
98
+ }
99
+ return {
100
+ parentLabels,
101
+ labels: {
102
+ ...range,
103
+ startColumnIndex: range.endColumnIndex,
104
+ endColumnIndex: range.endColumnIndex,
105
+ },
106
+ };
107
+ };
108
+ const dimensionRef = (data, dimTag, type) => {
109
+ const dims = asArray(child(data, dimTag)).filter((dim) => get(dim, "a$.type") === type);
110
+ const dim = dims[0] ?? (dimTag === "numDim" ? asArray(child(data, dimTag))[0] : undefined);
111
+ const f = child(dim, "f");
112
+ return textOf(Array.isArray(f) ? f[0] : f)?.trim() || undefined;
113
+ };
114
+ /** Parse a `cx:chartSpace` DOM into an `EmbeddedChart` spec (null when unsupported). */
115
+ export function parseChartExSpec(chartSpaceDom, sheetId, resolveSheetId) {
116
+ const chartSpace = child(chartSpaceDom, "chartSpace") ?? chartSpaceDom;
117
+ const chart = child(chartSpace, "chart");
118
+ if (!chart)
119
+ return null;
120
+ const region = child(child(chart, "plotArea"), "plotAreaRegion");
121
+ const series = asArray(child(region, "series"))[0];
122
+ if (!series)
123
+ return null;
124
+ const layoutId = String(get(series, "a$.layoutId") ?? "");
125
+ // Excel nests `<cx:binning>` in `<cx:layoutPr>`; tolerate it directly on the series too.
126
+ const binning = child(child(series, "layoutPr"), "binning") ?? child(series, "binning");
127
+ const chartType = layoutId === "clusteredColumn" && binning
128
+ ? "histogram"
129
+ : CHART_TYPE_BY_LAYOUT[layoutId];
130
+ if (!chartType)
131
+ return null;
132
+ const dataId = String(get(child(series, "dataId"), "a$.val") ?? "0");
133
+ const data = asArray(child(child(chartSpace, "chartData"), "data")).find((d) => String(get(d, "a$.id")) === dataId) ?? asArray(child(child(chartSpace, "chartData"), "data"))[0];
134
+ if (!data)
135
+ return null;
136
+ const title = textOf(child(child(child(child(chart, "title"), "tx"), "txData"), "v"));
137
+ const catRef = dimensionRef(data, "strDim", "cat");
138
+ const catSources = sourcesFromRef(catRef, sheetId, resolveSheetId);
139
+ if (chartType === "treemap" || chartType === "sunburst") {
140
+ const sizeRef = dimensionRef(data, "numDim", "size");
141
+ const sizeSources = sourcesFromRef(sizeRef, sheetId, resolveSheetId);
142
+ if (!catSources.length || !sizeSources.length)
143
+ return null;
144
+ const hierarchy = splitHierarchyRange(catSources[0]);
145
+ return {
146
+ chartType,
147
+ ...(title ? { title } : {}),
148
+ labels: [chartData([hierarchy.labels])],
149
+ parentLabels: hierarchy.parentLabels.map((range) => chartData([range])),
150
+ sizeData: [chartData(sizeSources)],
151
+ };
152
+ }
153
+ const valRef = dimensionRef(data, "numDim", "val");
154
+ const valSources = sourcesFromRef(valRef, sheetId, resolveSheetId);
155
+ if (!valSources.length)
156
+ return null;
157
+ const spec = {
158
+ chartType,
159
+ ...(title ? { title } : {}),
160
+ series: [chartData(valSources)],
161
+ ...(catSources.length ? { domains: [chartData(catSources)] } : {}),
162
+ };
163
+ if (chartType === "histogram") {
164
+ const binCount = Number(get(child(binning, "binCount"), "a$.val"));
165
+ if (Number.isFinite(binCount) && binCount > 0)
166
+ spec.binCount = binCount;
167
+ }
168
+ return spec;
169
+ }
170
+ /** Resolve + parse one chartex part referenced from a drawing anchor. */
171
+ export async function processChartEx(chartTarget, drawingPath, anchor, sheetId, zipParser, xmlParser, sheetDimensions, resolveSheetId) {
172
+ let chartPath = chartTarget;
173
+ const drawingDir = drawingPath.substring(0, drawingPath.lastIndexOf("/"));
174
+ if (chartPath.startsWith("/")) {
175
+ chartPath = chartPath.slice(1);
176
+ }
177
+ else if (chartPath.startsWith("../")) {
178
+ chartPath = `xl/${chartPath.replace("../", "")}`;
179
+ }
180
+ else if (!chartPath.startsWith("xl/")) {
181
+ chartPath = `${drawingDir}/${chartPath}`;
182
+ }
183
+ let content;
184
+ try {
185
+ content = await zipParser.getText(chartPath);
186
+ }
187
+ catch {
188
+ return null;
189
+ }
190
+ if (!content)
191
+ return null;
192
+ const spec = parseChartExSpec(xmlParser.parse(content), sheetId, resolveSheetId);
193
+ if (!spec)
194
+ return null;
195
+ const position = extractChartPosition(anchor, sheetId, sheetDimensions);
196
+ if (!position)
197
+ return null;
198
+ return { chartId: uuid(), spec, position };
199
+ }
@@ -17,6 +17,16 @@ export declare function extractChartDataRange(plotArea: any, chartType: string,
17
17
  export declare function extractHiddenDimensionStrategy(chart: any): HIDDEN_DIMENSION_STRATEGY | undefined;
18
18
  export declare function extractChartTitle(chart: any): string;
19
19
  export declare function determineChartType(chart: any): "bar" | "column" | "line" | "pie" | "doughnut" | "area" | "radar" | "stock" | "scatter" | "bubble" | "treemap" | "sunburst" | "histogram" | "boxplot" | "waterfall" | "funnel";
20
+ /**
21
+ * The authored 3-D / surface chart class, when the plot area's chart
22
+ * element is one of Excel's 3-D variants. These degrade to their 2-D
23
+ * `chartType` (bar3DChart → bar/column, line3DChart → line, pie3DChart →
24
+ * pie, area3DChart / surfaceChart / surface3DChart → area) and the
25
+ * original class is preserved verbatim as `sourceChartType`, matching the
26
+ * Rust importer, so the renderer's echarts-gl pipeline and the exporter's
27
+ * 3-D writer can restore it. Undefined for plain 2-D charts.
28
+ */
29
+ export declare function extractThreeDSourceChartType(plotArea: any): "BAR_3D" | "LINE_3D" | "PIE_3D" | "AREA_3D" | "SURFACE" | "SURFACE_3D" | undefined;
20
30
  /**
21
31
  * Phase 5.5 — pull binCount out of the c15:histogramChart extension
22
32
  * marker. Returns undefined if absent.
@@ -1 +1 @@
1
- {"version":3,"file":"charts.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/charts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"charts.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/charts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EAET,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,UAAU,EACX,MAAM,2BAA2B,CAAC;AAInC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;AAkDnF,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,kBAAkB,EAC7B,SAAS,EAAE,GAAG,EACd,eAAe,CAAC,EAAE,eAAe,EACjC,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAsM/B;AAoID,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,cAAc,GAC9B,UAAU,GAAG,IAAI,CAgEnB;AA+DD;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,GAAG,GACT,yBAAyB,GAAG,SAAS,CAiBvC;AAyBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAoBpD;AA0BD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,GAAG,GAER,KAAK,GACL,QAAQ,GACR,MAAM,GACN,KAAK,GACL,UAAU,GACV,MAAM,GACN,OAAO,GACP,OAAO,GACP,SAAS,GACT,QAAQ,GACR,SAAS,GACT,UAAU,GACV,WAAW,GACX,SAAS,GACT,WAAW,GACX,QAAQ,CA8EX;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,GAAG,GAEX,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,SAAS,GACT,SAAS,GACT,YAAY,GACZ,SAAS,CASZ;AAoED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,GAAG,GACZ,MAAM,GAAG,SAAS,CA+CpB;AA6GD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,cAAc,GAC9B,SAAS,EAAE,CAkLb;AAioBD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,cAAc,GAC9B,SAAS,EAAE,CAgGb;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,cAAc,GAC9B,SAAS,EAAE,CAiBb;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,eAAe,GAChC,sBAAsB,GAAG,IAAI,CA2H/B;AAsOD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,GAAG;;;;EAe/C;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,GAAG,GAC7C;IACE,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACD,SAAS,CAiCZ"}
@@ -120,6 +120,10 @@ export async function processChart(chartTarget, drawingPath, anchor, sheetId, zi
120
120
  // "pie" with sourceChartType "OF_PIE" plus the split fields the
121
121
  // renderer uses to draw the composite layout.
122
122
  const ofPieOptions = chartType === "pie" ? extractOfPieOptions(plotArea) : undefined;
123
+ // 3-D / surface variants — preserved as sourceChartType (BAR_3D,
124
+ // LINE_3D, PIE_3D, AREA_3D, SURFACE, SURFACE_3D) on top of the 2-D
125
+ // chartType they degrade to. Disjoint from OF_PIE.
126
+ const threeDSourceChartType = extractThreeDSourceChartType(plotArea);
123
127
  const radarStyle = chartType === "radar" ? extractRadarStyle(plotArea) : undefined;
124
128
  const binCount = chartType === "histogram"
125
129
  ? extractC15HistogramBinCount(plotArea)
@@ -166,6 +170,9 @@ export async function processChart(chartTarget, drawingPath, anchor, sheetId, zi
166
170
  ...(ofPieOptions
167
171
  ? { sourceChartType: "OF_PIE", ...ofPieOptions }
168
172
  : {}),
173
+ ...(threeDSourceChartType && !ofPieOptions
174
+ ? { sourceChartType: threeDSourceChartType }
175
+ : {}),
169
176
  ...(radarStyle ? { radarStyle } : {}),
170
177
  ...(typeof binCount === "number" ? { binCount } : {}),
171
178
  ...(barLayout?.stackedType
@@ -240,6 +247,12 @@ function getSeriesElements(plotArea, chartType) {
240
247
  "areaChart.ser",
241
248
  "c:area3DChart.c:ser",
242
249
  "area3DChart.ser",
250
+ // Surface / contour charts degrade to area (sourceChartType
251
+ // SURFACE / SURFACE_3D); their series carry the same cat/val shape.
252
+ "c:surfaceChart.c:ser",
253
+ "surfaceChart.ser",
254
+ "c:surface3DChart.c:ser",
255
+ "surface3DChart.ser",
243
256
  ]);
244
257
  case "radar":
245
258
  return getWithFallback(plotArea, ["c:radarChart.c:ser", "radarChart.ser"]);
@@ -562,6 +575,12 @@ export function determineChartType(chart) {
562
575
  "areaChart",
563
576
  "c:area3DChart",
564
577
  "area3DChart",
578
+ // Surface / contour degrade to area — the same 2-D base the Rust
579
+ // importer and the renderer's surface pipeline use.
580
+ "c:surfaceChart",
581
+ "surfaceChart",
582
+ "c:surface3DChart",
583
+ "surface3DChart",
565
584
  ]))
566
585
  return "area";
567
586
  if (getWithFallback(plotArea, ["c:radarChart", "radarChart"]))
@@ -576,6 +595,31 @@ export function determineChartType(chart) {
576
595
  return "bubble";
577
596
  return "column"; // default
578
597
  }
598
+ /**
599
+ * The authored 3-D / surface chart class, when the plot area's chart
600
+ * element is one of Excel's 3-D variants. These degrade to their 2-D
601
+ * `chartType` (bar3DChart → bar/column, line3DChart → line, pie3DChart →
602
+ * pie, area3DChart / surfaceChart / surface3DChart → area) and the
603
+ * original class is preserved verbatim as `sourceChartType`, matching the
604
+ * Rust importer, so the renderer's echarts-gl pipeline and the exporter's
605
+ * 3-D writer can restore it. Undefined for plain 2-D charts.
606
+ */
607
+ export function extractThreeDSourceChartType(plotArea) {
608
+ const has = (paths) => Boolean(getWithFallback(plotArea, paths));
609
+ if (has(["c:bar3DChart", "bar3DChart"]))
610
+ return "BAR_3D";
611
+ if (has(["c:line3DChart", "line3DChart"]))
612
+ return "LINE_3D";
613
+ if (has(["c:pie3DChart", "pie3DChart"]))
614
+ return "PIE_3D";
615
+ if (has(["c:area3DChart", "area3DChart"]))
616
+ return "AREA_3D";
617
+ if (has(["c:surface3DChart", "surface3DChart"]))
618
+ return "SURFACE_3D";
619
+ if (has(["c:surfaceChart", "surfaceChart"]))
620
+ return "SURFACE";
621
+ return undefined;
622
+ }
579
623
  /**
580
624
  * Phase 5.5 — detect the c15 extension marker our exporter writes on
581
625
  * the plotArea. Returns the originating chart type (histogram /
@@ -711,7 +755,16 @@ const CHART_TYPE_CONTAINERS = [
711
755
  chartType: "line",
712
756
  },
713
757
  {
714
- paths: ["c:areaChart", "areaChart", "c:area3DChart", "area3DChart"],
758
+ paths: [
759
+ "c:areaChart",
760
+ "areaChart",
761
+ "c:area3DChart",
762
+ "area3DChart",
763
+ "c:surfaceChart",
764
+ "surfaceChart",
765
+ "c:surface3DChart",
766
+ "surface3DChart",
767
+ ],
715
768
  chartType: "area",
716
769
  },
717
770
  {
@@ -1765,13 +1818,23 @@ const mapDataLabelPosition = (val) => {
1765
1818
  function extractDataLabelsOptions(plotArea, chartType) {
1766
1819
  // Look for <c:dLbls> inside the chartType-specific container. We pick
1767
1820
  // the first one we find — chart-level labels apply to all series.
1821
+ // The 3-D classes (bar3DChart / line3DChart / pie3DChart / area3DChart)
1822
+ // degrade to the same `chartType` and carry `<c:dLbls>` in the same slot
1823
+ // of their group, so they are looked up alongside the 2-D container.
1768
1824
  const containerKeys = {
1769
- bar: ["c:barChart", "barChart"],
1770
- column: ["c:barChart", "barChart"],
1771
- line: ["c:lineChart", "lineChart"],
1772
- pie: ["c:pieChart", "pieChart", "c:ofPieChart", "ofPieChart"],
1825
+ bar: ["c:barChart", "barChart", "c:bar3DChart", "bar3DChart"],
1826
+ column: ["c:barChart", "barChart", "c:bar3DChart", "bar3DChart"],
1827
+ line: ["c:lineChart", "lineChart", "c:line3DChart", "line3DChart"],
1828
+ pie: [
1829
+ "c:pieChart",
1830
+ "pieChart",
1831
+ "c:ofPieChart",
1832
+ "ofPieChart",
1833
+ "c:pie3DChart",
1834
+ "pie3DChart",
1835
+ ],
1773
1836
  doughnut: ["c:doughnutChart", "doughnutChart"],
1774
- area: ["c:areaChart", "areaChart"],
1837
+ area: ["c:areaChart", "areaChart", "c:area3DChart", "area3DChart"],
1775
1838
  };
1776
1839
  const keys = containerKeys[chartType] ?? [];
1777
1840
  let container;
@@ -1,9 +1,28 @@
1
- import type { EmbeddedObject, EmbedShapeSpec } from "@rowsncolumns/spreadsheet";
1
+ import type { EmbeddedObject, EmbedImageSpec, EmbedShapeSpec } from "@rowsncolumns/spreadsheet";
2
2
  import { type XMLParser } from "fast-xml-parser";
3
3
  import { type StreamingZipParser } from "../../zip-parser-streaming";
4
4
  export type EmbeddedObjectWithPosition = EmbeddedObject & {
5
5
  isInsideCell?: boolean;
6
6
  };
7
+ /** `processAnchors` anchor-type tags, keyed by the drawing element name. */
8
+ declare const ANCHOR_KIND_BY_ELEMENT: {
9
+ readonly oneCellAnchor: "oneCellAnchor";
10
+ readonly twoCellAnchor: "twoCellAnchors";
11
+ readonly absoluteAnchor: "absoluteAnchors";
12
+ };
13
+ type AnchorElementName = keyof typeof ANCHOR_KIND_BY_ELEMENT;
14
+ /**
15
+ * The `<xdr:wsDr>` anchors in document order — Excel's z-order (first is
16
+ * the back-most object). The unordered parse keeps document order within one
17
+ * element name but groups the three anchor kinds apart, so the kind sequence
18
+ * is read off the raw part and the parsed nodes are dealt out in that order.
19
+ * Anchors the scan does not account for (namespace quirks) trail in their
20
+ * parsed order, so nothing is ever dropped.
21
+ */
22
+ export declare function anchorsInDocumentOrder(drawing: any, drawingXml: string): Array<{
23
+ kind: (typeof ANCHOR_KIND_BY_ELEMENT)[AnchorElementName];
24
+ node: any;
25
+ }>;
7
26
  /**
8
27
  * Process different types of image anchors
9
28
  * @param anchors The anchor elements from the drawing
@@ -15,6 +34,13 @@ export type EmbeddedObjectWithPosition = EmbeddedObject & {
15
34
  * @returns An array of image objects with their properties and binary data
16
35
  */
17
36
  export declare function processAnchors(anchors: any, anchorType: string, drawingPath: string, sheetId: number, zipParser: StreamingZipParser, xmlParser: XMLParser): Promise<EmbeddedObjectWithPosition[]>;
37
+ /**
38
+ * Picture-format adjustments off an `<xdr:pic>`: `<a:blipFill><a:srcRect>`
39
+ * (crop), `<a:blip><a:lum bright contrast>` (brightness / contrast) and
40
+ * `<a:blip><a:alphaModFix amt>` (opacity → `transparency`). Only present
41
+ * values are returned so an untouched picture stays a bare image spec.
42
+ */
43
+ export declare function parsePictureAdjustments(picture: any): Pick<EmbedImageSpec, "crop" | "brightness" | "contrast" | "transparency">;
18
44
  /**
19
45
  * Whether an `<xdr:sp>` should import as a drawing shape (`EmbedShapeSpec`)
20
46
  * rather than a textbox. Text boxes are excluded explicitly (`txBox="1"`), and
@@ -36,4 +62,5 @@ export declare function parseShapeSpec(shape: any): EmbedShapeSpec;
36
62
  * @returns Boolean indicating if the image is inside a cell
37
63
  */
38
64
  export declare function determineIfOneCellInsideCell(fromColOff: number, fromRowOff: number, fLocksWithSheet: string, cx: number, cy: number): boolean;
65
+ export {};
39
66
  //# sourceMappingURL=drawing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"drawing.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/drawing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,cAAc,EAEd,cAAc,EAWf,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAoDrE,MAAM,MAAM,0BAA0B,GAAG,cAAc,GAAG;IACxD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,kBAAkB,EAC7B,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,0BAA0B,EAAE,CAAC,CA6dvC;AA6OD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CASlD;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,cAAc,CA8CzD;AA8MD;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,OAAO,CAqBT"}
1
+ {"version":3,"file":"drawing.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/drawing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,cAAc,EAEd,cAAc,EACd,cAAc,EAYf,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAoDrE,MAAM,MAAM,0BAA0B,GAAG,cAAc,GAAG;IACxD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,4EAA4E;AAC5E,QAAA,MAAM,sBAAsB;;;;CAIlB,CAAC;AAEX,KAAK,iBAAiB,GAAG,MAAM,OAAO,sBAAsB,CAAC;AAK7D;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,MAAM,GACjB,KAAK,CAAC;IACP,IAAI,EAAE,CAAC,OAAO,sBAAsB,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACzD,IAAI,EAAE,GAAG,CAAC;CACX,CAAC,CAkCD;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,kBAAkB,EAC7B,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,0BAA0B,EAAE,CAAC,CA8dvC;AASD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,GAAG,GACX,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,cAAc,CAAC,CAuC3E;AA6OD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CASlD;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,cAAc,CA8CzD;AA8MD;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,OAAO,CAqBT"}
@@ -41,6 +41,54 @@ const CELL_IMAGE_OFFSET_THRESHOLD_PX = 1;
41
41
  function emuToPixels(emuValue) {
42
42
  return Math.round(emuValue / EMU_PER_PIXEL);
43
43
  }
44
+ /** `processAnchors` anchor-type tags, keyed by the drawing element name. */
45
+ const ANCHOR_KIND_BY_ELEMENT = {
46
+ oneCellAnchor: "oneCellAnchor",
47
+ twoCellAnchor: "twoCellAnchors",
48
+ absoluteAnchor: "absoluteAnchors",
49
+ };
50
+ const ANCHOR_ELEMENT_REGEX = /<(?:[A-Za-z_][\w.-]*:)?(oneCellAnchor|twoCellAnchor|absoluteAnchor)(?=[\s/>])/g;
51
+ /**
52
+ * The `<xdr:wsDr>` anchors in document order — Excel's z-order (first is
53
+ * the back-most object). The unordered parse keeps document order within one
54
+ * element name but groups the three anchor kinds apart, so the kind sequence
55
+ * is read off the raw part and the parsed nodes are dealt out in that order.
56
+ * Anchors the scan does not account for (namespace quirks) trail in their
57
+ * parsed order, so nothing is ever dropped.
58
+ */
59
+ export function anchorsInDocumentOrder(drawing, drawingXml) {
60
+ const nodesByElement = {
61
+ oneCellAnchor: [],
62
+ twoCellAnchor: [],
63
+ absoluteAnchor: [],
64
+ };
65
+ for (const element of Object.keys(nodesByElement)) {
66
+ const parsed = get(drawing, `xdr:wsDr.xdr:${element}`) || get(drawing, `wsDr.${element}`);
67
+ if (!parsed)
68
+ continue;
69
+ nodesByElement[element] = Array.isArray(parsed) ? parsed : [parsed];
70
+ }
71
+ const cursor = {
72
+ oneCellAnchor: 0,
73
+ twoCellAnchor: 0,
74
+ absoluteAnchor: 0,
75
+ };
76
+ const ordered = [];
77
+ for (const match of drawingXml.matchAll(ANCHOR_ELEMENT_REGEX)) {
78
+ const element = match[1];
79
+ const node = nodesByElement[element][cursor[element]];
80
+ if (node === undefined)
81
+ continue;
82
+ cursor[element] += 1;
83
+ ordered.push({ kind: ANCHOR_KIND_BY_ELEMENT[element], node });
84
+ }
85
+ for (const element of Object.keys(nodesByElement)) {
86
+ for (const node of nodesByElement[element].slice(cursor[element])) {
87
+ ordered.push({ kind: ANCHOR_KIND_BY_ELEMENT[element], node });
88
+ }
89
+ }
90
+ return ordered;
91
+ }
44
92
  /**
45
93
  * Process different types of image anchors
46
94
  * @param anchors The anchor elements from the drawing
@@ -410,6 +458,7 @@ export async function processAnchors(anchors, anchorType, drawingPath, sheetId,
410
458
  imageUrl: createDataUrl(imageData, imageType),
411
459
  type: "image",
412
460
  description: imageName,
461
+ ...parsePictureAdjustments(picture),
413
462
  },
414
463
  position,
415
464
  draggable: true,
@@ -418,6 +467,56 @@ export async function processAnchors(anchors, anchorType, drawingPath, sheetId,
418
467
  }
419
468
  return images;
420
469
  }
470
+ /** DrawingML per-mille-percent (100000 = 100%) → fraction, or undefined. */
471
+ const pctToFraction = (value) => {
472
+ if (value === undefined || value === null || value === "")
473
+ return undefined;
474
+ const n = Number(value);
475
+ return Number.isFinite(n) ? n / 100000 : undefined;
476
+ };
477
+ /**
478
+ * Picture-format adjustments off an `<xdr:pic>`: `<a:blipFill><a:srcRect>`
479
+ * (crop), `<a:blip><a:lum bright contrast>` (brightness / contrast) and
480
+ * `<a:blip><a:alphaModFix amt>` (opacity → `transparency`). Only present
481
+ * values are returned so an untouched picture stays a bare image spec.
482
+ */
483
+ export function parsePictureAdjustments(picture) {
484
+ const blipFill = get(picture, "xdr:blipFill") ?? get(picture, "blipFill") ?? undefined;
485
+ const blip = get(blipFill, "a:blip") ?? get(blipFill, "blip");
486
+ const out = {};
487
+ const srcRect = get(blipFill, "a:srcRect.a$") ?? get(blipFill, "srcRect.a$");
488
+ if (srcRect) {
489
+ const crop = {};
490
+ const left = pctToFraction(srcRect.l);
491
+ const top = pctToFraction(srcRect.t);
492
+ const right = pctToFraction(srcRect.r);
493
+ const bottom = pctToFraction(srcRect.b);
494
+ if (left)
495
+ crop.left = left;
496
+ if (top)
497
+ crop.top = top;
498
+ if (right)
499
+ crop.right = right;
500
+ if (bottom)
501
+ crop.bottom = bottom;
502
+ if (Object.keys(crop).length)
503
+ out.crop = crop;
504
+ }
505
+ const lum = get(blip, "a:lum.a$") ?? get(blip, "lum.a$");
506
+ if (lum) {
507
+ const brightness = pctToFraction(lum.bright);
508
+ const contrast = pctToFraction(lum.contrast);
509
+ if (brightness)
510
+ out.brightness = brightness;
511
+ if (contrast)
512
+ out.contrast = contrast;
513
+ }
514
+ const alpha = pctToFraction(get(blip, "a:alphaModFix.a$.amt") ?? get(blip, "alphaModFix.a$.amt"));
515
+ if (alpha !== undefined && alpha < 1) {
516
+ out.transparency = Math.round((1 - alpha) * 100000) / 100000;
517
+ }
518
+ return out;
519
+ }
421
520
  /**
422
521
  * Parse color from DrawingML color element
423
522
  * Supports both RGB (srgbClr) and theme colors (schemeClr)
@@ -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"}