@rowsncolumns/toolkit 24.4.4 → 24.5.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 (113) hide show
  1. package/dist/cjs/autofilter-condition.d.ts +45 -1
  2. package/dist/cjs/autofilter-condition.d.ts.map +1 -1
  3. package/dist/cjs/autofilter-condition.js +135 -12
  4. package/dist/cjs/excel-parser/helpers.d.ts +15 -1
  5. package/dist/cjs/excel-parser/helpers.d.ts.map +1 -1
  6. package/dist/cjs/excel-parser/helpers.js +119 -5
  7. package/dist/cjs/excel-parser/interface.d.ts +3 -1
  8. package/dist/cjs/excel-parser/interface.d.ts.map +1 -1
  9. package/dist/cjs/excel-parser/plugins/ods/index.d.ts.map +1 -1
  10. package/dist/cjs/excel-parser/plugins/ods/index.js +186 -97
  11. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts +15 -0
  12. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  13. package/dist/cjs/excel-parser/plugins/ods/styles.js +80 -6
  14. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  15. package/dist/cjs/excel-parser/plugins/xlsb/index.js +107 -103
  16. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts +77 -1
  17. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  18. package/dist/cjs/excel-parser/plugins/xlsx/charts.js +920 -122
  19. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts +7 -1
  20. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  21. package/dist/cjs/excel-parser/plugins/xlsx/drawing.js +24 -9
  22. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts +24 -3
  23. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -1
  24. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.js +25 -3
  25. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +24 -1
  26. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  27. package/dist/cjs/excel-parser/plugins/xlsx/index.js +561 -394
  28. package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts +8 -2
  29. package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  30. package/dist/cjs/excel-parser/plugins/xlsx/pivots.js +312 -21
  31. package/dist/cjs/excel-parser/plugins/xlsx/relationships.d.ts +6 -0
  32. package/dist/cjs/excel-parser/plugins/xlsx/relationships.d.ts.map +1 -1
  33. package/dist/cjs/excel-parser/plugins/xlsx/relationships.js +9 -0
  34. package/dist/cjs/excel-parser/plugins/xlsx/theme.d.ts +1 -1
  35. package/dist/cjs/excel-parser/types.d.ts +9 -1
  36. package/dist/cjs/excel-parser/types.d.ts.map +1 -1
  37. package/dist/cjs/excel-parser/workbook.d.ts +1 -0
  38. package/dist/cjs/excel-parser/workbook.d.ts.map +1 -1
  39. package/dist/cjs/excel-parser/workbook.js +5 -0
  40. package/dist/cjs/excel-parser/worker.js +2 -0
  41. package/dist/cjs/exporter/ods/ods-export.d.ts.map +1 -1
  42. package/dist/cjs/exporter/ods/ods-export.js +255 -80
  43. package/dist/cjs/exporter/xlsx/chart-builder.d.ts +7 -1
  44. package/dist/cjs/exporter/xlsx/chart-builder.d.ts.map +1 -1
  45. package/dist/cjs/exporter/xlsx/chart-builder.js +902 -119
  46. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts +16 -3
  47. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts.map +1 -1
  48. package/dist/cjs/exporter/xlsx/form-controls-builder.js +30 -8
  49. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  50. package/dist/cjs/exporter/xlsx/pivot-builder.js +206 -162
  51. package/dist/cjs/exporter/xlsx/style-builder.d.ts +8 -2
  52. package/dist/cjs/exporter/xlsx/style-builder.d.ts.map +1 -1
  53. package/dist/cjs/exporter/xlsx/style-builder.js +25 -0
  54. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts +2 -2
  55. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  56. package/dist/cjs/exporter/xlsx/xlsx-export.js +728 -452
  57. package/dist/esm/autofilter-condition.d.ts +45 -1
  58. package/dist/esm/autofilter-condition.d.ts.map +1 -1
  59. package/dist/esm/autofilter-condition.js +131 -11
  60. package/dist/esm/excel-parser/helpers.d.ts +15 -1
  61. package/dist/esm/excel-parser/helpers.d.ts.map +1 -1
  62. package/dist/esm/excel-parser/helpers.js +94 -4
  63. package/dist/esm/excel-parser/interface.d.ts +3 -1
  64. package/dist/esm/excel-parser/interface.d.ts.map +1 -1
  65. package/dist/esm/excel-parser/plugins/ods/index.d.ts.map +1 -1
  66. package/dist/esm/excel-parser/plugins/ods/index.js +105 -22
  67. package/dist/esm/excel-parser/plugins/ods/styles.d.ts +15 -0
  68. package/dist/esm/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  69. package/dist/esm/excel-parser/plugins/ods/styles.js +79 -5
  70. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  71. package/dist/esm/excel-parser/plugins/xlsb/index.js +15 -7
  72. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts +77 -1
  73. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  74. package/dist/esm/excel-parser/plugins/xlsx/charts.js +708 -16
  75. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts +7 -1
  76. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  77. package/dist/esm/excel-parser/plugins/xlsx/drawing.js +23 -0
  78. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts +24 -3
  79. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -1
  80. package/dist/esm/excel-parser/plugins/xlsx/form-controls.js +21 -3
  81. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +24 -1
  82. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  83. package/dist/esm/excel-parser/plugins/xlsx/index.js +192 -54
  84. package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts +8 -2
  85. package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  86. package/dist/esm/excel-parser/plugins/xlsx/pivots.js +220 -4
  87. package/dist/esm/excel-parser/plugins/xlsx/relationships.d.ts +6 -0
  88. package/dist/esm/excel-parser/plugins/xlsx/relationships.d.ts.map +1 -1
  89. package/dist/esm/excel-parser/plugins/xlsx/relationships.js +9 -0
  90. package/dist/esm/excel-parser/plugins/xlsx/theme.d.ts +1 -1
  91. package/dist/esm/excel-parser/types.d.ts +9 -1
  92. package/dist/esm/excel-parser/types.d.ts.map +1 -1
  93. package/dist/esm/excel-parser/workbook.d.ts +1 -0
  94. package/dist/esm/excel-parser/workbook.d.ts.map +1 -1
  95. package/dist/esm/excel-parser/workbook.js +4 -0
  96. package/dist/esm/excel-parser/worker.js +2 -0
  97. package/dist/esm/exporter/ods/ods-export.d.ts.map +1 -1
  98. package/dist/esm/exporter/ods/ods-export.js +238 -72
  99. package/dist/esm/exporter/xlsx/chart-builder.d.ts +7 -1
  100. package/dist/esm/exporter/xlsx/chart-builder.d.ts.map +1 -1
  101. package/dist/esm/exporter/xlsx/chart-builder.js +674 -58
  102. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts +16 -3
  103. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts.map +1 -1
  104. package/dist/esm/exporter/xlsx/form-controls-builder.js +29 -8
  105. package/dist/esm/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  106. package/dist/esm/exporter/xlsx/pivot-builder.js +187 -139
  107. package/dist/esm/exporter/xlsx/style-builder.d.ts +8 -2
  108. package/dist/esm/exporter/xlsx/style-builder.d.ts.map +1 -1
  109. package/dist/esm/exporter/xlsx/style-builder.js +28 -0
  110. package/dist/esm/exporter/xlsx/xlsx-export.d.ts +2 -2
  111. package/dist/esm/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  112. package/dist/esm/exporter/xlsx/xlsx-export.js +451 -197
  113. package/package.json +11 -4
@@ -1,7 +1,9 @@
1
- import { __assign, __awaiter, __generator, __values } from "tslib";
1
+ import { __assign, __awaiter, __generator, __read, __spreadArray, __values } from "tslib";
2
2
  import { generateSelectionsFromFormula } from "@rowsncolumns/utils";
3
3
  import { uuid } from "@rowsncolumns/utils";
4
+ import { XMLParser } from "fast-xml-parser";
4
5
  import { get } from "lodash-es";
6
+ import { anchorPlacementFromEditAs } from "./drawing";
5
7
  /**
6
8
  * Pick the data sheetId for a parsed selection. Honours the explicit
7
9
  * sheet prefix in the chart's formula reference (cross-sheet charts);
@@ -50,12 +52,13 @@ function toInt(value) {
50
52
  }
51
53
  export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParser, xmlParser, sheetDimensions, resolveSheetId) {
52
54
  return __awaiter(this, void 0, void 0, function () {
53
- var chartPath, drawingDir, chartContent, chartXml, chart, chartSpaceRoot, roundedCornersRaw, roundedCornersVal, roundedCorners, chartId, title, titleTextFormat, chartType, plotArea, series, domains, dataRange, bubbleSizes, scatterStyle, hiddenDimensionStrategy, position, legend, dataLabels, _a, valueAxisOptions, secondaryValueAxisOptions, categoryAxisOptions, doughnutHoleSize, ofPieOptions, threeDSourceChartType, radarStyle, binCount, barLayout, err_1;
54
- var _b;
55
- return __generator(this, function (_c) {
56
- switch (_c.label) {
55
+ var chartPath, drawingDir, chartContent, chartXml, chart, chartSpaceRoot, roundedCornersRaw, roundedCornersVal, roundedCorners, chartStyle, pivotSourceName, pivotSourceFormatId, pivotFormats, pivotFieldButtons, chartSpacePr, chartAreaFill, chartAreaBorder, chartId, title, titleTextFormat, chartType, plotArea, series, domains, dataRange, bubbleSizes, scatterStyle, hiddenDimensionStrategy, emptyCells, showNaAsEmpty, position, legend, dataLabels, _a, valueAxisOptions, secondaryValueAxisOptions, categoryAxisOptions, doughnutHoleSize, explosion, ofPieOptions, threeDSourceChartType, radarStyle, binCount, barLayout, lineLayout, stockVariant, err_1;
56
+ var _b, _c;
57
+ var _d, _e, _f, _g;
58
+ return __generator(this, function (_h) {
59
+ switch (_h.label) {
57
60
  case 0:
58
- _c.trys.push([0, 2, , 3]);
61
+ _h.trys.push([0, 2, , 3]);
59
62
  chartPath = chartTarget;
60
63
  drawingDir = drawingPath.substring(0, drawingPath.lastIndexOf("/"));
61
64
  if (chartPath.startsWith("../")) {
@@ -66,7 +69,7 @@ export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParse
66
69
  }
67
70
  return [4 /*yield*/, zipParser.getText(chartPath)];
68
71
  case 1:
69
- chartContent = _c.sent();
72
+ chartContent = _h.sent();
70
73
  if (!chartContent) {
71
74
  return [2 /*return*/, null];
72
75
  }
@@ -90,12 +93,22 @@ export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParse
90
93
  "c:roundedCorners",
91
94
  "roundedCorners",
92
95
  ]);
93
- roundedCornersVal = (_b = roundedCornersRaw === null || roundedCornersRaw === void 0 ? void 0 : roundedCornersRaw.a$) === null || _b === void 0 ? void 0 : _b.val;
96
+ roundedCornersVal = (_d = roundedCornersRaw === null || roundedCornersRaw === void 0 ? void 0 : roundedCornersRaw.a$) === null || _d === void 0 ? void 0 : _d.val;
94
97
  roundedCorners = roundedCornersVal === "1" ||
95
98
  roundedCornersVal === "true" ||
96
99
  roundedCornersVal === true
97
100
  ? true
98
101
  : undefined;
102
+ chartStyle = extractChartStyle(chartSpaceRoot);
103
+ pivotSourceName = extractPivotSourceName(chartSpaceRoot);
104
+ pivotSourceFormatId = extractPivotSourceFormatId(chartSpaceRoot);
105
+ pivotFormats = extractPivotFormats(chart);
106
+ if (pivotFormats)
107
+ attachPivotFormatBodies(pivotFormats, chartContent);
108
+ pivotFieldButtons = extractPivotFieldButtons(chartSpaceRoot);
109
+ chartSpacePr = (_e = get(chartSpaceRoot, "c:spPr")) !== null && _e !== void 0 ? _e : get(chartSpaceRoot, "spPr");
110
+ chartAreaFill = extractSrgbHex((_f = get(chartSpacePr, "a:solidFill")) !== null && _f !== void 0 ? _f : get(chartSpacePr, "solidFill"));
111
+ chartAreaBorder = extractSrgbHex((_g = get(chartSpacePr, "a:ln.a:solidFill")) !== null && _g !== void 0 ? _g : get(chartSpacePr, "ln.solidFill"));
99
112
  chartId = uuid();
100
113
  title = extractChartTitle(chart);
101
114
  titleTextFormat = extractChartTitleTextFormat(chart);
@@ -109,6 +122,8 @@ export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParse
109
122
  : undefined;
110
123
  scatterStyle = chartType === "scatter" ? extractScatterStyle(plotArea) : undefined;
111
124
  hiddenDimensionStrategy = extractHiddenDimensionStrategy(chart);
125
+ emptyCells = extractEmptyCellsPolicy(chart);
126
+ showNaAsEmpty = extractShowNaAsEmpty(chart);
112
127
  position = extractChartPosition(anchor, sheetId, sheetDimensions);
113
128
  if (!position) {
114
129
  console.log("Could not extract chart position");
@@ -118,6 +133,9 @@ export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParse
118
133
  dataLabels = extractDataLabelsOptions(plotArea, chartType);
119
134
  _a = extractAxisOptions(plotArea), valueAxisOptions = _a.valueAxisOptions, secondaryValueAxisOptions = _a.secondaryValueAxisOptions, categoryAxisOptions = _a.categoryAxisOptions;
120
135
  doughnutHoleSize = chartType === "doughnut" ? extractDoughnutHoleSize(plotArea) : undefined;
136
+ explosion = chartType === "pie" || chartType === "doughnut"
137
+ ? extractExplosion(plotArea, chartType)
138
+ : undefined;
121
139
  ofPieOptions = chartType === "pie" ? extractOfPieOptions(plotArea) : undefined;
122
140
  threeDSourceChartType = extractThreeDSourceChartType(plotArea);
123
141
  radarStyle = chartType === "radar" ? extractRadarStyle(plotArea) : undefined;
@@ -127,9 +145,9 @@ export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParse
127
145
  barLayout = chartType === "bar" || chartType === "column"
128
146
  ? extractBarLayoutOptions(plotArea)
129
147
  : undefined;
130
- return [2 /*return*/, {
131
- chartId: chartId,
132
- spec: __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ title: title }, (titleTextFormat ? { titleTextFormat: titleTextFormat } : {})), { chartType: chartType, domains: domains, series: series, dataRange: dataRange, hiddenDimensionStrategy: hiddenDimensionStrategy }), (chartType === "scatter" || chartType === "bubble"
148
+ lineLayout = chartType === "line" ? extractLineChartOptions(plotArea, series) : undefined;
149
+ stockVariant = chartType === "stock" ? extractStockVariant(plotArea) : undefined;
150
+ return [2 /*return*/, __assign(__assign({ chartId: chartId, spec: __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ title: title }, (titleTextFormat ? { titleTextFormat: titleTextFormat } : {})), { chartType: chartType, domains: domains, series: series, dataRange: dataRange, hiddenDimensionStrategy: hiddenDimensionStrategy }), (emptyCells && emptyCells !== "gaps" ? { emptyCells: emptyCells } : {})), (showNaAsEmpty === false ? { showNaAsEmpty: showNaAsEmpty } : {})), (chartType === "scatter" || chartType === "bubble"
133
151
  ? { bubbleLabels: [] }
134
152
  : {})), (bubbleSizes && bubbleSizes.length ? { bubbleSizes: bubbleSizes } : {})), (scatterStyle
135
153
  ? { scatterStyle: scatterStyle }
@@ -137,7 +155,7 @@ export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParse
137
155
  ? { secondaryValueAxisOptions: secondaryValueAxisOptions }
138
156
  : {})), (categoryAxisOptions ? { categoryAxisOptions: categoryAxisOptions } : {})), (typeof doughnutHoleSize === "number"
139
157
  ? { doughnutHoleSize: doughnutHoleSize }
140
- : {})), (ofPieOptions
158
+ : {})), (typeof explosion === "number" ? { explosion: explosion } : {})), (ofPieOptions
141
159
  ? __assign({ sourceChartType: "OF_PIE" }, ofPieOptions) : {})), (threeDSourceChartType && !ofPieOptions
142
160
  ? { sourceChartType: threeDSourceChartType }
143
161
  : {})), (radarStyle ? { radarStyle: radarStyle } : {})), (typeof binCount === "number" ? { binCount: binCount } : {})), ((barLayout === null || barLayout === void 0 ? void 0 : barLayout.stackedType)
@@ -146,13 +164,12 @@ export function processChart(chartTarget, drawingPath, anchor, sheetId, zipParse
146
164
  ? { overlap: barLayout.overlap }
147
165
  : {})), (typeof (barLayout === null || barLayout === void 0 ? void 0 : barLayout.gapWidth) === "number"
148
166
  ? { gapWidth: barLayout.gapWidth }
149
- : {})), (roundedCorners ? { roundedCorners: roundedCorners } : {})),
150
- position: position,
151
- id: chartId,
152
- type: "chart",
153
- }];
167
+ : {})), ((lineLayout === null || lineLayout === void 0 ? void 0 : lineLayout.stackedType)
168
+ ? { stackedType: lineLayout.stackedType }
169
+ : {})), ((lineLayout === null || lineLayout === void 0 ? void 0 : lineLayout.showMarkers) ? { showMarkers: true } : {})), (stockVariant ? { stockVariant: stockVariant } : {})), (roundedCorners ? { roundedCorners: roundedCorners } : {})), (chartStyle !== undefined ? { chartStyle: chartStyle } : {})), (chartAreaFill ? { backgroundColor: chartAreaFill } : {})), (pivotSourceName ? (_b = {}, _b[PIVOT_SOURCE_NAME_KEY] = pivotSourceName, _b) : {})), (pivotSourceFormatId
170
+ ? (_c = {}, _c[PIVOT_SOURCE_FORMAT_ID_KEY] = pivotSourceFormatId, _c) : {})), (pivotFormats ? { pivotFormats: pivotFormats } : {})), (pivotFieldButtons ? { pivotFieldButtons: pivotFieldButtons } : {})), position: position }, (chartAreaBorder ? { borderColor: chartAreaBorder } : {})), { id: chartId, type: "chart" })];
154
171
  case 2:
155
- err_1 = _c.sent();
172
+ err_1 = _h.sent();
156
173
  console.log("Error processing chart:", err_1);
157
174
  return [2 /*return*/, null];
158
175
  case 3: return [2 /*return*/];
@@ -220,8 +237,19 @@ function getSeriesElements(plotArea, chartType) {
220
237
  ]);
221
238
  case "radar":
222
239
  return getWithFallback(plotArea, ["c:radarChart.c:ser", "radarChart.ser"]);
223
- case "stock":
224
- return getWithFallback(plotArea, ["c:stockChart.c:ser", "stockChart.ser"]);
240
+ case "stock": {
241
+ // VHLC / VOHLC: the volume series lives in a sibling <c:barChart>
242
+ // and comes first (utils/stock.ts STOCK_ROLES); the price series
243
+ // follow in the <c:stockChart>.
244
+ var toArray = function (value) {
245
+ return value === undefined || value === null
246
+ ? []
247
+ : Array.isArray(value)
248
+ ? value
249
+ : [value];
250
+ };
251
+ return __spreadArray(__spreadArray([], __read(toArray(getWithFallback(plotArea, ["c:barChart.c:ser", "barChart.ser"]))), false), __read(toArray(getWithFallback(plotArea, ["c:stockChart.c:ser", "stockChart.ser"]))), false);
252
+ }
225
253
  case "scatter":
226
254
  return getWithFallback(plotArea, [
227
255
  "c:scatterChart.c:ser",
@@ -441,6 +469,62 @@ export function extractHiddenDimensionStrategy(chart) {
441
469
  var skipHidden = plotVisOnly === "1" || plotVisOnly === "true" || plotVisOnly === true;
442
470
  return skipHidden ? "SKIP_HIDDEN_ROWS_AND_COLUMNS" : "SHOW_ALL";
443
471
  }
472
+ /**
473
+ * `<c:dispBlanksAs val="gap|zero|span"/>` — Excel's "Show empty cells as"
474
+ * (Select Data → Hidden and Empty Cells). `span` is "Connect data points
475
+ * with line".
476
+ */
477
+ export function extractEmptyCellsPolicy(chart) {
478
+ var val = getWithFallback(chart, [
479
+ "c:dispBlanksAs.a$.val",
480
+ "dispBlanksAs.a$.val",
481
+ ]);
482
+ switch (val) {
483
+ case "gap":
484
+ return "gaps";
485
+ case "zero":
486
+ return "zero";
487
+ case "span":
488
+ return "connect";
489
+ default:
490
+ return undefined;
491
+ }
492
+ }
493
+ /**
494
+ * Excel 2016+ "Show #N/A as an empty cell":
495
+ * `<c:chart><c:extLst><c:ext uri="{56B9EC1D-…}"><c16r3:dataDisplayOptions16>
496
+ * <c16r3:dispNaAsBlank val="0|1"/>`. Undefined when the file predates the
497
+ * option (Excel then treats #N/A the legacy way — as if `val="0"`, but the
498
+ * spec leaves the default to the renderer).
499
+ */
500
+ export function extractShowNaAsEmpty(chart) {
501
+ var e_4, _a;
502
+ var extLst = getWithFallback(chart, ["c:extLst", "extLst"]);
503
+ if (!extLst)
504
+ return undefined;
505
+ var extNode = getWithFallback(extLst, ["c:ext", "ext"]);
506
+ var exts = Array.isArray(extNode) ? extNode : extNode ? [extNode] : [];
507
+ try {
508
+ for (var exts_1 = __values(exts), exts_1_1 = exts_1.next(); !exts_1_1.done; exts_1_1 = exts_1.next()) {
509
+ var ext = exts_1_1.value;
510
+ var val = getWithFallback(ext, [
511
+ "c16r3:dataDisplayOptions16.c16r3:dispNaAsBlank.a$.val",
512
+ "dataDisplayOptions16.dispNaAsBlank.a$.val",
513
+ ]);
514
+ if (val !== undefined) {
515
+ return val === "1" || val === "true" || val === true;
516
+ }
517
+ }
518
+ }
519
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
520
+ finally {
521
+ try {
522
+ if (exts_1_1 && !exts_1_1.done && (_a = exts_1.return)) _a.call(exts_1);
523
+ }
524
+ finally { if (e_4) throw e_4.error; }
525
+ }
526
+ return undefined;
527
+ }
444
528
  /**
445
529
  * Read the chart title's text formatting. Excel chart titles can be
446
530
  * styled two ways:
@@ -452,6 +536,58 @@ export function extractHiddenDimensionStrategy(chart) {
452
536
  * the more explicit signal). Returns `undefined` when neither carries
453
537
  * formatting so the renderer falls back to its theme defaults.
454
538
  */
539
+ /**
540
+ * `<c:chartSpace>` → the Chart Styles id, from `<c14:style>` in the
541
+ * mc:Choice (id + 100) or the plain `<c:style>`. Excel's unstyled default
542
+ * (2) is returned as `undefined` so it stays implicit on the spec.
543
+ */
544
+ function extractChartStyle(chartSpaceRoot) {
545
+ var e_5, _a;
546
+ var alternates = [
547
+ getWithFallback(chartSpaceRoot, ["mc:AlternateContent", "AlternateContent"]),
548
+ ]
549
+ .flat()
550
+ .filter(Boolean);
551
+ var raw;
552
+ try {
553
+ for (var alternates_1 = __values(alternates), alternates_1_1 = alternates_1.next(); !alternates_1_1.done; alternates_1_1 = alternates_1.next()) {
554
+ var alternate = alternates_1_1.value;
555
+ var c14 = getWithFallback(alternate, [
556
+ "mc:Choice.c14:style.a$.val",
557
+ "Choice.c14:style.a$.val",
558
+ "Choice.style.a$.val",
559
+ ]);
560
+ if (c14 !== undefined) {
561
+ var value = Number(c14);
562
+ raw = value > 100 ? value - 100 : value;
563
+ break;
564
+ }
565
+ }
566
+ }
567
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
568
+ finally {
569
+ try {
570
+ if (alternates_1_1 && !alternates_1_1.done && (_a = alternates_1.return)) _a.call(alternates_1);
571
+ }
572
+ finally { if (e_5) throw e_5.error; }
573
+ }
574
+ if (raw === undefined) {
575
+ raw = getWithFallback(chartSpaceRoot, ["c:style.a$.val", "style.a$.val"]);
576
+ }
577
+ var style = Number(raw);
578
+ if (!Number.isInteger(style) || style < 1 || style > 48 || style === 2) {
579
+ return undefined;
580
+ }
581
+ return style;
582
+ }
583
+ /** `<a:solidFill><a:srgbClr val="RRGGBB"/>` → `#RRGGBB`; theme fills are ignored. */
584
+ function extractSrgbHex(solidFill) {
585
+ var _a;
586
+ var raw = (_a = get(solidFill, "a:srgbClr.a$.val")) !== null && _a !== void 0 ? _a : get(solidFill, "srgbClr.a$.val");
587
+ return typeof raw === "string" && /^[0-9a-fA-F]{6}$/.test(raw)
588
+ ? "#".concat(raw.toUpperCase())
589
+ : undefined;
590
+ }
455
591
  function extractChartTitleTextFormat(chart) {
456
592
  var _a, _b, _c;
457
593
  var title = (_a = get(chart, "c:title")) !== null && _a !== void 0 ? _a : get(chart, "title");
@@ -464,6 +600,416 @@ function extractChartTitleTextFormat(chart) {
464
600
  var txPr = (_c = get(title, "c:txPr")) !== null && _c !== void 0 ? _c : get(title, "txPr");
465
601
  return extractTextProperties(txPr);
466
602
  }
603
+ /**
604
+ * Transient spec key carrying `<c:pivotSource><c:name>` until the workbook's
605
+ * pivots are known; `bindPivotChartsToPivotTables` turns it into
606
+ * `pivotTableId` and removes it.
607
+ */
608
+ export var PIVOT_SOURCE_NAME_KEY = "__pivotSourceName";
609
+ /**
610
+ * Transient spec key carrying `<c:pivotSource><c:fmtId>` alongside the
611
+ * name; becomes `pivotSource.formatId` once the chart binds to its pivot.
612
+ */
613
+ export var PIVOT_SOURCE_FORMAT_ID_KEY = "__pivotSourceFormatId";
614
+ /**
615
+ * `<c:pivotSource><c:fmtId val="3"/>` — the id the pivot's `<chartFormats>`
616
+ * name this chart by. `0` is the exporter's default and stays implicit.
617
+ */
618
+ export function extractPivotSourceFormatId(chartSpaceRoot) {
619
+ var raw = getWithFallback(chartSpaceRoot, [
620
+ "c:pivotSource.c:fmtId.a$.val",
621
+ "pivotSource.fmtId.a$.val",
622
+ ]);
623
+ var id = toInt(raw);
624
+ return Number.isFinite(id) && id > 0 ? id : undefined;
625
+ }
626
+ /** `<c:pivotSource><c:name>[Book1.xlsx]Sheet1!PivotTable1</c:name>` → the name text. */
627
+ export function extractPivotSourceName(chartSpaceRoot) {
628
+ var raw = getWithFallback(chartSpaceRoot, [
629
+ "c:pivotSource.c:name.t$",
630
+ "c:pivotSource.c:name",
631
+ "pivotSource.name.t$",
632
+ "pivotSource.name",
633
+ ]);
634
+ var name = typeof raw === "string" ? raw.trim() : undefined;
635
+ return name ? name : undefined;
636
+ }
637
+ /**
638
+ * Split a pivotSource name into its sheet and pivot-table parts. The
639
+ * `[workbook]` prefix is dropped (it names the file the chart lived in);
640
+ * the sheet may be quoted (`'My Sheet'!PivotTable1`).
641
+ */
642
+ export function parsePivotSourceName(name) {
643
+ var withoutBook = name.replace(/^\[[^\]]*\]/, "");
644
+ var bang = withoutBook.lastIndexOf("!");
645
+ if (bang === -1) {
646
+ return withoutBook ? { pivotName: withoutBook } : undefined;
647
+ }
648
+ var pivotName = withoutBook.slice(bang + 1);
649
+ if (!pivotName)
650
+ return undefined;
651
+ var sheetTitle = withoutBook.slice(0, bang);
652
+ if (sheetTitle.startsWith("'") && sheetTitle.endsWith("'")) {
653
+ sheetTitle = sheetTitle.slice(1, -1).replace(/''/g, "'");
654
+ }
655
+ return { sheetTitle: sheetTitle || undefined, pivotName: pivotName };
656
+ }
657
+ /**
658
+ * Resolve every imported chart's `<c:pivotSource>` name to the id of the
659
+ * imported PivotTable it names (matched by pivot name, and by the pivot's
660
+ * target sheet when the name carries one). A name that matches no pivot
661
+ * leaves a plain chart — Excel converts a PivotChart whose pivot is gone
662
+ * to a static chart too. The transient key is always removed.
663
+ */
664
+ export function bindPivotChartsToPivotTables(charts, pivotTables, sheetTitleById) {
665
+ var e_6, _a;
666
+ var _b;
667
+ var _loop_1 = function (chart) {
668
+ var spec = chart.spec;
669
+ var raw = spec[PIVOT_SOURCE_NAME_KEY];
670
+ var formatId = spec[PIVOT_SOURCE_FORMAT_ID_KEY];
671
+ delete spec[PIVOT_SOURCE_FORMAT_ID_KEY];
672
+ if (raw === undefined)
673
+ return "continue";
674
+ delete spec[PIVOT_SOURCE_NAME_KEY];
675
+ var parsed = typeof raw === "string" ? parsePivotSourceName(raw) : undefined;
676
+ if (!parsed)
677
+ return "continue";
678
+ var byName = pivotTables.filter(function (pivot) { var _a; return ((_a = pivot.name) !== null && _a !== void 0 ? _a : "PivotTable".concat(pivot.pivotId)) === parsed.pivotName; });
679
+ var match = (_b = byName.find(function (pivot) {
680
+ var _a;
681
+ return parsed.sheetTitle === undefined ||
682
+ sheetTitleById.get((_a = pivot.targetPosition) === null || _a === void 0 ? void 0 : _a.sheetId) === parsed.sheetTitle;
683
+ })) !== null && _b !== void 0 ? _b : (parsed.sheetTitle === undefined ? byName[0] : undefined);
684
+ if (!match)
685
+ return "continue";
686
+ spec.pivotTableId = match.pivotId;
687
+ if (!spec.pivotSource) {
688
+ spec.pivotSource = { categoryAxis: "rows" };
689
+ }
690
+ if (typeof formatId === "number") {
691
+ spec.pivotSource.formatId = formatId;
692
+ }
693
+ };
694
+ try {
695
+ for (var charts_1 = __values(charts), charts_1_1 = charts_1.next(); !charts_1_1.done; charts_1_1 = charts_1.next()) {
696
+ var chart = charts_1_1.value;
697
+ _loop_1(chart);
698
+ }
699
+ }
700
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
701
+ finally {
702
+ try {
703
+ if (charts_1_1 && !charts_1_1.done && (_a = charts_1.return)) _a.call(charts_1);
704
+ }
705
+ finally { if (e_6) throw e_6.error; }
706
+ }
707
+ }
708
+ /**
709
+ * `<c:chart><c:pivotFmts><c:pivotFmt><c:idx val/>…` — the per pivot-item
710
+ * formats Excel re-applies on a re-plot; only the index and a literal
711
+ * fill colour are kept.
712
+ */
713
+ export function extractPivotFormats(chart) {
714
+ var e_7, _a;
715
+ var raw = getWithFallback(chart, ["c:pivotFmts.c:pivotFmt", "pivotFmts.pivotFmt"]);
716
+ if (raw === undefined)
717
+ return undefined;
718
+ var list = Array.isArray(raw) ? raw : [raw];
719
+ var formats = [];
720
+ try {
721
+ for (var list_1 = __values(list), list_1_1 = list_1.next(); !list_1_1.done; list_1_1 = list_1.next()) {
722
+ var fmt = list_1_1.value;
723
+ var idx = toInt(getWithFallback(fmt, ["c:idx.a$.val", "idx.a$.val"]));
724
+ var fill = getWithFallback(fmt, [
725
+ "c:spPr.a:solidFill.a:srgbClr.a$.val",
726
+ "spPr.solidFill.srgbClr.a$.val",
727
+ ]);
728
+ formats.push(__assign({ index: idx }, (typeof fill === "string" && fill ? { color: "#".concat(fill.toUpperCase()) } : {})));
729
+ }
730
+ }
731
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
732
+ finally {
733
+ try {
734
+ if (list_1_1 && !list_1_1.done && (_a = list_1.return)) _a.call(list_1);
735
+ }
736
+ finally { if (e_7) throw e_7.error; }
737
+ }
738
+ return formats.length ? formats : undefined;
739
+ }
740
+ /**
741
+ * Namespace URI → the prefix Excel writes for it. Bodies are stored with these
742
+ * canonical prefixes so a file that declared, say, `xmlns:c="…"` as `cs:` still
743
+ * round-trips through an exporter that declares `c:` / `a:` at the root.
744
+ */
745
+ export var CHART_XML_PREFIXES = {
746
+ "http://schemas.openxmlformats.org/drawingml/2006/chart": "c",
747
+ "http://schemas.openxmlformats.org/drawingml/2006/main": "a",
748
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships": "r",
749
+ "http://schemas.openxmlformats.org/markup-compatibility/2006": "mc",
750
+ "http://schemas.microsoft.com/office/drawing/2007/8/2/chart": "c14",
751
+ "http://schemas.microsoft.com/office/drawing/2012/chart": "c15",
752
+ "http://schemas.microsoft.com/office/drawing/2014/chart": "c16",
753
+ "http://schemas.microsoft.com/office/drawing/2015/06/chart": "c16r2",
754
+ "http://schemas.microsoft.com/office/drawing/2017/03/chart": "c16r3",
755
+ "http://schemas.microsoft.com/office/drawing/2010/main": "a14",
756
+ "http://schemas.microsoft.com/office/drawing/2014/main": "a16",
757
+ };
758
+ // Ordered parse of a chart part — the object parse the plugin uses drops the
759
+ // order of differently named siblings, which DrawingML schemas fix
760
+ // (`<a:gsLst>` before `<a:lin>`, `<a:bodyPr>` before `<a:p>`), so the verbatim
761
+ // bodies are read from a `preserveOrder` pass instead.
762
+ var orderedChartParser = new XMLParser({
763
+ ignoreAttributes: false,
764
+ preserveOrder: true,
765
+ attributeNamePrefix: "",
766
+ textNodeName: "t$",
767
+ trimValues: false,
768
+ processEntities: false,
769
+ });
770
+ var localName = function (tag) { return tag.slice(tag.indexOf(":") + 1); };
771
+ /**
772
+ * `preserveOrder` node → `ChartXmlElement`, prefixes canonicalised through the
773
+ * `xmlns:*` declarations seen so far (`declared`: prefix → URI); namespace
774
+ * declarations themselves are dropped — the exporters re-emit them.
775
+ */
776
+ var toChartXmlElement = function (node, declared) {
777
+ var e_8, _a, e_9, _b, e_10, _c;
778
+ var _d;
779
+ var tag = Object.keys(node).find(function (k) { return k !== ":@"; });
780
+ if (!tag)
781
+ return undefined;
782
+ var rawAttrs = ((_d = node[":@"]) !== null && _d !== void 0 ? _d : {});
783
+ var scope = new Map(declared);
784
+ try {
785
+ for (var _e = __values(Object.entries(rawAttrs)), _f = _e.next(); !_f.done; _f = _e.next()) {
786
+ var _g = __read(_f.value, 2), k = _g[0], v = _g[1];
787
+ if (k === "xmlns")
788
+ scope.set("", String(v));
789
+ else if (k.startsWith("xmlns:"))
790
+ scope.set(k.slice(6), String(v));
791
+ }
792
+ }
793
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
794
+ finally {
795
+ try {
796
+ if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
797
+ }
798
+ finally { if (e_8) throw e_8.error; }
799
+ }
800
+ var canonical = function (name) {
801
+ var at = name.indexOf(":");
802
+ var prefix = at === -1 ? "" : name.slice(0, at);
803
+ var uri = scope.get(prefix);
804
+ var known = uri ? CHART_XML_PREFIXES[uri] : undefined;
805
+ if (!known)
806
+ return name;
807
+ return "".concat(known, ":").concat(at === -1 ? name : name.slice(at + 1));
808
+ };
809
+ var attributes = {};
810
+ try {
811
+ for (var _h = __values(Object.entries(rawAttrs)), _j = _h.next(); !_j.done; _j = _h.next()) {
812
+ var _k = __read(_j.value, 2), k = _k[0], v = _k[1];
813
+ if (k === "xmlns" || k.startsWith("xmlns:"))
814
+ continue;
815
+ attributes[k.includes(":") ? canonical(k) : k] = String(v);
816
+ }
817
+ }
818
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
819
+ finally {
820
+ try {
821
+ if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
822
+ }
823
+ finally { if (e_9) throw e_9.error; }
824
+ }
825
+ var element = { tag: canonical(tag) };
826
+ if (Object.keys(attributes).length)
827
+ element.attributes = attributes;
828
+ var kids = Array.isArray(node[tag]) ? node[tag] : [];
829
+ var children = [];
830
+ var text;
831
+ try {
832
+ for (var kids_1 = __values(kids), kids_1_1 = kids_1.next(); !kids_1_1.done; kids_1_1 = kids_1.next()) {
833
+ var kid = kids_1_1.value;
834
+ if (!kid || typeof kid !== "object")
835
+ continue;
836
+ if ("t$" in kid) {
837
+ text = (text !== null && text !== void 0 ? text : "") + String(kid.t$);
838
+ continue;
839
+ }
840
+ var child = toChartXmlElement(kid, scope);
841
+ if (child)
842
+ children.push(child);
843
+ }
844
+ }
845
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
846
+ finally {
847
+ try {
848
+ if (kids_1_1 && !kids_1_1.done && (_c = kids_1.return)) _c.call(kids_1);
849
+ }
850
+ finally { if (e_10) throw e_10.error; }
851
+ }
852
+ if (children.length)
853
+ element.children = children;
854
+ else if (text !== undefined && text !== "")
855
+ element.text = text;
856
+ return element;
857
+ };
858
+ /**
859
+ * Read every `<c:pivotFmt>` body (its children after `<c:idx>`) verbatim from
860
+ * the chart part and attach it to the matching `pivotFormats` entry by index
861
+ * (rowsncolumns/spreadsheet#668 C-83). Gradient fills, theme colours, markers
862
+ * and data-label formatting Excel keeps per pivot item survive the round-trip
863
+ * that `color` (a literal solid fill) alone cannot carry.
864
+ */
865
+ export function attachPivotFormatBodies(formats, chartContent) {
866
+ var e_11, _a, e_12, _b, e_13, _c;
867
+ var _d, _e;
868
+ var ordered;
869
+ try {
870
+ ordered = orderedChartParser.parse(chartContent);
871
+ }
872
+ catch (_f) {
873
+ return;
874
+ }
875
+ var findPivotFmts = function (nodes, declared) {
876
+ var e_14, _a, e_15, _b;
877
+ var _c, _d;
878
+ try {
879
+ for (var nodes_1 = __values(nodes), nodes_1_1 = nodes_1.next(); !nodes_1_1.done; nodes_1_1 = nodes_1.next()) {
880
+ var node = nodes_1_1.value;
881
+ if (!node || typeof node !== "object")
882
+ continue;
883
+ var tag = Object.keys(node).find(function (k) { return k !== ":@"; });
884
+ // Text nodes (`{ t$ }`) have no element children to search.
885
+ if (!tag || !Array.isArray(node[tag]))
886
+ continue;
887
+ var scope = new Map(declared);
888
+ try {
889
+ for (var _e = (e_15 = void 0, __values(Object.entries(((_c = node[":@"]) !== null && _c !== void 0 ? _c : {})))), _f = _e.next(); !_f.done; _f = _e.next()) {
890
+ var _g = __read(_f.value, 2), k = _g[0], v = _g[1];
891
+ if (k === "xmlns")
892
+ scope.set("", String(v));
893
+ else if (k.startsWith("xmlns:"))
894
+ scope.set(k.slice(6), String(v));
895
+ }
896
+ }
897
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
898
+ finally {
899
+ try {
900
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
901
+ }
902
+ finally { if (e_15) throw e_15.error; }
903
+ }
904
+ if (localName(tag) === "pivotFmts")
905
+ return { node: node, declared: scope };
906
+ var found_1 = findPivotFmts(((_d = node[tag]) !== null && _d !== void 0 ? _d : []), scope);
907
+ if (found_1)
908
+ return found_1;
909
+ }
910
+ }
911
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
912
+ finally {
913
+ try {
914
+ if (nodes_1_1 && !nodes_1_1.done && (_a = nodes_1.return)) _a.call(nodes_1);
915
+ }
916
+ finally { if (e_14) throw e_14.error; }
917
+ }
918
+ return undefined;
919
+ };
920
+ var found = findPivotFmts(ordered, new Map());
921
+ if (!found)
922
+ return;
923
+ var fmtsTag = Object.keys(found.node).find(function (k) { return k !== ":@"; });
924
+ var byIndex = new Map();
925
+ try {
926
+ for (var _g = __values(((_d = found.node[fmtsTag]) !== null && _d !== void 0 ? _d : [])), _h = _g.next(); !_h.done; _h = _g.next()) {
927
+ var fmt = _h.value;
928
+ if (!fmt || typeof fmt !== "object")
929
+ continue;
930
+ var fmtTag = Object.keys(fmt).find(function (k) { return k !== ":@"; });
931
+ if (!fmtTag || localName(fmtTag) !== "pivotFmt" || !Array.isArray(fmt[fmtTag]))
932
+ continue;
933
+ var kids = fmt[fmtTag];
934
+ var index = void 0;
935
+ var body = [];
936
+ try {
937
+ for (var kids_2 = (e_12 = void 0, __values(kids)), kids_2_1 = kids_2.next(); !kids_2_1.done; kids_2_1 = kids_2.next()) {
938
+ var kid = kids_2_1.value;
939
+ if (!kid || typeof kid !== "object")
940
+ continue;
941
+ var kidTag = Object.keys(kid).find(function (k) { return k !== ":@"; });
942
+ if (!kidTag)
943
+ continue;
944
+ if (localName(kidTag) === "idx") {
945
+ index = toInt((_e = kid[":@"]) === null || _e === void 0 ? void 0 : _e.val);
946
+ continue;
947
+ }
948
+ var element = toChartXmlElement(kid, found.declared);
949
+ if (element)
950
+ body.push(element);
951
+ }
952
+ }
953
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
954
+ finally {
955
+ try {
956
+ if (kids_2_1 && !kids_2_1.done && (_b = kids_2.return)) _b.call(kids_2);
957
+ }
958
+ finally { if (e_12) throw e_12.error; }
959
+ }
960
+ if (index !== undefined && body.length)
961
+ byIndex.set(index, body);
962
+ }
963
+ }
964
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
965
+ finally {
966
+ try {
967
+ if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
968
+ }
969
+ finally { if (e_11) throw e_11.error; }
970
+ }
971
+ try {
972
+ for (var formats_1 = __values(formats), formats_1_1 = formats_1.next(); !formats_1_1.done; formats_1_1 = formats_1.next()) {
973
+ var format = formats_1_1.value;
974
+ var body = byIndex.get(format.index);
975
+ if (body)
976
+ format.body = body;
977
+ }
978
+ }
979
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
980
+ finally {
981
+ try {
982
+ if (formats_1_1 && !formats_1_1.done && (_c = formats_1.return)) _c.call(formats_1);
983
+ }
984
+ finally { if (e_13) throw e_13.error; }
985
+ }
986
+ }
987
+ var PIVOT_OPTIONS_EXT_URI = "{781A3756-C4B2-4CAC-9D66-4F8BD8637D16}";
988
+ /**
989
+ * Excel's Field Buttons choices — `<c14:pivotOptions>` in the chartSpace
990
+ * `<c:extLst>`: `dropZoneFilter` / `dropZoneCategories` / `dropZoneData` /
991
+ * `dropZoneSeries` / `dropZonesVisible`, each `1` unless hidden. Only the
992
+ * hidden ones are recorded (every button shows by default).
993
+ */
994
+ export function extractPivotFieldButtons(chartSpaceRoot) {
995
+ var extList = getWithFallback(chartSpaceRoot, ["c:extLst.c:ext", "extLst.ext"]);
996
+ if (extList === undefined)
997
+ return undefined;
998
+ var exts = Array.isArray(extList) ? extList : [extList];
999
+ var ext = exts.find(function (e) { var _a; return ((_a = e === null || e === void 0 ? void 0 : e.a$) === null || _a === void 0 ? void 0 : _a.uri) === PIVOT_OPTIONS_EXT_URI; });
1000
+ var options = getWithFallback(ext, ["c14:pivotOptions", "pivotOptions"]);
1001
+ if (!options)
1002
+ return undefined;
1003
+ var isHidden = function (element) {
1004
+ var val = getWithFallback(options, [
1005
+ "c14:".concat(element, ".a$.val"),
1006
+ "".concat(element, ".a$.val"),
1007
+ ]);
1008
+ return val === "0" || val === "false" || val === false;
1009
+ };
1010
+ var buttons = __assign(__assign(__assign(__assign(__assign({}, (isHidden("dropZonesVisible") ? { visible: false } : {})), (isHidden("dropZoneFilter") ? { reportFilter: false } : {})), (isHidden("dropZoneCategories") ? { axis: false } : {})), (isHidden("dropZoneSeries") ? { legend: false } : {})), (isHidden("dropZoneData") ? { value: false } : {}));
1011
+ return Object.keys(buttons).length ? buttons : undefined;
1012
+ }
467
1013
  export function extractChartTitle(chart) {
468
1014
  // Try different possible paths for chart title
469
1015
  var title =
@@ -518,12 +1064,19 @@ export function determineChartType(chart) {
518
1064
  var c15Type = detectC15ChartType(plotArea);
519
1065
  if (c15Type)
520
1066
  return c15Type;
521
- var barChart = getWithFallback(plotArea, [
1067
+ // Excel's VHLC / VOHLC stock charts pair a <c:barChart> (the volume
1068
+ // series) with the <c:stockChart>, so the stock group must win over the
1069
+ // bar scan below.
1070
+ if (getWithFallback(plotArea, ["c:stockChart", "stockChart"]))
1071
+ return "stock";
1072
+ // A chart whose secondary axis group is split into its own container
1073
+ // carries an array here; the primary group comes first.
1074
+ var barChart = firstGroup(getWithFallback(plotArea, [
522
1075
  "c:barChart",
523
1076
  "barChart",
524
1077
  "c:bar3DChart",
525
1078
  "bar3DChart",
526
- ]);
1079
+ ]));
527
1080
  if (barChart) {
528
1081
  var direction = get(barChart, "c:barDir.a$.val") ||
529
1082
  get(barChart, "c:barDir.a$.t$") ||
@@ -571,8 +1124,6 @@ export function determineChartType(chart) {
571
1124
  return "area";
572
1125
  if (getWithFallback(plotArea, ["c:radarChart", "radarChart"]))
573
1126
  return "radar";
574
- if (getWithFallback(plotArea, ["c:stockChart", "stockChart"]))
575
- return "stock";
576
1127
  // Scatter and bubble — both use c:xVal/c:yVal series shape (not
577
1128
  // c:cat/c:val like other charts). Bubble additionally has c:bubbleSize.
578
1129
  if (getWithFallback(plotArea, ["c:scatterChart", "scatterChart"]))
@@ -618,7 +1169,7 @@ export function extractThreeDSourceChartType(plotArea) {
618
1169
  * fast-xml-parser normalizes lone children to objects.
619
1170
  */
620
1171
  function detectC15ChartType(plotArea) {
621
- var e_4, _a, e_5, _b;
1172
+ var e_16, _a, e_17, _b;
622
1173
  if (!plotArea)
623
1174
  return null;
624
1175
  // Empty c15 elements (`<c15:histogramChart/>`) parse to "" — truthy
@@ -650,12 +1201,12 @@ function detectC15ChartType(plotArea) {
650
1201
  return "funnel";
651
1202
  }
652
1203
  }
653
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
1204
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
654
1205
  finally {
655
1206
  try {
656
1207
  if (choices_1_1 && !choices_1_1.done && (_a = choices_1.return)) _a.call(choices_1);
657
1208
  }
658
- finally { if (e_4) throw e_4.error; }
1209
+ finally { if (e_16) throw e_16.error; }
659
1210
  }
660
1211
  }
661
1212
  }
@@ -670,8 +1221,8 @@ function detectC15ChartType(plotArea) {
670
1221
  return null;
671
1222
  var exts = Array.isArray(extNode) ? extNode : [extNode];
672
1223
  try {
673
- for (var exts_1 = __values(exts), exts_1_1 = exts_1.next(); !exts_1_1.done; exts_1_1 = exts_1.next()) {
674
- var ext = exts_1_1.value;
1224
+ for (var exts_2 = __values(exts), exts_2_1 = exts_2.next(); !exts_2_1.done; exts_2_1 = exts_2.next()) {
1225
+ var ext = exts_2_1.value;
675
1226
  if (!ext)
676
1227
  continue;
677
1228
  if (hasKey(ext, "c15:histogramChart") || hasKey(ext, "histogramChart"))
@@ -684,12 +1235,12 @@ function detectC15ChartType(plotArea) {
684
1235
  return "funnel";
685
1236
  }
686
1237
  }
687
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
1238
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
688
1239
  finally {
689
1240
  try {
690
- if (exts_1_1 && !exts_1_1.done && (_b = exts_1.return)) _b.call(exts_1);
1241
+ if (exts_2_1 && !exts_2_1.done && (_b = exts_2.return)) _b.call(exts_2);
691
1242
  }
692
- finally { if (e_5) throw e_5.error; }
1243
+ finally { if (e_17) throw e_17.error; }
693
1244
  }
694
1245
  return null;
695
1246
  }
@@ -698,7 +1249,7 @@ function detectC15ChartType(plotArea) {
698
1249
  * marker. Returns undefined if absent.
699
1250
  */
700
1251
  export function extractC15HistogramBinCount(plotArea) {
701
- var e_6, _a, e_7, _b;
1252
+ var e_18, _a, e_19, _b;
702
1253
  var _c, _d, _e, _f;
703
1254
  if (!plotArea)
704
1255
  return undefined;
@@ -733,12 +1284,12 @@ export function extractC15HistogramBinCount(plotArea) {
733
1284
  return v;
734
1285
  }
735
1286
  }
736
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
1287
+ catch (e_18_1) { e_18 = { error: e_18_1 }; }
737
1288
  finally {
738
1289
  try {
739
1290
  if (choices_2_1 && !choices_2_1.done && (_a = choices_2.return)) _a.call(choices_2);
740
1291
  }
741
- finally { if (e_6) throw e_6.error; }
1292
+ finally { if (e_18) throw e_18.error; }
742
1293
  }
743
1294
  }
744
1295
  // Phase 5.5 (legacy): histogram inside c:extLst > c:ext marker.
@@ -750,20 +1301,20 @@ export function extractC15HistogramBinCount(plotArea) {
750
1301
  return undefined;
751
1302
  var exts = Array.isArray(extNode) ? extNode : [extNode];
752
1303
  try {
753
- for (var exts_2 = __values(exts), exts_2_1 = exts_2.next(); !exts_2_1.done; exts_2_1 = exts_2.next()) {
754
- var ext = exts_2_1.value;
1304
+ for (var exts_3 = __values(exts), exts_3_1 = exts_3.next(); !exts_3_1.done; exts_3_1 = exts_3.next()) {
1305
+ var ext = exts_3_1.value;
755
1306
  var hist = (_f = (_e = ext === null || ext === void 0 ? void 0 : ext["c15:histogramChart"]) !== null && _e !== void 0 ? _e : ext === null || ext === void 0 ? void 0 : ext["histogramChart"]) !== null && _f !== void 0 ? _f : null;
756
1307
  var v = readBinCount(hist);
757
1308
  if (v !== undefined)
758
1309
  return v;
759
1310
  }
760
1311
  }
761
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
1312
+ catch (e_19_1) { e_19 = { error: e_19_1 }; }
762
1313
  finally {
763
1314
  try {
764
- if (exts_2_1 && !exts_2_1.done && (_b = exts_2.return)) _b.call(exts_2);
1315
+ if (exts_3_1 && !exts_3_1.done && (_b = exts_3.return)) _b.call(exts_3);
765
1316
  }
766
- finally { if (e_7) throw e_7.error; }
1317
+ finally { if (e_19) throw e_19.error; }
767
1318
  }
768
1319
  return undefined;
769
1320
  }
@@ -807,6 +1358,89 @@ var CHART_TYPE_CONTAINERS = [
807
1358
  isXY: true,
808
1359
  },
809
1360
  ];
1361
+ /**
1362
+ * A series' position in the chart — `<c:order>` (Excel's plot / legend
1363
+ * order), falling back to `<c:idx>`; NaN when the series carries neither.
1364
+ */
1365
+ function seriesOrderOf(ser) {
1366
+ var _a, _b, _c;
1367
+ var raw = (_c = (_b = (_a = get(ser, "c:order.a$.val")) !== null && _a !== void 0 ? _a : get(ser, "order.a$.val")) !== null && _b !== void 0 ? _b : get(ser, "c:idx.a$.val")) !== null && _c !== void 0 ? _c : get(ser, "idx.a$.val");
1368
+ var n = Number(raw);
1369
+ return raw === undefined || raw === null || raw === "" ? NaN : n;
1370
+ }
1371
+ /**
1372
+ * Put the collected series back in Excel's `<c:order>`: a chart split into
1373
+ * several containers (one per chart type and per axis group) lists them
1374
+ * container by container, which is not the authored order. Only sorts
1375
+ * when every series carries an order (older / hand-written files without
1376
+ * one keep their document order).
1377
+ */
1378
+ function sortSeriesByOrder(series, orders) {
1379
+ if (series.length < 2 || orders.length !== series.length)
1380
+ return series;
1381
+ if (orders.some(function (order) { return !Number.isFinite(order); }))
1382
+ return series;
1383
+ return series
1384
+ .map(function (entry, index) { return ({ entry: entry, order: orders[index], index: index }); })
1385
+ .sort(function (a, b) { return a.order - b.order || a.index - b.index; })
1386
+ .map(function (_a) {
1387
+ var entry = _a.entry;
1388
+ return entry;
1389
+ });
1390
+ }
1391
+ /**
1392
+ * The first chart-type container of a group that may be split into one
1393
+ * container per axis group (primary first, then the secondary group).
1394
+ */
1395
+ function firstGroup(node) {
1396
+ return Array.isArray(node) ? node[0] : node;
1397
+ }
1398
+ /** `<c:axId val>` values of an axis element or a chart-type container. */
1399
+ function axisIdsOf(node) {
1400
+ var raw = getWithFallback(node, ["c:axId", "axId"]);
1401
+ if (!raw)
1402
+ return [];
1403
+ var list = Array.isArray(raw) ? raw : [raw];
1404
+ return list
1405
+ .map(function (entry) { var _a, _b, _c, _d; return (_d = (_b = (_a = entry === null || entry === void 0 ? void 0 : entry.a$) === null || _a === void 0 ? void 0 : _a.val) !== null && _b !== void 0 ? _b : (_c = entry === null || entry === void 0 ? void 0 : entry.a$) === null || _c === void 0 ? void 0 : _c.t$) !== null && _d !== void 0 ? _d : entry; })
1406
+ .filter(function (id) { return id != null; })
1407
+ .map(String);
1408
+ }
1409
+ /**
1410
+ * The axis ids of the plot area's SECONDARY axis group — every `<c:valAx>`,
1411
+ * `<c:catAx>` and `<c:dateAx>` after the first of its kind. Excel keeps one
1412
+ * category axis and one value axis per axis group; a chart-type container
1413
+ * whose `<c:axId>`s name any of these ids plots its series on the
1414
+ * secondary group (Excel's "Plot Series On: Secondary Axis").
1415
+ */
1416
+ function secondaryAxisGroupIds(plotArea) {
1417
+ var e_20, _a;
1418
+ var ids = new Set();
1419
+ try {
1420
+ for (var _b = __values(["c:valAx", "valAx", "c:catAx", "catAx", "c:dateAx", "dateAx"]), _c = _b.next(); !_c.done; _c = _b.next()) {
1421
+ var key = _c.value;
1422
+ var axes = get(plotArea, key);
1423
+ if (!axes)
1424
+ continue;
1425
+ var list = Array.isArray(axes) ? axes : [axes];
1426
+ list.slice(1).forEach(function (axis) { return axisIdsOf(axis).forEach(function (id) { return ids.add(id); }); });
1427
+ }
1428
+ }
1429
+ catch (e_20_1) { e_20 = { error: e_20_1 }; }
1430
+ finally {
1431
+ try {
1432
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1433
+ }
1434
+ finally { if (e_20) throw e_20.error; }
1435
+ }
1436
+ return ids;
1437
+ }
1438
+ /** True when a chart-type container's `<c:axId>`s bind it to the secondary axis group. */
1439
+ function isSecondaryGroupContainer(container, secondaryIds) {
1440
+ if (!secondaryIds.size)
1441
+ return false;
1442
+ return axisIdsOf(container).some(function (id) { return secondaryIds.has(id); });
1443
+ }
810
1444
  /**
811
1445
  * Resolve a chart-formula range string (e.g.
812
1446
  * `'Data for the Chart'!$A$7:$A$26`) into the sources array our chart
@@ -827,7 +1461,7 @@ function resolveSourcesFromRef(ref, hostSheetId, resolveSheetId) {
827
1461
  * sparse indices). Returns `undefined` when no inline data is present.
828
1462
  */
829
1463
  function extractInlineValues(node) {
830
- var e_8, _a;
1464
+ var e_21, _a;
831
1465
  var _b, _c, _d, _e;
832
1466
  if (!node)
833
1467
  return undefined;
@@ -864,25 +1498,29 @@ function extractInlineValues(node) {
864
1498
  indexed.push({ idx: Number.isFinite(idx) ? idx : indexed.length, v: v });
865
1499
  }
866
1500
  }
867
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
1501
+ catch (e_21_1) { e_21 = { error: e_21_1 }; }
868
1502
  finally {
869
1503
  try {
870
1504
  if (ptArray_1_1 && !ptArray_1_1.done && (_a = ptArray_1.return)) _a.call(ptArray_1);
871
1505
  }
872
- finally { if (e_8) throw e_8.error; }
1506
+ finally { if (e_21) throw e_21.error; }
873
1507
  }
874
1508
  indexed.sort(function (a, b) { return a.idx - b.idx; });
875
1509
  return indexed.map(function (entry) { return entry.v; });
876
1510
  }
877
1511
  export function extractChartSeries(plotArea, chartType, sheetId, resolveSheetId) {
878
- var e_9, _a, e_10, _b;
1512
+ var e_22, _a, e_23, _b;
879
1513
  var _c, _d;
880
1514
  var series = [];
1515
+ var orders = [];
881
1516
  var seriesIndex = 0;
1517
+ var secondaryIds = secondaryAxisGroupIds(plotArea);
882
1518
  try {
883
- // Iterate through all chart type containers to support combo charts
884
- for (var CHART_TYPE_CONTAINERS_1 = __values(CHART_TYPE_CONTAINERS), CHART_TYPE_CONTAINERS_1_1 = CHART_TYPE_CONTAINERS_1.next(); !CHART_TYPE_CONTAINERS_1_1.done; CHART_TYPE_CONTAINERS_1_1 = CHART_TYPE_CONTAINERS_1.next()) {
885
- var container = CHART_TYPE_CONTAINERS_1_1.value;
1519
+ // Iterate through all chart type containers to support combo charts.
1520
+ // A stock chart's <c:barChart> is its volume series, not a combo member
1521
+ // — the stock path below reads both groups in role order.
1522
+ for (var _e = __values(chartType === "stock" ? [] : CHART_TYPE_CONTAINERS), _f = _e.next(); !_f.done; _f = _e.next()) {
1523
+ var container = _f.value;
886
1524
  var chartElement = getWithFallback(plotArea, container.paths);
887
1525
  if (!chartElement)
888
1526
  continue;
@@ -891,8 +1529,11 @@ export function extractChartSeries(plotArea, chartType, sheetId, resolveSheetId)
891
1529
  ? chartElement
892
1530
  : [chartElement];
893
1531
  try {
894
- for (var chartElements_1 = (e_10 = void 0, __values(chartElements)), chartElements_1_1 = chartElements_1.next(); !chartElements_1_1.done; chartElements_1_1 = chartElements_1.next()) {
1532
+ for (var chartElements_1 = (e_23 = void 0, __values(chartElements)), chartElements_1_1 = chartElements_1.next(); !chartElements_1_1.done; chartElements_1_1 = chartElements_1.next()) {
895
1533
  var singleChartElement = chartElements_1_1.value;
1534
+ // Series in a container bound to the secondary axis group plot on
1535
+ // the secondary axes (Excel's "Plot Series On: Secondary Axis").
1536
+ var useSecondaryAxis = isSecondaryGroupContainer(singleChartElement, secondaryIds);
896
1537
  // Determine the actual chart type for this container
897
1538
  var seriesChartType = container.chartType;
898
1539
  if (container.isBar) {
@@ -955,28 +1596,29 @@ export function extractChartSeries(plotArea, chartType, sheetId, resolveSheetId)
955
1596
  var categorySources = serCatRef
956
1597
  ? resolveSourcesFromRef(serCatRef, sheetId, resolveSheetId)
957
1598
  : [];
958
- series.push(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ dataLabel: seriesTitle || "Series ".concat(seriesIndex + 1) }, (nameRef ? { dataLabelRef: nameRef } : {})), (categorySources.length ? { categorySources: categorySources } : {})), { color: colorInfo.color }), (colorInfo.noFill ? { noFill: true } : {})), { negativeColor: colorInfo.negativeColor, invertIfNegative: colorInfo.invertIfNegative }), (colorInfo.gradient ? { gradient: colorInfo.gradient } : {})), (container.isXY ? {} : { seriesChartType: seriesChartType })), { sources: sources }), (inlineValues && inlineValues.length ? { inlineValues: inlineValues } : {})), (trendlines && trendlines.length ? { trendlines: trendlines } : {})), (errorBars ? { errorBars: errorBars } : {})), (marker ? { marker: marker } : {})), (dataPointColors && dataPointColors.length
1599
+ orders.push(seriesOrderOf(ser));
1600
+ series.push(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ dataLabel: seriesTitle || "Series ".concat(seriesIndex + 1) }, (nameRef ? { dataLabelRef: nameRef } : {})), (categorySources.length ? { categorySources: categorySources } : {})), { color: colorInfo.color }), (colorInfo.noFill ? { noFill: true } : {})), { negativeColor: colorInfo.negativeColor, invertIfNegative: colorInfo.invertIfNegative }), (colorInfo.gradient ? { gradient: colorInfo.gradient } : {})), (container.isXY ? {} : { seriesChartType: seriesChartType })), (useSecondaryAxis ? { useSecondaryAxis: true } : {})), { sources: sources }), (inlineValues && inlineValues.length ? { inlineValues: inlineValues } : {})), (trendlines && trendlines.length ? { trendlines: trendlines } : {})), (errorBars ? { errorBars: errorBars } : {})), (marker ? { marker: marker } : {})), (dataPointColors && dataPointColors.length
959
1601
  ? { dataPointColors: dataPointColors }
960
1602
  : {})));
961
1603
  seriesIndex++;
962
1604
  }
963
1605
  }
964
1606
  }
965
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
1607
+ catch (e_23_1) { e_23 = { error: e_23_1 }; }
966
1608
  finally {
967
1609
  try {
968
1610
  if (chartElements_1_1 && !chartElements_1_1.done && (_b = chartElements_1.return)) _b.call(chartElements_1);
969
1611
  }
970
- finally { if (e_10) throw e_10.error; }
1612
+ finally { if (e_23) throw e_23.error; }
971
1613
  }
972
1614
  }
973
1615
  }
974
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
1616
+ catch (e_22_1) { e_22 = { error: e_22_1 }; }
975
1617
  finally {
976
1618
  try {
977
- if (CHART_TYPE_CONTAINERS_1_1 && !CHART_TYPE_CONTAINERS_1_1.done && (_a = CHART_TYPE_CONTAINERS_1.return)) _a.call(CHART_TYPE_CONTAINERS_1);
1619
+ if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
978
1620
  }
979
- finally { if (e_9) throw e_9.error; }
1621
+ finally { if (e_22) throw e_22.error; }
980
1622
  }
981
1623
  // Fallback: pie/doughnut/radar/stock/ofPie/etc. aren't in
982
1624
  // CHART_TYPE_CONTAINERS; they're single-container, type-specific,
@@ -1018,13 +1660,16 @@ export function extractChartSeries(plotArea, chartType, sheetId, resolveSheetId)
1018
1660
  var categorySources = serCatRef
1019
1661
  ? resolveSourcesFromRef(serCatRef, sheetId, resolveSheetId)
1020
1662
  : [];
1663
+ orders.push(seriesOrderOf(ser));
1021
1664
  series.push(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ dataLabel: seriesTitle || "Series ".concat(index + 1) }, (nameRef ? { dataLabelRef: nameRef } : {})), (categorySources.length ? { categorySources: categorySources } : {})), { color: colorInfo.color }), (colorInfo.noFill ? { noFill: true } : {})), { negativeColor: colorInfo.negativeColor, invertIfNegative: colorInfo.invertIfNegative }), (colorInfo.gradient ? { gradient: colorInfo.gradient } : {})), { sources: sources }), (inlineValues && inlineValues.length ? { inlineValues: inlineValues } : {})), (marker ? { marker: marker } : {})), (dataPointColors && dataPointColors.length
1022
1665
  ? { dataPointColors: dataPointColors }
1023
1666
  : {})));
1024
1667
  });
1025
1668
  }
1026
1669
  }
1027
- return series;
1670
+ // Stock charts read their price roles in document order; every other
1671
+ // chart lists its series in Excel's <c:order>.
1672
+ return chartType === "stock" ? series : sortSeriesByOrder(series, orders);
1028
1673
  }
1029
1674
  /**
1030
1675
  * Extract per-data-point color overrides — `<c:dPt>` array inside
@@ -1034,7 +1679,7 @@ export function extractChartSeries(plotArea, chartType, sheetId, resolveSheetId)
1034
1679
  * are no overrides.
1035
1680
  */
1036
1681
  function extractSeriesDataPointColors(ser) {
1037
- var e_11, _a;
1682
+ var e_24, _a;
1038
1683
  var _b, _c, _d;
1039
1684
  var raw = (_b = get(ser, "c:dPt")) !== null && _b !== void 0 ? _b : get(ser, "dPt");
1040
1685
  if (!raw)
@@ -1042,8 +1687,8 @@ function extractSeriesDataPointColors(ser) {
1042
1687
  var list = Array.isArray(raw) ? raw : [raw];
1043
1688
  var result = [];
1044
1689
  try {
1045
- for (var list_1 = __values(list), list_1_1 = list_1.next(); !list_1_1.done; list_1_1 = list_1.next()) {
1046
- var dPt = list_1_1.value;
1690
+ for (var list_2 = __values(list), list_2_1 = list_2.next(); !list_2_1.done; list_2_1 = list_2.next()) {
1691
+ var dPt = list_2_1.value;
1047
1692
  var idxRaw = (_c = get(dPt, "c:idx.a$.val")) !== null && _c !== void 0 ? _c : get(dPt, "idx.a$.val");
1048
1693
  var idx = idxRaw !== undefined ? Number(idxRaw) : NaN;
1049
1694
  if (!Number.isFinite(idx))
@@ -1055,12 +1700,12 @@ function extractSeriesDataPointColors(ser) {
1055
1700
  result.push({ idx: idx, color: color });
1056
1701
  }
1057
1702
  }
1058
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
1703
+ catch (e_24_1) { e_24 = { error: e_24_1 }; }
1059
1704
  finally {
1060
1705
  try {
1061
- if (list_1_1 && !list_1_1.done && (_a = list_1.return)) _a.call(list_1);
1706
+ if (list_2_1 && !list_2_1.done && (_a = list_2.return)) _a.call(list_2);
1062
1707
  }
1063
- finally { if (e_11) throw e_11.error; }
1708
+ finally { if (e_24) throw e_24.error; }
1064
1709
  }
1065
1710
  return result.length ? result : undefined;
1066
1711
  }
@@ -1276,7 +1921,9 @@ function extractTextProperties(txPr) {
1276
1921
  */
1277
1922
  function extractBarLayoutOptions(plotArea) {
1278
1923
  var _a, _b, _c, _d, _e, _f, _g, _h;
1279
- var bar = (_c = (_b = (_a = get(plotArea, "c:barChart")) !== null && _a !== void 0 ? _a : get(plotArea, "barChart")) !== null && _b !== void 0 ? _b : get(plotArea, "c:bar3DChart")) !== null && _c !== void 0 ? _c : get(plotArea, "bar3DChart");
1924
+ // The primary axis group's container when the secondary group is split
1925
+ // into its own (Excel writes one container per axis group).
1926
+ var bar = firstGroup((_c = (_b = (_a = get(plotArea, "c:barChart")) !== null && _a !== void 0 ? _a : get(plotArea, "barChart")) !== null && _b !== void 0 ? _b : get(plotArea, "c:bar3DChart")) !== null && _c !== void 0 ? _c : get(plotArea, "bar3DChart"));
1280
1927
  if (!bar)
1281
1928
  return undefined;
1282
1929
  // `<c:grouping val="clustered|stacked|percentStacked|standard"/>`.
@@ -1307,6 +1954,61 @@ function extractBarLayoutOptions(plotArea) {
1307
1954
  result.gapWidth = gapWidthVal;
1308
1955
  return Object.keys(result).length ? result : undefined;
1309
1956
  }
1957
+ /**
1958
+ * Read `<c:lineChart>` / `<c:line3DChart>` `<c:grouping>` (standard /
1959
+ * stacked / percentStacked → `stackedType`) and the chart-level
1960
+ * `<c:marker val>` flag. Excel writes `<c:marker val="1"/>` on every line
1961
+ * chart and hides a plain "Line"'s markers per series through
1962
+ * `<c:marker><c:symbol val="none"/>`, so `showMarkers` is only reported
1963
+ * when the flag is set and at least one series is not "none".
1964
+ */
1965
+ function extractLineChartOptions(plotArea, series) {
1966
+ var _a, _b, _c, _d, _e, _f, _g;
1967
+ // The primary axis group's container when the secondary group is split
1968
+ // into its own (Excel writes one container per axis group).
1969
+ var line = firstGroup((_c = (_b = (_a = get(plotArea, "c:lineChart")) !== null && _a !== void 0 ? _a : get(plotArea, "lineChart")) !== null && _b !== void 0 ? _b : get(plotArea, "c:line3DChart")) !== null && _c !== void 0 ? _c : get(plotArea, "line3DChart"));
1970
+ if (!line)
1971
+ return undefined;
1972
+ var groupingVal = (_f = (_e = (_d = get(line, "c:grouping.a$.val")) !== null && _d !== void 0 ? _d : get(line, "grouping.a$.val")) !== null && _e !== void 0 ? _e : get(line, "c:grouping.a$.t$")) !== null && _f !== void 0 ? _f : get(line, "grouping.a$.t$");
1973
+ var result = {};
1974
+ switch (groupingVal) {
1975
+ case "stacked":
1976
+ result.stackedType = "STACKED";
1977
+ break;
1978
+ case "percentStacked":
1979
+ result.stackedType = "PERCENT_STACKED";
1980
+ break;
1981
+ case "standard":
1982
+ result.stackedType = "UNSTACKED";
1983
+ break;
1984
+ }
1985
+ var markerVal = (_g = get(line, "c:marker.a$.val")) !== null && _g !== void 0 ? _g : get(line, "marker.a$.val");
1986
+ var markerFlag = markerVal === "1" ||
1987
+ markerVal === 1 ||
1988
+ markerVal === "true" ||
1989
+ markerVal === true;
1990
+ if (markerFlag &&
1991
+ series.length > 0 &&
1992
+ series.some(function (entry) { var _a; return ((_a = entry.marker) === null || _a === void 0 ? void 0 : _a.symbol) !== "none"; })) {
1993
+ result.showMarkers = true;
1994
+ }
1995
+ return Object.keys(result).length ? result : undefined;
1996
+ }
1997
+ /**
1998
+ * Which of Excel's four stock layouts a `<c:stockChart>` is: a sibling
1999
+ * `<c:barChart>` carries the volume series (V-variants), and four price
2000
+ * series (open/high/low/close) instead of three mean OHLC.
2001
+ */
2002
+ function extractStockVariant(plotArea) {
2003
+ var prices = getWithFallback(plotArea, [
2004
+ "c:stockChart.c:ser",
2005
+ "stockChart.ser",
2006
+ ]);
2007
+ var priceCount = Array.isArray(prices) ? prices.length : prices ? 1 : 0;
2008
+ var hasVolume = Boolean(getWithFallback(plotArea, ["c:barChart", "barChart"]));
2009
+ var body = priceCount >= 4 ? "OHLC" : "HLC";
2010
+ return hasVolume ? "V".concat(body) : body;
2011
+ }
1310
2012
  /**
1311
2013
  * Extract chart-level `<c:scatterStyle val=…>`. Excel default is
1312
2014
  * "lineMarker" (straight lines + markers). Returns undefined for
@@ -1318,7 +2020,7 @@ function extractScatterStyle(plotArea) {
1318
2020
  return typeof val === "string" && val ? val : undefined;
1319
2021
  }
1320
2022
  function extractSeriesTitleFromSeries(ser) {
1321
- var e_12, _a;
2023
+ var e_25, _a;
1322
2024
  // Prefer cached textual value if present
1323
2025
  var cacheEntries = get(ser, "c:tx.c:strRef.c:strCache.c:pt");
1324
2026
  if (cacheEntries) {
@@ -1334,12 +2036,12 @@ function extractSeriesTitleFromSeries(ser) {
1334
2036
  }
1335
2037
  }
1336
2038
  }
1337
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
2039
+ catch (e_25_1) { e_25 = { error: e_25_1 }; }
1338
2040
  finally {
1339
2041
  try {
1340
2042
  if (pts_1_1 && !pts_1_1.done && (_a = pts_1.return)) _a.call(pts_1);
1341
2043
  }
1342
- finally { if (e_12) throw e_12.error; }
2044
+ finally { if (e_25) throw e_25.error; }
1343
2045
  }
1344
2046
  }
1345
2047
  // Fall back to literal
@@ -1365,7 +2067,7 @@ function coerceTitleText(value) {
1365
2067
  return undefined;
1366
2068
  }
1367
2069
  function extractRichText(node) {
1368
- var e_13, _a, e_14, _b;
2070
+ var e_26, _a, e_27, _b;
1369
2071
  if (!node) {
1370
2072
  return undefined;
1371
2073
  }
@@ -1382,7 +2084,7 @@ function extractRichText(node) {
1382
2084
  var runs = getWithFallback(paragraph, ["a:r", "r"]);
1383
2085
  var runArray = Array.isArray(runs) ? runs : runs ? [runs] : [paragraph];
1384
2086
  try {
1385
- for (var runArray_1 = (e_14 = void 0, __values(runArray)), runArray_1_1 = runArray_1.next(); !runArray_1_1.done; runArray_1_1 = runArray_1.next()) {
2087
+ for (var runArray_1 = (e_27 = void 0, __values(runArray)), runArray_1_1 = runArray_1.next(); !runArray_1_1.done; runArray_1_1 = runArray_1.next()) {
1386
2088
  var run = runArray_1_1.value;
1387
2089
  var text = getWithFallback(run, ["a:t.t$", "a:t"]) ||
1388
2090
  getWithFallback(run, ["t$", "t"]);
@@ -1391,21 +2093,21 @@ function extractRichText(node) {
1391
2093
  }
1392
2094
  }
1393
2095
  }
1394
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
2096
+ catch (e_27_1) { e_27 = { error: e_27_1 }; }
1395
2097
  finally {
1396
2098
  try {
1397
2099
  if (runArray_1_1 && !runArray_1_1.done && (_b = runArray_1.return)) _b.call(runArray_1);
1398
2100
  }
1399
- finally { if (e_14) throw e_14.error; }
2101
+ finally { if (e_27) throw e_27.error; }
1400
2102
  }
1401
2103
  }
1402
2104
  }
1403
- catch (e_13_1) { e_13 = { error: e_13_1 }; }
2105
+ catch (e_26_1) { e_26 = { error: e_26_1 }; }
1404
2106
  finally {
1405
2107
  try {
1406
2108
  if (paragraphArray_1_1 && !paragraphArray_1_1.done && (_a = paragraphArray_1.return)) _a.call(paragraphArray_1);
1407
2109
  }
1408
- finally { if (e_13) throw e_13.error; }
2110
+ finally { if (e_26) throw e_26.error; }
1409
2111
  }
1410
2112
  if (fragments.length > 0) {
1411
2113
  return fragments.join("");
@@ -1428,7 +2130,7 @@ function normalizeHexColor(value) {
1428
2130
  return undefined;
1429
2131
  }
1430
2132
  function extractSeriesColorInfo(ser) {
1431
- var e_15, _a, e_16, _b;
2133
+ var e_28, _a, e_29, _b;
1432
2134
  var _c, _d, _e, _f;
1433
2135
  var result = {};
1434
2136
  // <a:noFill/> on the series shape properties — transparent series.
@@ -1510,12 +2212,12 @@ function extractSeriesColorInfo(ser) {
1510
2212
  stops.push({ position: position, color: color });
1511
2213
  }
1512
2214
  }
1513
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
2215
+ catch (e_28_1) { e_28 = { error: e_28_1 }; }
1514
2216
  finally {
1515
2217
  try {
1516
2218
  if (stopList_1_1 && !stopList_1_1.done && (_a = stopList_1.return)) _a.call(stopList_1);
1517
2219
  }
1518
- finally { if (e_15) throw e_15.error; }
2220
+ finally { if (e_28) throw e_28.error; }
1519
2221
  }
1520
2222
  if (stops.length > 0) {
1521
2223
  stops.sort(function (a, b) { return a.position - b.position; });
@@ -1598,26 +2300,32 @@ function extractSeriesColorInfo(ser) {
1598
2300
  }
1599
2301
  }
1600
2302
  }
1601
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
2303
+ catch (e_29_1) { e_29 = { error: e_29_1 }; }
1602
2304
  finally {
1603
2305
  try {
1604
2306
  if (extArray_1_1 && !extArray_1_1.done && (_b = extArray_1.return)) _b.call(extArray_1);
1605
2307
  }
1606
- finally { if (e_16) throw e_16.error; }
2308
+ finally { if (e_29) throw e_29.error; }
1607
2309
  }
1608
2310
  }
1609
2311
  return result;
1610
2312
  }
1611
2313
  export function extractChartDomains(plotArea, chartType, sheetId, resolveSheetId) {
1612
- var e_17, _a, e_18, _b, e_19, _c, e_20, _d;
2314
+ var e_30, _a, e_31, _b, e_32, _c, e_33, _d;
1613
2315
  var _e, _f;
1614
2316
  var domains = [];
2317
+ // Non-XY: Excel keeps one category axis per axis group. The primary
2318
+ // group's first `<c:cat>` is domains[0]; when a container bound to the
2319
+ // secondary axis group carries a different `<c:cat>`, that list is
2320
+ // domains[1] — the secondary group's category axis.
2321
+ var secondaryIds = secondaryAxisGroupIds(plotArea);
2322
+ var primaryRef;
1615
2323
  try {
1616
2324
  // Search all chart type containers for domains. For XY charts the
1617
2325
  // "domain" is the X values (c:xVal); for everything else it's the
1618
2326
  // category axis (c:cat). Per-container loop covers combo charts.
1619
- for (var CHART_TYPE_CONTAINERS_2 = __values(CHART_TYPE_CONTAINERS), CHART_TYPE_CONTAINERS_2_1 = CHART_TYPE_CONTAINERS_2.next(); !CHART_TYPE_CONTAINERS_2_1.done; CHART_TYPE_CONTAINERS_2_1 = CHART_TYPE_CONTAINERS_2.next()) {
1620
- var container = CHART_TYPE_CONTAINERS_2_1.value;
2327
+ for (var CHART_TYPE_CONTAINERS_1 = __values(CHART_TYPE_CONTAINERS), CHART_TYPE_CONTAINERS_1_1 = CHART_TYPE_CONTAINERS_1.next(); !CHART_TYPE_CONTAINERS_1_1.done; CHART_TYPE_CONTAINERS_1_1 = CHART_TYPE_CONTAINERS_1.next()) {
2328
+ var container = CHART_TYPE_CONTAINERS_1_1.value;
1621
2329
  var chartElement = getWithFallback(plotArea, container.paths);
1622
2330
  if (!chartElement)
1623
2331
  continue;
@@ -1625,7 +2333,7 @@ export function extractChartDomains(plotArea, chartType, sheetId, resolveSheetId
1625
2333
  ? chartElement
1626
2334
  : [chartElement];
1627
2335
  try {
1628
- for (var chartElements_2 = (e_18 = void 0, __values(chartElements)), chartElements_2_1 = chartElements_2.next(); !chartElements_2_1.done; chartElements_2_1 = chartElements_2.next()) {
2336
+ for (var chartElements_2 = (e_31 = void 0, __values(chartElements)), chartElements_2_1 = chartElements_2.next(); !chartElements_2_1.done; chartElements_2_1 = chartElements_2.next()) {
1629
2337
  var singleChartElement = chartElements_2_1.value;
1630
2338
  var seriesElements_1 = getWithFallback(singleChartElement, [
1631
2339
  "c:ser",
@@ -1636,25 +2344,44 @@ export function extractChartDomains(plotArea, chartType, sheetId, resolveSheetId
1636
2344
  var seriesArray = Array.isArray(seriesElements_1)
1637
2345
  ? seriesElements_1
1638
2346
  : [seriesElements_1];
2347
+ var secondaryGroup = !container.isXY &&
2348
+ isSecondaryGroupContainer(singleChartElement, secondaryIds);
1639
2349
  try {
1640
- for (var seriesArray_2 = (e_19 = void 0, __values(seriesArray)), seriesArray_2_1 = seriesArray_2.next(); !seriesArray_2_1.done; seriesArray_2_1 = seriesArray_2.next()) {
2350
+ for (var seriesArray_2 = (e_32 = void 0, __values(seriesArray)), seriesArray_2_1 = seriesArray_2.next(); !seriesArray_2_1.done; seriesArray_2_1 = seriesArray_2.next()) {
1641
2351
  var ser = seriesArray_2_1.value;
1642
2352
  var domainRef = container.isXY
1643
2353
  ? getWithFallback(ser, X_VAL_REF_PATHS)
1644
2354
  : getWithFallback(ser, CAT_REF_PATHS);
1645
2355
  if (domainRef) {
2356
+ if (!container.isXY && domains.length) {
2357
+ // Primary already found: only a secondary-group container
2358
+ // with a different category list adds domains[1].
2359
+ if (secondaryGroup && domainRef !== primaryRef) {
2360
+ var sources_1 = resolveSourcesFromRef(domainRef, sheetId, resolveSheetId);
2361
+ if (sources_1.length) {
2362
+ domains.push({ sources: sources_1 });
2363
+ return domains;
2364
+ }
2365
+ }
2366
+ break;
2367
+ }
1646
2368
  var sources = resolveSourcesFromRef(domainRef, sheetId, resolveSheetId);
1647
2369
  if (sources.length) {
1648
2370
  domains.push({ sources: sources });
1649
2371
  // XY charts may carry per-series domains that differ — keep
1650
2372
  // the first one we encounter for the dataRange anchor, but
1651
2373
  // continue collecting so the renderer has a per-series X
1652
- // when it needs one. For non-XY, first-found is enough.
1653
- if (!container.isXY)
1654
- return domains;
2374
+ // when it needs one. For non-XY, remember the primary ref
2375
+ // and keep scanning for a secondary group's own list.
2376
+ if (!container.isXY) {
2377
+ primaryRef = domainRef;
2378
+ if (!secondaryIds.size)
2379
+ return domains;
2380
+ break;
2381
+ }
1655
2382
  }
1656
2383
  }
1657
- else if (!container.isXY) {
2384
+ else if (!container.isXY && !domains.length) {
1658
2385
  // No cell ref — check for an inline `<c:strLit>`/`<c:numLit>`
1659
2386
  // category list (e.g. `["Estimated", "Actual"]` embedded
1660
2387
  // directly in the chart XML). Same for the series val side,
@@ -1668,32 +2395,32 @@ export function extractChartDomains(plotArea, chartType, sheetId, resolveSheetId
1668
2395
  }
1669
2396
  }
1670
2397
  }
1671
- catch (e_19_1) { e_19 = { error: e_19_1 }; }
2398
+ catch (e_32_1) { e_32 = { error: e_32_1 }; }
1672
2399
  finally {
1673
2400
  try {
1674
2401
  if (seriesArray_2_1 && !seriesArray_2_1.done && (_c = seriesArray_2.return)) _c.call(seriesArray_2);
1675
2402
  }
1676
- finally { if (e_19) throw e_19.error; }
2403
+ finally { if (e_32) throw e_32.error; }
1677
2404
  }
1678
2405
  if (domains.length && container.isXY)
1679
2406
  return domains;
1680
2407
  }
1681
2408
  }
1682
- catch (e_18_1) { e_18 = { error: e_18_1 }; }
2409
+ catch (e_31_1) { e_31 = { error: e_31_1 }; }
1683
2410
  finally {
1684
2411
  try {
1685
2412
  if (chartElements_2_1 && !chartElements_2_1.done && (_b = chartElements_2.return)) _b.call(chartElements_2);
1686
2413
  }
1687
- finally { if (e_18) throw e_18.error; }
2414
+ finally { if (e_31) throw e_31.error; }
1688
2415
  }
1689
2416
  }
1690
2417
  }
1691
- catch (e_17_1) { e_17 = { error: e_17_1 }; }
2418
+ catch (e_30_1) { e_30 = { error: e_30_1 }; }
1692
2419
  finally {
1693
2420
  try {
1694
- if (CHART_TYPE_CONTAINERS_2_1 && !CHART_TYPE_CONTAINERS_2_1.done && (_a = CHART_TYPE_CONTAINERS_2.return)) _a.call(CHART_TYPE_CONTAINERS_2);
2421
+ if (CHART_TYPE_CONTAINERS_1_1 && !CHART_TYPE_CONTAINERS_1_1.done && (_a = CHART_TYPE_CONTAINERS_1.return)) _a.call(CHART_TYPE_CONTAINERS_1);
1695
2422
  }
1696
- finally { if (e_17) throw e_17.error; }
2423
+ finally { if (e_30) throw e_30.error; }
1697
2424
  }
1698
2425
  // Fallback for chart types not in CHART_TYPE_CONTAINERS
1699
2426
  // (pie/doughnut/radar/stock/ofPie/scatter/bubble outside combos).
@@ -1726,12 +2453,12 @@ export function extractChartDomains(plotArea, chartType, sheetId, resolveSheetId
1726
2453
  }
1727
2454
  }
1728
2455
  }
1729
- catch (e_20_1) { e_20 = { error: e_20_1 }; }
2456
+ catch (e_33_1) { e_33 = { error: e_33_1 }; }
1730
2457
  finally {
1731
2458
  try {
1732
2459
  if (seriesArray_3_1 && !seriesArray_3_1.done && (_d = seriesArray_3.return)) _d.call(seriesArray_3);
1733
2460
  }
1734
- finally { if (e_20) throw e_20.error; }
2461
+ finally { if (e_33) throw e_33.error; }
1735
2462
  }
1736
2463
  }
1737
2464
  return domains;
@@ -1743,7 +2470,7 @@ export function extractChartDomains(plotArea, chartType, sheetId, resolveSheetId
1743
2470
  * `series`).
1744
2471
  */
1745
2472
  export function extractChartBubbleSizes(plotArea, sheetId, resolveSheetId) {
1746
- var e_21, _a;
2473
+ var e_34, _a;
1747
2474
  var sizes = [];
1748
2475
  var seriesElements = getSeriesElements(plotArea, "bubble");
1749
2476
  if (!seriesElements)
@@ -1762,24 +2489,48 @@ export function extractChartBubbleSizes(plotArea, sheetId, resolveSheetId) {
1762
2489
  sizes.push({ sources: sources });
1763
2490
  }
1764
2491
  }
1765
- catch (e_21_1) { e_21 = { error: e_21_1 }; }
2492
+ catch (e_34_1) { e_34 = { error: e_34_1 }; }
1766
2493
  finally {
1767
2494
  try {
1768
2495
  if (seriesArray_4_1 && !seriesArray_4_1.done && (_a = seriesArray_4.return)) _a.call(seriesArray_4);
1769
2496
  }
1770
- finally { if (e_21) throw e_21.error; }
2497
+ finally { if (e_34) throw e_34.error; }
1771
2498
  }
1772
2499
  return sizes;
1773
2500
  }
1774
2501
  export function extractChartPosition(anchor, sheetId, sheetDimensions) {
1775
- var _a, _b, _c, _d, _e, _f;
2502
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1776
2503
  try {
1777
2504
  // Handle oneCellAnchor
1778
2505
  var oneCellFrom = (_a = getWithFallback(anchor, ["xdr:from", "from"])) !== null && _a !== void 0 ? _a : undefined;
1779
2506
  var hasTwoCellTarget = getWithFallback(anchor, ["xdr:to", "to"]) !== undefined;
2507
+ // absoluteAnchor: `<xdr:pos>` + `<xdr:ext>` — "Don't move or size with
2508
+ // cells"; kept as A1-relative pixel offsets (#668 C-06)
2509
+ var absolutePos = getWithFallback(anchor, ["xdr:pos", "pos"]);
2510
+ if (!oneCellFrom && absolutePos) {
2511
+ var posAttributes = (_b = absolutePos.a$) !== null && _b !== void 0 ? _b : absolutePos;
2512
+ var extNode = getWithFallback(anchor, ["xdr:ext", "ext"]);
2513
+ var extAttributes = (extNode && ((_c = extNode.a$) !== null && _c !== void 0 ? _c : extNode)) || undefined;
2514
+ var emuToPx = function (value, fallback) {
2515
+ return value !== undefined && value !== null
2516
+ ? Math.round(parseInt(String(value), 10) / 9525)
2517
+ : fallback;
2518
+ };
2519
+ return {
2520
+ sheetId: sheetId,
2521
+ overlayPosition: {
2522
+ anchorCell: { rowIndex: 1, columnIndex: 1 },
2523
+ offsetXPixels: emuToPx(posAttributes === null || posAttributes === void 0 ? void 0 : posAttributes.x, 0),
2524
+ offsetYPixels: emuToPx(posAttributes === null || posAttributes === void 0 ? void 0 : posAttributes.y, 0),
2525
+ widthPixels: emuToPx(extAttributes === null || extAttributes === void 0 ? void 0 : extAttributes.cx, 400),
2526
+ heightPixels: emuToPx(extAttributes === null || extAttributes === void 0 ? void 0 : extAttributes.cy, 300),
2527
+ placement: "absolute",
2528
+ },
2529
+ };
2530
+ }
1780
2531
  if (oneCellFrom && !hasTwoCellTarget) {
1781
2532
  var extNode = getWithFallback(anchor, ["xdr:ext", "ext"]);
1782
- var extAttributes = (extNode && ((_b = extNode.a$) !== null && _b !== void 0 ? _b : extNode)) || undefined;
2533
+ var extAttributes = (extNode && ((_d = extNode.a$) !== null && _d !== void 0 ? _d : extNode)) || undefined;
1783
2534
  var col = toInt(getWithFallback(oneCellFrom, ["xdr:col", "col"]));
1784
2535
  var row = toInt(getWithFallback(oneCellFrom, ["xdr:row", "row"]));
1785
2536
  var colOff = toInt(getWithFallback(oneCellFrom, ["xdr:colOff", "colOff"]));
@@ -1802,12 +2553,13 @@ export function extractChartPosition(anchor, sheetId, sheetDimensions) {
1802
2553
  offsetYPixels: Math.round(rowOff / 9525),
1803
2554
  widthPixels: width,
1804
2555
  heightPixels: height,
2556
+ placement: "moveOnly",
1805
2557
  },
1806
2558
  };
1807
2559
  }
1808
2560
  // Handle twoCellAnchor
1809
- var fromCell = (_c = getWithFallback(anchor, ["xdr:from", "from"])) !== null && _c !== void 0 ? _c : undefined;
1810
- var toCell = (_d = getWithFallback(anchor, ["xdr:to", "to"])) !== null && _d !== void 0 ? _d : undefined;
2561
+ var fromCell = (_e = getWithFallback(anchor, ["xdr:from", "from"])) !== null && _e !== void 0 ? _e : undefined;
2562
+ var toCell = (_f = getWithFallback(anchor, ["xdr:to", "to"])) !== null && _f !== void 0 ? _f : undefined;
1811
2563
  if (fromCell && toCell) {
1812
2564
  var col = toInt(getWithFallback(fromCell, ["xdr:col", "col"]));
1813
2565
  var row = toInt(getWithFallback(fromCell, ["xdr:row", "row"]));
@@ -1818,8 +2570,8 @@ export function extractChartPosition(anchor, sheetId, sheetDimensions) {
1818
2570
  var toColOff = toInt(getWithFallback(toCell, ["xdr:colOff", "colOff"]));
1819
2571
  var toRowOff = toInt(getWithFallback(toCell, ["xdr:rowOff", "rowOff"]));
1820
2572
  // Default cell dimensions in pixels
1821
- var DEFAULT_COL_WIDTH_PX_1 = (_e = sheetDimensions === null || sheetDimensions === void 0 ? void 0 : sheetDimensions.defaultColumnWidth) !== null && _e !== void 0 ? _e : 64;
1822
- var DEFAULT_ROW_HEIGHT_PX_1 = (_f = sheetDimensions === null || sheetDimensions === void 0 ? void 0 : sheetDimensions.defaultRowHeight) !== null && _f !== void 0 ? _f : 20;
2573
+ var DEFAULT_COL_WIDTH_PX_1 = (_g = sheetDimensions === null || sheetDimensions === void 0 ? void 0 : sheetDimensions.defaultColumnWidth) !== null && _g !== void 0 ? _g : 64;
2574
+ var DEFAULT_ROW_HEIGHT_PX_1 = (_h = sheetDimensions === null || sheetDimensions === void 0 ? void 0 : sheetDimensions.defaultRowHeight) !== null && _h !== void 0 ? _h : 20;
1823
2575
  // Helper to get column width in pixels
1824
2576
  var getColWidth = function (colIndex) {
1825
2577
  var _a, _b;
@@ -1849,18 +2601,22 @@ export function extractChartPosition(anchor, sheetId, sheetDimensions) {
1849
2601
  heightPx += Math.round(toRowOff / 9525);
1850
2602
  var width = Math.max(widthPx, 100);
1851
2603
  var height = Math.max(heightPx, 100);
2604
+ // `editAs` is the placement mode; the default "Move and size with
2605
+ // cells" keeps `to` as the second anchor so the frame follows the
2606
+ // cells between the corners (#668 C-06)
2607
+ var placement = anchorPlacementFromEditAs(getWithFallback(anchor, ["a$.editAs"]));
1852
2608
  return {
1853
2609
  sheetId: sheetId,
1854
- overlayPosition: {
1855
- anchorCell: {
2610
+ overlayPosition: __assign({ anchorCell: {
1856
2611
  rowIndex: row + 1,
1857
2612
  columnIndex: col + 1,
1858
- },
1859
- offsetXPixels: Math.round(colOff / 9525),
1860
- offsetYPixels: Math.round(rowOff / 9525),
1861
- widthPixels: width,
1862
- heightPixels: height,
1863
- },
2613
+ }, offsetXPixels: Math.round(colOff / 9525), offsetYPixels: Math.round(rowOff / 9525), widthPixels: width, heightPixels: height }, (placement === "moveAndSize"
2614
+ ? {
2615
+ toCell: { rowIndex: toRow + 1, columnIndex: toCol + 1 },
2616
+ toOffsetXPixels: Math.round(toColOff / 9525),
2617
+ toOffsetYPixels: Math.round(toRowOff / 9525),
2618
+ }
2619
+ : { placement: placement })),
1864
2620
  };
1865
2621
  }
1866
2622
  return null;
@@ -1941,7 +2697,7 @@ var mapDataLabelPosition = function (val) {
1941
2697
  }
1942
2698
  };
1943
2699
  function extractDataLabelsOptions(plotArea, chartType) {
1944
- var e_22, _a;
2700
+ var e_35, _a;
1945
2701
  var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
1946
2702
  // Look for <c:dLbls> inside the chartType-specific container. We pick
1947
2703
  // the first one we find — chart-level labels apply to all series.
@@ -1968,15 +2724,15 @@ function extractDataLabelsOptions(plotArea, chartType) {
1968
2724
  try {
1969
2725
  for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
1970
2726
  var key = keys_1_1.value;
1971
- container = container !== null && container !== void 0 ? container : get(plotArea, key);
2727
+ container = container !== null && container !== void 0 ? container : firstGroup(get(plotArea, key));
1972
2728
  }
1973
2729
  }
1974
- catch (e_22_1) { e_22 = { error: e_22_1 }; }
2730
+ catch (e_35_1) { e_35 = { error: e_35_1 }; }
1975
2731
  finally {
1976
2732
  try {
1977
2733
  if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
1978
2734
  }
1979
- finally { if (e_22) throw e_22.error; }
2735
+ finally { if (e_35) throw e_35.error; }
1980
2736
  }
1981
2737
  var dLbls = (_e = (_d = (_c = get(container, "c:dLbls")) !== null && _c !== void 0 ? _c : get(container, "dLbls")) !== null && _d !== void 0 ? _d : get(plotArea, "c:dLbls")) !== null && _e !== void 0 ? _e : get(plotArea, "dLbls");
1982
2738
  if (!dLbls)
@@ -2024,7 +2780,7 @@ function extractDataLabelsOptions(plotArea, chartType) {
2024
2780
  return Object.keys(result).length ? result : undefined;
2025
2781
  }
2026
2782
  function readAxis(axis) {
2027
- var _a, _b, _c, _d, _e, _f, _g;
2783
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
2028
2784
  if (!axis)
2029
2785
  return undefined;
2030
2786
  var result = {};
@@ -2055,6 +2811,17 @@ function readAxis(axis) {
2055
2811
  var textFormat = extractTextProperties((_g = get(axis, "c:txPr")) !== null && _g !== void 0 ? _g : get(axis, "txPr"));
2056
2812
  if (textFormat)
2057
2813
  result.textFormat = textFormat;
2814
+ // <c:numFmt formatCode="…" sourceLinked="0"/> — an explicit tick-label
2815
+ // format. `sourceLinked="1"` (Excel's default) means the axis inherits
2816
+ // the source cells' format, which the renderer resolves at draw time,
2817
+ // so it is intentionally NOT copied into the spec.
2818
+ var numFmt = (_h = get(axis, "c:numFmt.a$")) !== null && _h !== void 0 ? _h : get(axis, "numFmt.a$");
2819
+ var formatCode = (_j = numFmt === null || numFmt === void 0 ? void 0 : numFmt.formatCode) !== null && _j !== void 0 ? _j : numFmt === null || numFmt === void 0 ? void 0 : numFmt.t$;
2820
+ if (typeof formatCode === "string" &&
2821
+ formatCode &&
2822
+ !readBoolean(numFmt === null || numFmt === void 0 ? void 0 : numFmt.sourceLinked)) {
2823
+ result.numberFormatPattern = formatCode;
2824
+ }
2058
2825
  return Object.keys(result).length ? result : undefined;
2059
2826
  }
2060
2827
  export function extractAxisOptions(plotArea) {
@@ -2107,6 +2874,37 @@ function extractDoughnutHoleSize(plotArea) {
2107
2874
  return undefined;
2108
2875
  return Math.min(0.9, Math.max(0, holeSize / 100));
2109
2876
  }
2877
+ /**
2878
+ * Exploded pie / doughnut — `<c:ser><c:explosion val="25"/>` is the
2879
+ * slice offset as a percentage of the radius. Excel writes it on every
2880
+ * series of an exploded chart; the spec keeps one chart-level value, so
2881
+ * the largest authored explosion wins. Undefined when no series is
2882
+ * exploded (Excel omits the element for a plain pie).
2883
+ */
2884
+ function extractExplosion(plotArea, chartType) {
2885
+ var e_36, _a;
2886
+ var _b;
2887
+ var sers = getSeriesElements(plotArea, chartType);
2888
+ var list = Array.isArray(sers) ? sers : sers ? [sers] : [];
2889
+ var explosion;
2890
+ try {
2891
+ for (var list_3 = __values(list), list_3_1 = list_3.next(); !list_3_1.done; list_3_1 = list_3.next()) {
2892
+ var ser = list_3_1.value;
2893
+ var value = readNumber((_b = get(ser, "c:explosion.a$.val")) !== null && _b !== void 0 ? _b : get(ser, "explosion.a$.val"));
2894
+ if (typeof value === "number" && value > 0) {
2895
+ explosion = Math.max(explosion !== null && explosion !== void 0 ? explosion : 0, value);
2896
+ }
2897
+ }
2898
+ }
2899
+ catch (e_36_1) { e_36 = { error: e_36_1 }; }
2900
+ finally {
2901
+ try {
2902
+ if (list_3_1 && !list_3_1.done && (_a = list_3.return)) _a.call(list_3);
2903
+ }
2904
+ finally { if (e_36) throw e_36.error; }
2905
+ }
2906
+ return explosion;
2907
+ }
2110
2908
  // -------------------------- Phase 5.2 helpers --------------------------
2111
2909
  var mapTrendlineType = function (val) {
2112
2910
  switch (val) {
@@ -2126,7 +2924,7 @@ var mapTrendlineType = function (val) {
2126
2924
  }
2127
2925
  };
2128
2926
  function extractTrendlines(ser) {
2129
- var e_23, _a;
2927
+ var e_37, _a;
2130
2928
  var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
2131
2929
  // <c:trendline> can appear multiple times under a single series; the
2132
2930
  // parser may surface either an array or a single object.
@@ -2136,8 +2934,8 @@ function extractTrendlines(ser) {
2136
2934
  var list = Array.isArray(raw) ? raw : [raw];
2137
2935
  var results = [];
2138
2936
  try {
2139
- for (var list_2 = __values(list), list_2_1 = list_2.next(); !list_2_1.done; list_2_1 = list_2.next()) {
2140
- var t = list_2_1.value;
2937
+ for (var list_4 = __values(list), list_4_1 = list_4.next(); !list_4_1.done; list_4_1 = list_4.next()) {
2938
+ var t = list_4_1.value;
2141
2939
  var type = mapTrendlineType((_c = get(t, "c:trendlineType.a$.val")) !== null && _c !== void 0 ? _c : get(t, "trendlineType.a$.val"));
2142
2940
  var order = readNumber((_d = get(t, "c:order.a$.val")) !== null && _d !== void 0 ? _d : get(t, "order.a$.val"));
2143
2941
  var period = readNumber((_e = get(t, "c:period.a$.val")) !== null && _e !== void 0 ? _e : get(t, "period.a$.val"));
@@ -2164,12 +2962,12 @@ function extractTrendlines(ser) {
2164
2962
  results.push(entry);
2165
2963
  }
2166
2964
  }
2167
- catch (e_23_1) { e_23 = { error: e_23_1 }; }
2965
+ catch (e_37_1) { e_37 = { error: e_37_1 }; }
2168
2966
  finally {
2169
2967
  try {
2170
- if (list_2_1 && !list_2_1.done && (_a = list_2.return)) _a.call(list_2);
2968
+ if (list_4_1 && !list_4_1.done && (_a = list_4.return)) _a.call(list_4);
2171
2969
  }
2172
- finally { if (e_23) throw e_23.error; }
2970
+ finally { if (e_37) throw e_37.error; }
2173
2971
  }
2174
2972
  return results;
2175
2973
  }