@odoo/o-spreadsheet 19.2.0-alpha.3 → 19.2.0-alpha.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.
@@ -3,8 +3,8 @@
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
5
  * @version 19.1.0-alpha.3
6
- * @date 2026-01-14T10:01:30.535Z
7
- * @hash e5cbf18
6
+ * @date 2026-01-21T11:07:49.673Z
7
+ * @hash fa080c2
8
8
  */
9
9
 
10
10
  (function (exports) {
@@ -2547,7 +2547,11 @@
2547
2547
  if (operator === "<>" || operator === "=") {
2548
2548
  let result;
2549
2549
  if (typeof value === typeof operand) {
2550
- if (typeof value === "string" && typeof operand === "string") {
2550
+ if (value === "" && operand === "") {
2551
+ // fast path to avoid regex evaluation
2552
+ result = true;
2553
+ }
2554
+ else if (typeof value === "string" && typeof operand === "string") {
2551
2555
  result = wildcardToRegExp(operand).test(value);
2552
2556
  }
2553
2557
  else {
@@ -2901,7 +2905,16 @@
2901
2905
  }
2902
2906
  acceptToVectorize.push(!argDefinition.acceptMatrix);
2903
2907
  }
2904
- return applyVectorization(errorHandlingCompute.bind(this), args, acceptToVectorize);
2908
+ return replaceErrorPlaceholderInResult(applyVectorization(errorHandlingCompute.bind(this), args, acceptToVectorize));
2909
+ }
2910
+ function replaceErrorPlaceholderInResult(result) {
2911
+ if (!isMatrix(result)) {
2912
+ replaceFunctionNamePlaceholder(result, descr.name);
2913
+ }
2914
+ else {
2915
+ matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, descr.name));
2916
+ }
2917
+ return result;
2905
2918
  }
2906
2919
  function errorHandlingCompute(...args) {
2907
2920
  for (let i = 0; i < args.length; i++) {
@@ -2930,13 +2943,12 @@
2930
2943
  const result = descr.compute.apply(this, args);
2931
2944
  if (!isMatrix(result)) {
2932
2945
  if (typeof result === "object" && result !== null && "value" in result) {
2933
- replaceFunctionNamePlaceholder(result, descr.name);
2934
2946
  return result;
2935
2947
  }
2948
+ descr.name;
2936
2949
  return { value: result };
2937
2950
  }
2938
2951
  if (typeof result[0][0] === "object" && result[0][0] !== null && "value" in result[0][0]) {
2939
- matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, descr.name));
2940
2952
  return result;
2941
2953
  }
2942
2954
  return matrixMap(result, (row) => ({ value: row }));
@@ -3919,9 +3931,14 @@
3919
3931
  else if (value < 1e11) {
3920
3932
  return createLargeNumberFormat(format, 2, "m");
3921
3933
  }
3922
- return createLargeNumberFormat(format, 3, "b");
3934
+ else if (value < 1e14) {
3935
+ return createLargeNumberFormat(format, 3, "b");
3936
+ }
3937
+ else {
3938
+ return "0.00e";
3939
+ }
3923
3940
  }
3924
- function createLargeNumberFormat(format, magnitude, postFix, locale) {
3941
+ function createLargeNumberFormat(format, magnitude, postFix) {
3925
3942
  const multiPartFormat = parseFormat(format || "#,##0");
3926
3943
  const roundedInternalFormat = {
3927
3944
  positive: _createLargeNumberFormat(multiPartFormat.positive, magnitude, postFix),
@@ -18039,7 +18056,7 @@
18039
18056
  const groups = groupConsecutive(elements);
18040
18057
  return (range) => {
18041
18058
  if (range.sheetId !== cmd.sheetId) {
18042
- return { changeType: "NONE" };
18059
+ return { changeType: "NONE", range };
18043
18060
  }
18044
18061
  let newRange = range;
18045
18062
  let changeType = "NONE";
@@ -18066,10 +18083,7 @@
18066
18083
  newRange = createAdaptedRange(newRange, dimension, changeType, -(max - min + 1));
18067
18084
  }
18068
18085
  }
18069
- if (changeType !== "NONE") {
18070
- return { changeType, range: newRange };
18071
- }
18072
- return { changeType: "NONE" };
18086
+ return { changeType, range: newRange };
18073
18087
  };
18074
18088
  }
18075
18089
  function getApplyRangeChangeAddColRow(cmd) {
@@ -18078,7 +18092,7 @@
18078
18092
  const dimension = cmd.dimension === "COL" ? "columns" : "rows";
18079
18093
  return (range) => {
18080
18094
  if (range.sheetId !== cmd.sheetId) {
18081
- return { changeType: "NONE" };
18095
+ return { changeType: "NONE", range };
18082
18096
  }
18083
18097
  if (cmd.position === "after") {
18084
18098
  if (range.zone[start] <= cmd.base && cmd.base < range.zone[end]) {
@@ -18108,13 +18122,13 @@
18108
18122
  };
18109
18123
  }
18110
18124
  }
18111
- return { changeType: "NONE" };
18125
+ return { changeType: "NONE", range };
18112
18126
  };
18113
18127
  }
18114
18128
  function getApplyRangeChangeDeleteSheet(cmd) {
18115
18129
  return (range) => {
18116
18130
  if (range.sheetId !== cmd.sheetId && range.invalidSheetName !== cmd.sheetName) {
18117
- return { changeType: "NONE" };
18131
+ return { changeType: "NONE", range };
18118
18132
  }
18119
18133
  const invalidSheetName = cmd.sheetName;
18120
18134
  range = {
@@ -18141,14 +18155,14 @@
18141
18155
  const newRange = { ...range, sheetId, invalidSheetName };
18142
18156
  return { changeType: "CHANGE", range: newRange };
18143
18157
  }
18144
- return { changeType: "NONE" };
18158
+ return { changeType: "NONE", range };
18145
18159
  };
18146
18160
  }
18147
18161
  function getApplyRangeChangeMoveRange(cmd) {
18148
18162
  const originZone = cmd.target[0];
18149
18163
  return (range) => {
18150
18164
  if (range.sheetId !== cmd.sheetId || !isZoneInside(range.zone, originZone)) {
18151
- return { changeType: "NONE" };
18165
+ return { changeType: "NONE", range };
18152
18166
  }
18153
18167
  const targetSheetId = cmd.targetSheetId;
18154
18168
  const offsetX = cmd.col - originZone.left;
@@ -20080,7 +20094,7 @@
20080
20094
  continue;
20081
20095
  }
20082
20096
  const sheetXC = tokens[tokenIdx].value;
20083
- const newSheetXC = adaptStringRange(defaultSheetId, sheetXC, applyChange);
20097
+ const newSheetXC = adaptStringRange(defaultSheetId, sheetXC, applyChange).range;
20084
20098
  if (sheetXC !== newSheetXC) {
20085
20099
  tokens[tokenIdx] = {
20086
20100
  value: newSheetXC,
@@ -20090,23 +20104,30 @@
20090
20104
  }
20091
20105
  return concat(tokens.map((token) => token.value));
20092
20106
  }
20093
- function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20107
+ function adaptStringRange(defaultSheetId, sheetXC, rangeAdapter) {
20094
20108
  const sheetName = splitReference(sheetXC).sheetName;
20095
20109
  if (sheetName
20096
- ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
20097
- : defaultSheetId !== applyChange.sheetId) {
20098
- return sheetXC;
20110
+ ? !isSheetNameEqual(sheetName, rangeAdapter.sheetName.old)
20111
+ : defaultSheetId !== rangeAdapter.sheetId) {
20112
+ return { changeType: "NONE", range: sheetXC };
20099
20113
  }
20100
- const sheetId = sheetName ? applyChange.sheetId : defaultSheetId;
20114
+ const sheetId = sheetName ? rangeAdapter.sheetId : defaultSheetId;
20101
20115
  const range = getRange(sheetXC, sheetId);
20102
20116
  if (range.invalidXc) {
20103
- return sheetXC;
20117
+ return { changeType: "NONE", range: sheetXC };
20104
20118
  }
20105
- const change = applyChange.applyChange(range);
20119
+ const change = rangeAdapter.applyChange(range);
20106
20120
  if (change.changeType === "NONE" || change.changeType === "REMOVE") {
20107
- return sheetXC;
20121
+ return { changeType: change.changeType, range: sheetXC };
20108
20122
  }
20109
- return getRangeString(change.range, defaultSheetId, getSheetNameGetter(applyChange));
20123
+ const rangeStr = getRangeString(change.range, defaultSheetId, getSheetNameGetter(rangeAdapter));
20124
+ if (rangeStr === CellErrorType.InvalidReference) {
20125
+ return { changeType: "REMOVE", range: rangeStr };
20126
+ }
20127
+ return {
20128
+ changeType: change.changeType,
20129
+ range: rangeStr,
20130
+ };
20110
20131
  }
20111
20132
  function getSheetNameGetter(applyChange) {
20112
20133
  return (sheetId) => {
@@ -20321,7 +20342,7 @@
20321
20342
  cmd.cf.rule = {
20322
20343
  ...rule,
20323
20344
  rangeValues: rule.rangeValues
20324
- ? adaptStringRange(cmd.sheetId, rule.rangeValues, applyChange)
20345
+ ? adaptStringRange(cmd.sheetId, rule.rangeValues, applyChange).range
20325
20346
  : undefined,
20326
20347
  };
20327
20348
  }
@@ -22814,6 +22835,413 @@
22814
22835
  */
22815
22836
  const DEFAULT_SYSTEM_COLOR = "FF000000";
22816
22837
 
22838
+ const globalReverseLookup$1 = new WeakMap();
22839
+ const globalIdCounter = new WeakMap();
22840
+ /**
22841
+ * Get the id of the given item (its key in the given dictionary).
22842
+ * If the given item does not exist in the dictionary, it creates one with a new id.
22843
+ */
22844
+ function getItemId(item, itemsDic) {
22845
+ if (!globalReverseLookup$1.has(itemsDic)) {
22846
+ globalReverseLookup$1.set(itemsDic, new Map());
22847
+ globalIdCounter.set(itemsDic, 0);
22848
+ }
22849
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
22850
+ const canonical = getCanonicalRepresentation(item);
22851
+ if (reverseLookup.has(canonical)) {
22852
+ const id = reverseLookup.get(canonical);
22853
+ itemsDic[id] = item;
22854
+ return id;
22855
+ }
22856
+ // Generate new Id if the item didn't exist in the dictionary
22857
+ const newId = globalIdCounter.get(itemsDic) + 1;
22858
+ reverseLookup.set(canonical, newId);
22859
+ globalIdCounter.set(itemsDic, newId);
22860
+ itemsDic[newId] = item;
22861
+ return newId;
22862
+ }
22863
+ function groupItemIdsByZones(positionsByItemId) {
22864
+ const result = {};
22865
+ for (const itemId in positionsByItemId) {
22866
+ const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
22867
+ for (const zone of zones) {
22868
+ result[zoneToXc(zone)] = Number(itemId);
22869
+ }
22870
+ }
22871
+ return result;
22872
+ }
22873
+ function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
22874
+ for (const zoneXc in itemIdsByZones) {
22875
+ const zone = toZone(zoneXc);
22876
+ const itemId = itemIdsByZones[zoneXc];
22877
+ for (let row = zone.top; row <= zone.bottom; row++) {
22878
+ for (let col = zone.left; col <= zone.right; col++) {
22879
+ const position = { sheetId, col, row };
22880
+ yield [position, itemId];
22881
+ }
22882
+ }
22883
+ }
22884
+ }
22885
+ function getCanonicalRepresentation(item) {
22886
+ if (item === null) {
22887
+ return "null";
22888
+ }
22889
+ if (item === undefined) {
22890
+ return "undefined";
22891
+ }
22892
+ if (typeof item !== "object") {
22893
+ return String(item);
22894
+ }
22895
+ if (Array.isArray(item)) {
22896
+ const len = item.length;
22897
+ let result = "[";
22898
+ for (let i = 0; i < len; i++) {
22899
+ if (i > 0) {
22900
+ result += ",";
22901
+ }
22902
+ result += getCanonicalRepresentation(item[i]);
22903
+ }
22904
+ return result + "]";
22905
+ }
22906
+ const keys = Object.keys(item).sort();
22907
+ let repr = "{";
22908
+ for (const key of keys) {
22909
+ if (item[key] !== undefined) {
22910
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
22911
+ }
22912
+ }
22913
+ repr += "}";
22914
+ return repr;
22915
+ }
22916
+
22917
+ // -------------------------------------
22918
+ // CF HELPERS
22919
+ // -------------------------------------
22920
+ /**
22921
+ * Convert the conditional formatting o-spreadsheet operator to
22922
+ * the corresponding excel operator.
22923
+ * */
22924
+ function convertOperator(operator) {
22925
+ switch (operator) {
22926
+ case "isNotEmpty":
22927
+ return "notContainsBlanks";
22928
+ case "isEmpty":
22929
+ return "containsBlanks";
22930
+ case "notContainsText":
22931
+ return "notContainsBlanks";
22932
+ case "containsText":
22933
+ return "containsText";
22934
+ case "beginsWithText":
22935
+ return "beginsWith";
22936
+ case "endsWithText":
22937
+ return "endsWith";
22938
+ case "isGreaterThan":
22939
+ return "greaterThan";
22940
+ case "isGreaterOrEqualTo":
22941
+ return "greaterThanOrEqual";
22942
+ case "isLessThan":
22943
+ return "lessThan";
22944
+ case "isLessOrEqualTo":
22945
+ return "lessThanOrEqual";
22946
+ case "isBetween":
22947
+ return "between";
22948
+ case "isNotBetween":
22949
+ return "notBetween";
22950
+ case "isEqual":
22951
+ return "equal";
22952
+ case "isNotEqual":
22953
+ return "notEqual";
22954
+ case "customFormula":
22955
+ return "";
22956
+ case "dateIs":
22957
+ return "";
22958
+ case "dateIsBefore":
22959
+ return "lessThan";
22960
+ case "dateIsAfter":
22961
+ return "greaterThan";
22962
+ case "dateIsOnOrAfter":
22963
+ return "greaterThanOrEqual";
22964
+ case "dateIsOnOrBefore":
22965
+ return "lessThanOrEqual";
22966
+ case "top10":
22967
+ return "top10";
22968
+ }
22969
+ }
22970
+ // -------------------------------------
22971
+ // WORKSHEET HELPERS
22972
+ // -------------------------------------
22973
+ function getCellType(value) {
22974
+ switch (typeof value) {
22975
+ case "boolean":
22976
+ return "b";
22977
+ case "string":
22978
+ return "str";
22979
+ case "number":
22980
+ return "n";
22981
+ default:
22982
+ return undefined;
22983
+ }
22984
+ }
22985
+ function convertHeightToExcel(height) {
22986
+ return Math.round(HEIGHT_FACTOR * height * 100) / 100;
22987
+ }
22988
+ function convertWidthToExcel(width) {
22989
+ return Math.round(WIDTH_FACTOR * width * 100) / 100;
22990
+ }
22991
+ function convertHeightFromExcel(height) {
22992
+ if (!height) {
22993
+ return height;
22994
+ }
22995
+ return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
22996
+ }
22997
+ function convertWidthFromExcel(width) {
22998
+ if (!width) {
22999
+ return width;
23000
+ }
23001
+ return Math.round((width / WIDTH_FACTOR) * 100) / 100;
23002
+ }
23003
+ function extractStyle(data, content, styleId, formatId, borderId) {
23004
+ const style = styleId ? data.styles[styleId] : {};
23005
+ const format = formatId ? data.formats[formatId] : undefined;
23006
+ const styles = {
23007
+ font: {
23008
+ size: style?.fontSize || DEFAULT_FONT_SIZE,
23009
+ color: { rgb: style?.textColor ? style.textColor : "000000" },
23010
+ family: 2,
23011
+ name: "Arial",
23012
+ },
23013
+ fill: style?.fillColor
23014
+ ? {
23015
+ fgColor: { rgb: style.fillColor },
23016
+ }
23017
+ : { reservedAttribute: "none" },
23018
+ numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
23019
+ border: borderId || 0,
23020
+ alignment: {
23021
+ horizontal: style.align,
23022
+ vertical: style.verticalAlign
23023
+ ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
23024
+ : undefined,
23025
+ wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
23026
+ textRotation: style.rotation ? rotationToXLSX(style.rotation) : undefined,
23027
+ shrinkToFit: style.wrapping === "clip" ? true : undefined,
23028
+ },
23029
+ };
23030
+ styles.font["strike"] = !!style?.strikethrough || undefined;
23031
+ styles.font["underline"] = !!style?.underline || undefined;
23032
+ styles.font["bold"] = !!style?.bold || undefined;
23033
+ styles.font["italic"] = !!style?.italic || undefined;
23034
+ return styles;
23035
+ }
23036
+ function rotationToXLSX(rad) {
23037
+ let deg = Math.round((-rad / Math.PI) * 180) % 180;
23038
+ if (deg > 90) {
23039
+ deg -= 180;
23040
+ }
23041
+ else if (deg < -90) {
23042
+ deg += 180;
23043
+ }
23044
+ if (deg >= 0) {
23045
+ return deg;
23046
+ }
23047
+ else {
23048
+ return 90 - deg;
23049
+ }
23050
+ }
23051
+ function rotationFromXLSX(deg) {
23052
+ if (deg <= 90) {
23053
+ return -(deg / 180) * Math.PI;
23054
+ }
23055
+ else {
23056
+ return (-(90 - deg) / 180) * Math.PI;
23057
+ }
23058
+ }
23059
+ function normalizeStyle(construct, styles) {
23060
+ // Normalize this
23061
+ const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
23062
+ const style = {
23063
+ fontId: pushElement(styles.font, construct.fonts),
23064
+ fillId: pushElement(styles.fill, construct.fills),
23065
+ borderId: styles.border,
23066
+ numFmtId,
23067
+ alignment: {
23068
+ vertical: styles.alignment.vertical,
23069
+ horizontal: styles.alignment.horizontal,
23070
+ wrapText: styles.alignment.wrapText,
23071
+ textRotation: styles.alignment.textRotation,
23072
+ shrinkToFit: styles.alignment.shrinkToFit,
23073
+ },
23074
+ };
23075
+ return pushElement(style, construct.styles);
23076
+ }
23077
+ function convertFormat(format, numFmtStructure) {
23078
+ if (!format) {
23079
+ return 0;
23080
+ }
23081
+ let formatId = XLSX_FORMAT_MAP[format.format];
23082
+ if (!formatId) {
23083
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23084
+ }
23085
+ return formatId;
23086
+ }
23087
+ /**
23088
+ * Add a relation to the given file and return its id.
23089
+ */
23090
+ function addRelsToFile(relsFiles, path, rel) {
23091
+ const relsFile = relsFiles.find((file) => file.path === path);
23092
+ // the id is a one-based int casted as string
23093
+ let id;
23094
+ if (!relsFile) {
23095
+ id = "rId1";
23096
+ relsFiles.push({ path, rels: [{ ...rel, id }] });
23097
+ }
23098
+ else {
23099
+ id = `rId${(relsFile.rels.length + 1).toString()}`;
23100
+ relsFile.rels.push({
23101
+ ...rel,
23102
+ id,
23103
+ });
23104
+ }
23105
+ return id;
23106
+ }
23107
+ const globalReverseLookup = new WeakMap();
23108
+ function pushElement(property, propertyList) {
23109
+ let reverseLookup = globalReverseLookup.get(propertyList);
23110
+ if (!reverseLookup) {
23111
+ reverseLookup = new Map();
23112
+ for (let i = 0; i < propertyList.length; i++) {
23113
+ const canonical = getCanonicalRepresentation(propertyList[i]);
23114
+ reverseLookup.set(canonical, i);
23115
+ }
23116
+ globalReverseLookup.set(propertyList, reverseLookup);
23117
+ }
23118
+ const canonical = getCanonicalRepresentation(property);
23119
+ if (reverseLookup.has(canonical)) {
23120
+ return reverseLookup.get(canonical);
23121
+ }
23122
+ const maxId = propertyList.length;
23123
+ propertyList.push(property);
23124
+ reverseLookup.set(canonical, maxId);
23125
+ return maxId;
23126
+ }
23127
+ /**
23128
+ * Convert a chart o-spreadsheet id to a xlsx id which
23129
+ * are unsigned integers (starting from 1).
23130
+ */
23131
+ function convertChartId(chartId, construct) {
23132
+ const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23133
+ if (xlsxId === -1) {
23134
+ construct.chartIds.push(chartId);
23135
+ return construct.chartIds.length;
23136
+ }
23137
+ return xlsxId + 1;
23138
+ }
23139
+ const imageIds = [];
23140
+ /**
23141
+ * Convert a image o-spreadsheet id to a xlsx id which
23142
+ * are unsigned integers (starting from 1).
23143
+ */
23144
+ function convertImageId(imageId) {
23145
+ const xlsxId = imageIds.findIndex((id) => id === imageId);
23146
+ if (xlsxId === -1) {
23147
+ imageIds.push(imageId);
23148
+ return imageIds.length;
23149
+ }
23150
+ return xlsxId + 1;
23151
+ }
23152
+ /**
23153
+ * Convert a value expressed in dot to EMU.
23154
+ * EMU = English Metrical Unit
23155
+ * There are 914400 EMU per inch.
23156
+ *
23157
+ * /!\ A value expressed in EMU cannot be fractional.
23158
+ * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23159
+ */
23160
+ function convertDotValueToEMU(value) {
23161
+ const DPI = 96;
23162
+ return Math.round((value * 914400) / DPI);
23163
+ }
23164
+ function getRangeSize(reference, defaultSheetIndex, data) {
23165
+ let xc = reference;
23166
+ let sheetName = undefined;
23167
+ ({ xc, sheetName } = splitReference(reference));
23168
+ let rangeSheetIndex;
23169
+ if (sheetName) {
23170
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23171
+ if (index < 0) {
23172
+ throw new Error("Unable to find a sheet with the name " + sheetName);
23173
+ }
23174
+ rangeSheetIndex = index;
23175
+ }
23176
+ else {
23177
+ rangeSheetIndex = Number(defaultSheetIndex);
23178
+ }
23179
+ const zone = toUnboundedZone(xc);
23180
+ if (zone.right === undefined) {
23181
+ zone.right = data.sheets[rangeSheetIndex].colNumber;
23182
+ }
23183
+ if (zone.bottom === undefined) {
23184
+ zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23185
+ }
23186
+ return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23187
+ }
23188
+ function convertEMUToDotValue(value) {
23189
+ const DPI = 96;
23190
+ return Math.round((value * DPI) / 914400);
23191
+ }
23192
+ /**
23193
+ * Get the position of the start of a column in Excel (in px).
23194
+ */
23195
+ function getColPosition(colIndex, sheetData) {
23196
+ let position = 0;
23197
+ for (let i = 0; i < colIndex; i++) {
23198
+ const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23199
+ if (colAtIndex?.width) {
23200
+ position += colAtIndex.width;
23201
+ }
23202
+ else if (sheetData.sheetFormat?.defaultColWidth) {
23203
+ position += sheetData.sheetFormat.defaultColWidth;
23204
+ }
23205
+ else {
23206
+ position += EXCEL_DEFAULT_COL_WIDTH;
23207
+ }
23208
+ }
23209
+ return position / WIDTH_FACTOR;
23210
+ }
23211
+ /**
23212
+ * Get the position of the start of a row in Excel (in px).
23213
+ */
23214
+ function getRowPosition(rowIndex, sheetData) {
23215
+ let position = 0;
23216
+ for (let i = 0; i < rowIndex; i++) {
23217
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23218
+ if (rowAtIndex?.height) {
23219
+ position += rowAtIndex.height;
23220
+ }
23221
+ else if (sheetData.sheetFormat?.defaultRowHeight) {
23222
+ position += sheetData.sheetFormat.defaultRowHeight;
23223
+ }
23224
+ else {
23225
+ position += EXCEL_DEFAULT_ROW_HEIGHT;
23226
+ }
23227
+ }
23228
+ return position / HEIGHT_FACTOR;
23229
+ }
23230
+ /**
23231
+ * Convert the o-spreadsheet data validation decimal
23232
+ * criterion type to the corresponding excel operator.
23233
+ */
23234
+ function convertDecimalCriterionTypeToExcelOperator(operator) {
23235
+ return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23236
+ }
23237
+ /**
23238
+ * Convert the o-spreadsheet data validation date
23239
+ * criterion type to the corresponding excel operator.
23240
+ */
23241
+ function convertDateCriterionTypeToExcelOperator(operator) {
23242
+ return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23243
+ }
23244
+
22817
23245
  const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
22818
23246
  /**
22819
23247
  * Convert excel format to o_spreadsheet format
@@ -22914,6 +23342,9 @@
22914
23342
  align: styleStruct.alignment?.horizontal
22915
23343
  ? H_ALIGNMENT_CONVERSION_MAP[styleStruct.alignment.horizontal]
22916
23344
  : undefined,
23345
+ rotation: styleStruct.alignment?.textRotation
23346
+ ? rotationFromXLSX(styleStruct.alignment.textRotation)
23347
+ : undefined,
22917
23348
  // In xlsx fills, bgColor is the color of the fill, and fgColor is the color of the pattern above the background, except in solid fills
22918
23349
  fillColor: styleStruct.fillStyle?.patternType === "solid"
22919
23350
  ? convertColor(styleStruct.fillStyle?.fgColor)
@@ -23235,386 +23666,6 @@
23235
23666
  }
23236
23667
  }
23237
23668
 
23238
- const globalReverseLookup$1 = new WeakMap();
23239
- const globalIdCounter = new WeakMap();
23240
- /**
23241
- * Get the id of the given item (its key in the given dictionary).
23242
- * If the given item does not exist in the dictionary, it creates one with a new id.
23243
- */
23244
- function getItemId(item, itemsDic) {
23245
- if (!globalReverseLookup$1.has(itemsDic)) {
23246
- globalReverseLookup$1.set(itemsDic, new Map());
23247
- globalIdCounter.set(itemsDic, 0);
23248
- }
23249
- const reverseLookup = globalReverseLookup$1.get(itemsDic);
23250
- const canonical = getCanonicalRepresentation(item);
23251
- if (reverseLookup.has(canonical)) {
23252
- const id = reverseLookup.get(canonical);
23253
- itemsDic[id] = item;
23254
- return id;
23255
- }
23256
- // Generate new Id if the item didn't exist in the dictionary
23257
- const newId = globalIdCounter.get(itemsDic) + 1;
23258
- reverseLookup.set(canonical, newId);
23259
- globalIdCounter.set(itemsDic, newId);
23260
- itemsDic[newId] = item;
23261
- return newId;
23262
- }
23263
- function groupItemIdsByZones(positionsByItemId) {
23264
- const result = {};
23265
- for (const itemId in positionsByItemId) {
23266
- const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
23267
- for (const zone of zones) {
23268
- result[zoneToXc(zone)] = Number(itemId);
23269
- }
23270
- }
23271
- return result;
23272
- }
23273
- function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
23274
- for (const zoneXc in itemIdsByZones) {
23275
- const zone = toZone(zoneXc);
23276
- const itemId = itemIdsByZones[zoneXc];
23277
- for (let row = zone.top; row <= zone.bottom; row++) {
23278
- for (let col = zone.left; col <= zone.right; col++) {
23279
- const position = { sheetId, col, row };
23280
- yield [position, itemId];
23281
- }
23282
- }
23283
- }
23284
- }
23285
- function getCanonicalRepresentation(item) {
23286
- if (item === null) {
23287
- return "null";
23288
- }
23289
- if (item === undefined) {
23290
- return "undefined";
23291
- }
23292
- if (typeof item !== "object") {
23293
- return String(item);
23294
- }
23295
- if (Array.isArray(item)) {
23296
- const len = item.length;
23297
- let result = "[";
23298
- for (let i = 0; i < len; i++) {
23299
- if (i > 0) {
23300
- result += ",";
23301
- }
23302
- result += getCanonicalRepresentation(item[i]);
23303
- }
23304
- return result + "]";
23305
- }
23306
- const keys = Object.keys(item).sort();
23307
- let repr = "{";
23308
- for (const key of keys) {
23309
- if (item[key] !== undefined) {
23310
- repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
23311
- }
23312
- }
23313
- repr += "}";
23314
- return repr;
23315
- }
23316
-
23317
- // -------------------------------------
23318
- // CF HELPERS
23319
- // -------------------------------------
23320
- /**
23321
- * Convert the conditional formatting o-spreadsheet operator to
23322
- * the corresponding excel operator.
23323
- * */
23324
- function convertOperator(operator) {
23325
- switch (operator) {
23326
- case "isNotEmpty":
23327
- return "notContainsBlanks";
23328
- case "isEmpty":
23329
- return "containsBlanks";
23330
- case "notContainsText":
23331
- return "notContainsBlanks";
23332
- case "containsText":
23333
- return "containsText";
23334
- case "beginsWithText":
23335
- return "beginsWith";
23336
- case "endsWithText":
23337
- return "endsWith";
23338
- case "isGreaterThan":
23339
- return "greaterThan";
23340
- case "isGreaterOrEqualTo":
23341
- return "greaterThanOrEqual";
23342
- case "isLessThan":
23343
- return "lessThan";
23344
- case "isLessOrEqualTo":
23345
- return "lessThanOrEqual";
23346
- case "isBetween":
23347
- return "between";
23348
- case "isNotBetween":
23349
- return "notBetween";
23350
- case "isEqual":
23351
- return "equal";
23352
- case "isNotEqual":
23353
- return "notEqual";
23354
- case "customFormula":
23355
- return "";
23356
- case "dateIs":
23357
- return "";
23358
- case "dateIsBefore":
23359
- return "lessThan";
23360
- case "dateIsAfter":
23361
- return "greaterThan";
23362
- case "dateIsOnOrAfter":
23363
- return "greaterThanOrEqual";
23364
- case "dateIsOnOrBefore":
23365
- return "lessThanOrEqual";
23366
- case "top10":
23367
- return "top10";
23368
- }
23369
- }
23370
- // -------------------------------------
23371
- // WORKSHEET HELPERS
23372
- // -------------------------------------
23373
- function getCellType(value) {
23374
- switch (typeof value) {
23375
- case "boolean":
23376
- return "b";
23377
- case "string":
23378
- return "str";
23379
- case "number":
23380
- return "n";
23381
- default:
23382
- return undefined;
23383
- }
23384
- }
23385
- function convertHeightToExcel(height) {
23386
- return Math.round(HEIGHT_FACTOR * height * 100) / 100;
23387
- }
23388
- function convertWidthToExcel(width) {
23389
- return Math.round(WIDTH_FACTOR * width * 100) / 100;
23390
- }
23391
- function convertHeightFromExcel(height) {
23392
- if (!height) {
23393
- return height;
23394
- }
23395
- return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
23396
- }
23397
- function convertWidthFromExcel(width) {
23398
- if (!width) {
23399
- return width;
23400
- }
23401
- return Math.round((width / WIDTH_FACTOR) * 100) / 100;
23402
- }
23403
- function extractStyle(data, content, styleId, formatId, borderId) {
23404
- const style = styleId ? data.styles[styleId] : {};
23405
- const format = formatId ? data.formats[formatId] : undefined;
23406
- const styles = {
23407
- font: {
23408
- size: style?.fontSize || DEFAULT_FONT_SIZE,
23409
- color: { rgb: style?.textColor ? style.textColor : "000000" },
23410
- family: 2,
23411
- name: "Arial",
23412
- },
23413
- fill: style?.fillColor
23414
- ? {
23415
- fgColor: { rgb: style.fillColor },
23416
- }
23417
- : { reservedAttribute: "none" },
23418
- numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
23419
- border: borderId || 0,
23420
- alignment: {
23421
- horizontal: style.align,
23422
- vertical: style.verticalAlign
23423
- ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
23424
- : undefined,
23425
- wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
23426
- },
23427
- };
23428
- styles.font["strike"] = !!style?.strikethrough || undefined;
23429
- styles.font["underline"] = !!style?.underline || undefined;
23430
- styles.font["bold"] = !!style?.bold || undefined;
23431
- styles.font["italic"] = !!style?.italic || undefined;
23432
- return styles;
23433
- }
23434
- function normalizeStyle(construct, styles) {
23435
- // Normalize this
23436
- const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
23437
- const style = {
23438
- fontId: pushElement(styles.font, construct.fonts),
23439
- fillId: pushElement(styles.fill, construct.fills),
23440
- borderId: styles.border,
23441
- numFmtId,
23442
- alignment: {
23443
- vertical: styles.alignment.vertical,
23444
- horizontal: styles.alignment.horizontal,
23445
- wrapText: styles.alignment.wrapText,
23446
- },
23447
- };
23448
- return pushElement(style, construct.styles);
23449
- }
23450
- function convertFormat(format, numFmtStructure) {
23451
- if (!format) {
23452
- return 0;
23453
- }
23454
- let formatId = XLSX_FORMAT_MAP[format.format];
23455
- if (!formatId) {
23456
- formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23457
- }
23458
- return formatId;
23459
- }
23460
- /**
23461
- * Add a relation to the given file and return its id.
23462
- */
23463
- function addRelsToFile(relsFiles, path, rel) {
23464
- const relsFile = relsFiles.find((file) => file.path === path);
23465
- // the id is a one-based int casted as string
23466
- let id;
23467
- if (!relsFile) {
23468
- id = "rId1";
23469
- relsFiles.push({ path, rels: [{ ...rel, id }] });
23470
- }
23471
- else {
23472
- id = `rId${(relsFile.rels.length + 1).toString()}`;
23473
- relsFile.rels.push({
23474
- ...rel,
23475
- id,
23476
- });
23477
- }
23478
- return id;
23479
- }
23480
- const globalReverseLookup = new WeakMap();
23481
- function pushElement(property, propertyList) {
23482
- let reverseLookup = globalReverseLookup.get(propertyList);
23483
- if (!reverseLookup) {
23484
- reverseLookup = new Map();
23485
- for (let i = 0; i < propertyList.length; i++) {
23486
- const canonical = getCanonicalRepresentation(propertyList[i]);
23487
- reverseLookup.set(canonical, i);
23488
- }
23489
- globalReverseLookup.set(propertyList, reverseLookup);
23490
- }
23491
- const canonical = getCanonicalRepresentation(property);
23492
- if (reverseLookup.has(canonical)) {
23493
- return reverseLookup.get(canonical);
23494
- }
23495
- const maxId = propertyList.length;
23496
- propertyList.push(property);
23497
- reverseLookup.set(canonical, maxId);
23498
- return maxId;
23499
- }
23500
- /**
23501
- * Convert a chart o-spreadsheet id to a xlsx id which
23502
- * are unsigned integers (starting from 1).
23503
- */
23504
- function convertChartId(chartId, construct) {
23505
- const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23506
- if (xlsxId === -1) {
23507
- construct.chartIds.push(chartId);
23508
- return construct.chartIds.length;
23509
- }
23510
- return xlsxId + 1;
23511
- }
23512
- const imageIds = [];
23513
- /**
23514
- * Convert a image o-spreadsheet id to a xlsx id which
23515
- * are unsigned integers (starting from 1).
23516
- */
23517
- function convertImageId(imageId) {
23518
- const xlsxId = imageIds.findIndex((id) => id === imageId);
23519
- if (xlsxId === -1) {
23520
- imageIds.push(imageId);
23521
- return imageIds.length;
23522
- }
23523
- return xlsxId + 1;
23524
- }
23525
- /**
23526
- * Convert a value expressed in dot to EMU.
23527
- * EMU = English Metrical Unit
23528
- * There are 914400 EMU per inch.
23529
- *
23530
- * /!\ A value expressed in EMU cannot be fractional.
23531
- * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23532
- */
23533
- function convertDotValueToEMU(value) {
23534
- const DPI = 96;
23535
- return Math.round((value * 914400) / DPI);
23536
- }
23537
- function getRangeSize(reference, defaultSheetIndex, data) {
23538
- let xc = reference;
23539
- let sheetName = undefined;
23540
- ({ xc, sheetName } = splitReference(reference));
23541
- let rangeSheetIndex;
23542
- if (sheetName) {
23543
- const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23544
- if (index < 0) {
23545
- throw new Error("Unable to find a sheet with the name " + sheetName);
23546
- }
23547
- rangeSheetIndex = index;
23548
- }
23549
- else {
23550
- rangeSheetIndex = Number(defaultSheetIndex);
23551
- }
23552
- const zone = toUnboundedZone(xc);
23553
- if (zone.right === undefined) {
23554
- zone.right = data.sheets[rangeSheetIndex].colNumber;
23555
- }
23556
- if (zone.bottom === undefined) {
23557
- zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23558
- }
23559
- return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23560
- }
23561
- function convertEMUToDotValue(value) {
23562
- const DPI = 96;
23563
- return Math.round((value * DPI) / 914400);
23564
- }
23565
- /**
23566
- * Get the position of the start of a column in Excel (in px).
23567
- */
23568
- function getColPosition(colIndex, sheetData) {
23569
- let position = 0;
23570
- for (let i = 0; i < colIndex; i++) {
23571
- const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23572
- if (colAtIndex?.width) {
23573
- position += colAtIndex.width;
23574
- }
23575
- else if (sheetData.sheetFormat?.defaultColWidth) {
23576
- position += sheetData.sheetFormat.defaultColWidth;
23577
- }
23578
- else {
23579
- position += EXCEL_DEFAULT_COL_WIDTH;
23580
- }
23581
- }
23582
- return position / WIDTH_FACTOR;
23583
- }
23584
- /**
23585
- * Get the position of the start of a row in Excel (in px).
23586
- */
23587
- function getRowPosition(rowIndex, sheetData) {
23588
- let position = 0;
23589
- for (let i = 0; i < rowIndex; i++) {
23590
- const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23591
- if (rowAtIndex?.height) {
23592
- position += rowAtIndex.height;
23593
- }
23594
- else if (sheetData.sheetFormat?.defaultRowHeight) {
23595
- position += sheetData.sheetFormat.defaultRowHeight;
23596
- }
23597
- else {
23598
- position += EXCEL_DEFAULT_ROW_HEIGHT;
23599
- }
23600
- }
23601
- return position / HEIGHT_FACTOR;
23602
- }
23603
- /**
23604
- * Convert the o-spreadsheet data validation decimal
23605
- * criterion type to the corresponding excel operator.
23606
- */
23607
- function convertDecimalCriterionTypeToExcelOperator(operator) {
23608
- return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23609
- }
23610
- /**
23611
- * Convert the o-spreadsheet data validation date
23612
- * criterion type to the corresponding excel operator.
23613
- */
23614
- function convertDateCriterionTypeToExcelOperator(operator) {
23615
- return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23616
- }
23617
-
23618
23669
  function convertFigures(sheetData) {
23619
23670
  let id = 1;
23620
23671
  return sheetData.figures
@@ -23704,6 +23755,7 @@
23704
23755
  horizontal: chartData.horizontal,
23705
23756
  isDoughnut: chartData.isDoughnut,
23706
23757
  pieHolePercentage: chartData.pieHolePercentage,
23758
+ showValues: chartData.showValues,
23707
23759
  };
23708
23760
  try {
23709
23761
  const ChartClass = chartRegistry.get(chartData.type);
@@ -25432,6 +25484,8 @@
25432
25484
  const chartHoleSize = this.extractChildAttr(rootChartElement, "c:holeSize", "val", {
25433
25485
  default: "0",
25434
25486
  }).asNum();
25487
+ const showValueNodes = this.querySelectorAll(rootChartElement, "c:chart c:showVal");
25488
+ const showValues = [...showValueNodes].some((el) => el.attributes.getNamedItem("val")?.value === "1");
25435
25489
  return {
25436
25490
  title: { text: chartTitle },
25437
25491
  type: CHART_TYPE_CONVERSION_MAP[chartType],
@@ -25448,6 +25502,7 @@
25448
25502
  horizontal: chartDirection === "bar",
25449
25503
  isDoughnut: chartHoleSize > 0,
25450
25504
  pieHolePercentage: chartHoleSize,
25505
+ showValues,
25451
25506
  };
25452
25507
  })[0];
25453
25508
  }
@@ -25466,6 +25521,8 @@
25466
25521
  const barChartGrouping = this.extractChildAttr(chartElement, "c:grouping", "val", {
25467
25522
  default: "clustered",
25468
25523
  }).asString();
25524
+ const showValueNodes = this.querySelectorAll(chartElement, "c:chart c:showVal");
25525
+ const showValues = [...showValueNodes].some((el) => el.attributes.getNamedItem("val")?.value === "1");
25469
25526
  return {
25470
25527
  title: { text: chartTitle },
25471
25528
  type: "combo",
@@ -25482,6 +25539,7 @@
25482
25539
  }).asString()],
25483
25540
  stacked: barChartGrouping === "stacked",
25484
25541
  fontColor: "000000",
25542
+ showValues,
25485
25543
  };
25486
25544
  }
25487
25545
  extractChartDatasets(chartElements, chartType) {
@@ -27717,7 +27775,7 @@
27717
27775
  * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
27718
27776
  * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
27719
27777
  */
27720
- adaptRanges(applyChange, sheetId, sheetName) { }
27778
+ adaptRanges(rangeAdapterFunctions, sheetId, sheetName) { }
27721
27779
  }
27722
27780
 
27723
27781
  class BordersPlugin extends CorePlugin {
@@ -27792,7 +27850,7 @@
27792
27850
  }
27793
27851
  }
27794
27852
  }
27795
- adaptRanges(applyChange, sheetId) {
27853
+ adaptRanges({ applyChange }, sheetId) {
27796
27854
  const newBorders = [];
27797
27855
  for (const border of this.borders[sheetId] ?? []) {
27798
27856
  const change = applyChange(this.getters.getRangeFromZone(sheetId, border.zone));
@@ -28279,7 +28337,7 @@
28279
28337
  ];
28280
28338
  nextId = 1;
28281
28339
  cells = {};
28282
- adaptRanges(applyChange, sheetId, sheetName) {
28340
+ adaptRanges({ applyChange }, sheetId, sheetName) {
28283
28341
  for (const sheet of Object.keys(this.cells)) {
28284
28342
  for (const cell of Object.values(this.cells[sheet] || {})) {
28285
28343
  if (cell.isFormula) {
@@ -28482,8 +28540,8 @@
28482
28540
  for (const _sheet of data.sheets) {
28483
28541
  const positionsByFormat = [];
28484
28542
  const cells = {};
28485
- const positions = Object.keys(this.cells[_sheet.id] || {})
28486
- .map((cellId) => this.getters.getCellPosition(cellId))
28543
+ const positions = Object.values(this.cells[_sheet.id] || {})
28544
+ .map((cell) => this.getters.getCellPosition(cell.id))
28487
28545
  .sort((a, b) => (a.col === b.col ? a.row - b.row : a.col - b.col));
28488
28546
  for (const position of positions) {
28489
28547
  const cell = this.getters.getCell(position);
@@ -28503,7 +28561,7 @@
28503
28561
  data.formats = formats;
28504
28562
  }
28505
28563
  importCell(sheetId, content, format) {
28506
- const cellId = this.getNextUid();
28564
+ const cellId = this.getNextCellId();
28507
28565
  return this.createCell(cellId, content || "", format, sheetId);
28508
28566
  }
28509
28567
  exportForExcel(data) {
@@ -28530,7 +28588,7 @@
28530
28588
  // GETTERS
28531
28589
  // ---------------------------------------------------------------------------
28532
28590
  getCells(sheetId) {
28533
- return this.cells[sheetId] || {};
28591
+ return Object.values(this.cells[sheetId] || {});
28534
28592
  }
28535
28593
  /**
28536
28594
  * get a cell by ID. Used in evaluation when evaluating an async cell, we need to be able to find it back after
@@ -28646,8 +28704,8 @@
28646
28704
  }
28647
28705
  return format;
28648
28706
  }
28649
- getNextUid() {
28650
- const id = this.nextId.toString();
28707
+ getNextCellId() {
28708
+ const id = this.nextId;
28651
28709
  this.history.update("nextId", this.nextId + 1);
28652
28710
  return id;
28653
28711
  }
@@ -28678,7 +28736,7 @@
28678
28736
  }
28679
28737
  return;
28680
28738
  }
28681
- const cellId = before?.id || this.getNextUid();
28739
+ const cellId = before?.id || this.getNextCellId();
28682
28740
  const cell = this.createCell(cellId, afterContent, format, sheetId);
28683
28741
  this.history.update("cells", sheetId, cell.id, cell);
28684
28742
  this.dispatch("UPDATE_CELL_POSITION", { cellId: cell.id, col, row, sheetId });
@@ -28842,12 +28900,12 @@
28842
28900
  charts = {};
28843
28901
  createChart = chartFactory(this.getters);
28844
28902
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
28845
- adaptRanges(applyChange, sheetId, adaptSheetName) {
28903
+ adaptRanges(rangeAdapters) {
28846
28904
  for (const [chartId, chart] of Object.entries(this.charts)) {
28847
28905
  if (!chart) {
28848
28906
  continue;
28849
28907
  }
28850
- const newChart = chart.chart.updateRanges(applyChange, sheetId, adaptSheetName);
28908
+ const newChart = chart.chart.updateRanges(rangeAdapters);
28851
28909
  this.history.update("charts", chartId, newChart ? { figureId: chart.figureId, chart: newChart } : undefined);
28852
28910
  }
28853
28911
  }
@@ -29738,7 +29796,7 @@
29738
29796
  "getAdaptedCfRanges",
29739
29797
  ];
29740
29798
  cfRules = {};
29741
- adaptCFFormulas(applyChange) {
29799
+ adaptCFFormulas({ applyChange, adaptFormulaString }) {
29742
29800
  for (const sheetId in this.cfRules) {
29743
29801
  for (const rule of this.cfRules[sheetId]) {
29744
29802
  if (rule.rule.type === "DataBarRule" && rule.rule.rangeValues) {
@@ -29762,7 +29820,7 @@
29762
29820
  for (let i = 0; i < rule.rule.values.length; i++) {
29763
29821
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29764
29822
  //@ts-expect-error
29765
- "values", i, this.getters.adaptFormulaStringDependencies(sheetId, rule.rule.values[i], applyChange));
29823
+ "values", i, adaptFormulaString(sheetId, rule.rule.values[i]));
29766
29824
  }
29767
29825
  }
29768
29826
  else if (rule.rule.type === "IconSetRule") {
@@ -29770,7 +29828,7 @@
29770
29828
  if (rule.rule[inflectionPoint].type === "formula") {
29771
29829
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29772
29830
  //@ts-expect-error
29773
- inflectionPoint, "value", this.getters.adaptFormulaStringDependencies(sheetId, rule.rule[inflectionPoint].value, applyChange));
29831
+ inflectionPoint, "value", adaptFormulaString(sheetId, rule.rule[inflectionPoint].value));
29774
29832
  }
29775
29833
  }
29776
29834
  }
@@ -29780,14 +29838,14 @@
29780
29838
  if (ruleValue?.type === "formula" && ruleValue?.value) {
29781
29839
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29782
29840
  //@ts-expect-error
29783
- value, "value", this.getters.adaptFormulaStringDependencies(sheetId, ruleValue.value, applyChange));
29841
+ value, "value", adaptFormulaString(sheetId, ruleValue.value));
29784
29842
  }
29785
29843
  }
29786
29844
  }
29787
29845
  }
29788
29846
  }
29789
29847
  }
29790
- adaptCFRanges(sheetId, applyChange) {
29848
+ adaptCFRanges(sheetId, { applyChange }) {
29791
29849
  for (const rule of this.cfRules[sheetId]) {
29792
29850
  for (const range of rule.ranges) {
29793
29851
  const change = applyChange(range);
@@ -29811,12 +29869,12 @@
29811
29869
  }
29812
29870
  }
29813
29871
  }
29814
- adaptRanges(applyChange, sheetId) {
29872
+ adaptRanges(rangeAdapters, sheetId) {
29815
29873
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
29816
29874
  for (const sheetId of sheetIds) {
29817
- this.adaptCFRanges(sheetId, applyChange);
29875
+ this.adaptCFRanges(sheetId, rangeAdapters);
29818
29876
  }
29819
- this.adaptCFFormulas(applyChange);
29877
+ this.adaptCFFormulas(rangeAdapters);
29820
29878
  }
29821
29879
  // ---------------------------------------------------------------------------
29822
29880
  // Command Handling
@@ -30197,23 +30255,23 @@
30197
30255
  "getValidationRuleForCell",
30198
30256
  ];
30199
30257
  rules = {};
30200
- adaptRanges(applyChange, sheetId) {
30201
- this.adaptDVRanges(sheetId, applyChange);
30202
- this.adaptDVFormulas(applyChange);
30258
+ adaptRanges(rangeAdapters, sheetId) {
30259
+ this.adaptDVRanges(sheetId, rangeAdapters);
30260
+ this.adaptDVFormulas(rangeAdapters);
30203
30261
  }
30204
- adaptDVFormulas(applyChange) {
30262
+ adaptDVFormulas({ adaptFormulaString }) {
30205
30263
  for (const sheetId in this.rules) {
30206
30264
  const rules = this.rules[sheetId];
30207
30265
  for (let ruleIndex = rules.length - 1; ruleIndex >= 0; ruleIndex--) {
30208
30266
  const rule = this.rules[sheetId][ruleIndex];
30209
30267
  for (let valueIndex = 0; valueIndex < rule.criterion.values.length; valueIndex++) {
30210
- const value = this.getters.adaptFormulaStringDependencies(sheetId, rule.criterion.values[valueIndex], applyChange);
30268
+ const value = adaptFormulaString(sheetId, rule.criterion.values[valueIndex]);
30211
30269
  this.history.update("rules", sheetId, ruleIndex, "criterion", "values", valueIndex, value);
30212
30270
  }
30213
30271
  }
30214
30272
  }
30215
30273
  }
30216
- adaptDVRanges(sheetId, applyChange) {
30274
+ adaptDVRanges(sheetId, { applyChange }) {
30217
30275
  const rules = this.rules[sheetId];
30218
30276
  for (let ruleIndex = rules.length - 1; ruleIndex >= 0; ruleIndex--) {
30219
30277
  const rule = this.rules[sheetId][ruleIndex];
@@ -30488,7 +30546,7 @@
30488
30546
  // ---------------------------------------------------------------------------
30489
30547
  // Command Handling
30490
30548
  // ---------------------------------------------------------------------------
30491
- adaptRanges(applyChange, sheetId) {
30549
+ adaptRanges({ applyChange }, sheetId) {
30492
30550
  for (const figure of this.getFigures(sheetId)) {
30493
30551
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
30494
30552
  left: figure.col,
@@ -31728,8 +31786,8 @@
31728
31786
  break;
31729
31787
  }
31730
31788
  }
31731
- adaptRanges(applyChange, sheetId) {
31732
- this.applyRangeChangeOnSheet(sheetId, applyChange);
31789
+ adaptRanges(rangeAdapters, sheetId) {
31790
+ this.applyRangeChangeOnSheet(sheetId, rangeAdapters);
31733
31791
  }
31734
31792
  // ---------------------------------------------------------------------------
31735
31793
  // Getters
@@ -32012,7 +32070,7 @@
32012
32070
  /**
32013
32071
  * Apply a range change on merges of a particular sheet.
32014
32072
  */
32015
- applyRangeChangeOnSheet(sheetId, applyChange) {
32073
+ applyRangeChangeOnSheet(sheetId, { applyChange }) {
32016
32074
  const merges = Object.entries(this.merges[sheetId] || {});
32017
32075
  for (const [mergeId, range] of merges) {
32018
32076
  if (range) {
@@ -33650,8 +33708,6 @@
33650
33708
  }
33651
33709
  const change = applyChange(range);
33652
33710
  switch (change.changeType) {
33653
- case "NONE":
33654
- return range;
33655
33711
  case "REMOVE":
33656
33712
  return undefined;
33657
33713
  default:
@@ -33760,7 +33816,7 @@
33760
33816
  }
33761
33817
  }
33762
33818
  }
33763
- adaptRanges(applyChange) {
33819
+ adaptRanges({ applyChange, adaptFormulaString }) {
33764
33820
  for (const pivotId in this.pivots) {
33765
33821
  const definition = deepCopy(this.pivots[pivotId]?.definition);
33766
33822
  if (!definition) {
@@ -33780,19 +33836,13 @@
33780
33836
  continue;
33781
33837
  }
33782
33838
  const sheetId = measure.computedBy.sheetId;
33783
- const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
33784
- const newDependencies = [];
33785
- for (const range of compiledFormula.dependencies) {
33786
- const change = applyChange(range);
33787
- if (change.changeType === "NONE") {
33788
- newDependencies.push(range);
33789
- }
33790
- else {
33791
- newDependencies.push(change.range);
33792
- }
33793
- }
33794
- const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
33839
+ const { formula: compiledFormula, dependencies: indirectDependencies } = this.compiledMeasureFormulas[pivotId][measureId];
33840
+ // adapt direct dependencies
33841
+ this.history.update("compiledMeasureFormulas", pivotId, measureId, "formula", "dependencies", compiledFormula.dependencies.map((range) => applyChange(range).range));
33842
+ // adapt all dependencies (including indirect)
33843
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", indirectDependencies.map((range) => applyChange(range).range));
33795
33844
  const oldFormulaString = measure.computedBy.formula;
33845
+ const newFormulaString = adaptFormulaString(sheetId, oldFormulaString);
33796
33846
  if (newFormulaString !== oldFormulaString) {
33797
33847
  this.replaceMeasureFormula(pivotId, measure, newFormulaString);
33798
33848
  }
@@ -33954,7 +34004,6 @@
33954
34004
  formula: newFormulaString,
33955
34005
  sheetId: measure.computedBy.sheetId,
33956
34006
  });
33957
- this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
33958
34007
  }
33959
34008
  checkSortedColumnInMeasures(definition) {
33960
34009
  const measures = definition.measures.map((measure) => measure.id);
@@ -34047,7 +34096,7 @@
34047
34096
  }
34048
34097
  changeCellsDateFormatWithLocale(oldLocale, newLocale) {
34049
34098
  for (const sheetId of this.getters.getSheetIds()) {
34050
- for (const [cellId, cell] of Object.entries(this.getters.getCells(sheetId))) {
34099
+ for (const cell of this.getters.getCells(sheetId)) {
34051
34100
  let formatToApply;
34052
34101
  if (cell.format === oldLocale.dateFormat) {
34053
34102
  formatToApply = newLocale.dateFormat;
@@ -34059,7 +34108,7 @@
34059
34108
  formatToApply = getDateTimeFormat(newLocale);
34060
34109
  }
34061
34110
  if (formatToApply) {
34062
- const { col, row, sheetId } = this.getters.getCellPosition(cellId);
34111
+ const { col, row, sheetId } = this.getters.getCellPosition(cell.id);
34063
34112
  this.dispatch("UPDATE_CELL", {
34064
34113
  col,
34065
34114
  row,
@@ -34093,7 +34142,7 @@
34093
34142
  "getCell",
34094
34143
  "getCellPosition",
34095
34144
  "getColsZone",
34096
- "getRowCells",
34145
+ "getRowCellIds",
34097
34146
  "getRowsZone",
34098
34147
  "getNumberCols",
34099
34148
  "getNumberRows",
@@ -34393,7 +34442,7 @@
34393
34442
  right: end,
34394
34443
  };
34395
34444
  }
34396
- getRowCells(sheetId, row) {
34445
+ getRowCellIds(sheetId, row) {
34397
34446
  return Object.values(this.getSheet(sheetId).rows[row]?.cells).filter(isDefined);
34398
34447
  }
34399
34448
  getRowsZone(sheetId, start, end) {
@@ -34690,7 +34739,7 @@
34690
34739
  orderedSheetIds.splice(currentIndex + 1, 0, newSheet.id);
34691
34740
  this.history.update("orderedSheetIds", orderedSheetIds);
34692
34741
  this.history.update("sheets", Object.assign({}, this.sheets, { [newSheet.id]: newSheet }));
34693
- for (const cell of Object.values(this.getters.getCells(fromId))) {
34742
+ for (const cell of this.getters.getCells(fromId)) {
34694
34743
  const { sheetId, col, row } = this.getCellPosition(cell.id);
34695
34744
  const style = this.getters.getCellStyle({ sheetId, col, row });
34696
34745
  this.dispatch("UPDATE_CELL", {
@@ -35049,7 +35098,7 @@
35049
35098
  break;
35050
35099
  }
35051
35100
  }
35052
- adaptRanges(applyChange, sheetId) {
35101
+ adaptRanges({ applyChange }, sheetId) {
35053
35102
  const newStyles = [];
35054
35103
  for (const style of this.styles[sheetId] ?? []) {
35055
35104
  const change = applyChange(this.getters.getRangeFromZone(sheetId, style.zone));
@@ -36048,7 +36097,7 @@
36048
36097
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
36049
36098
  tables = {};
36050
36099
  nextTableId = 1;
36051
- adaptRanges(applyChange, sheetId) {
36100
+ adaptRanges({ applyChange }, sheetId) {
36052
36101
  for (const table of this.getCoreTables(sheetId)) {
36053
36102
  this.applyRangeChangeOnTable(sheetId, table, applyChange);
36054
36103
  }
@@ -37914,11 +37963,16 @@
37914
37963
  return this.arrayFormulasToResults.get(formulasPosition);
37915
37964
  }
37916
37965
  /**
37917
- * Remove a node, also remove it from other nodes adjacency list
37966
+ * Remove a spreading relation for a given array formula position
37967
+ * and its result zone
37918
37968
  */
37919
37969
  removeNode(position) {
37970
+ const resultZone = this.arrayFormulasToResults.get(position);
37971
+ if (!resultZone) {
37972
+ return;
37973
+ }
37920
37974
  this.resultsToArrayFormulas.remove({
37921
- boundingBox: { sheetId: position.sheetId, zone: positionToZone(position) },
37975
+ boundingBox: { sheetId: position.sheetId, zone: resultZone },
37922
37976
  data: position,
37923
37977
  });
37924
37978
  this.arrayFormulasToResults.delete(position);
@@ -38072,9 +38126,7 @@
38072
38126
  this.formulaDependencies = lazy(() => {
38073
38127
  const rTreeItems = [];
38074
38128
  for (const sheetId of this.getters.getSheetIds()) {
38075
- const cells = this.getters.getCells(sheetId);
38076
- for (const cellId in cells) {
38077
- const cell = cells[cellId];
38129
+ for (const cell of this.getters.getCells(sheetId)) {
38078
38130
  if (cell.isFormula) {
38079
38131
  const directDependencies = cell.compiledFormula.dependencies;
38080
38132
  for (const range of directDependencies) {
@@ -38084,7 +38136,7 @@
38084
38136
  rTreeItems.push({
38085
38137
  data: {
38086
38138
  sheetId,
38087
- zone: positionToZone(this.getters.getCellPosition(cellId)),
38139
+ zone: positionToZone(this.getters.getCellPosition(cell.id)),
38088
38140
  },
38089
38141
  boundingBox: { sheetId: range.sheetId, zone: range.zone },
38090
38142
  });
@@ -38245,6 +38297,10 @@
38245
38297
  // empty matrix
38246
38298
  return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
38247
38299
  }
38300
+ if (nbRows === 1 && nbColumns === 1) {
38301
+ // single value matrix
38302
+ return createEvaluatedCell(validateNumberValue(formulaReturn[0][0]), this.getters.getLocale(), cellData);
38303
+ }
38248
38304
  const resultZone = {
38249
38305
  top: formulaPosition.row,
38250
38306
  bottom: formulaPosition.row + nbRows - 1,
@@ -38763,11 +38819,20 @@
38763
38819
  /**
38764
38820
  * Get the default height of the cell given its style.
38765
38821
  */
38766
- function getDefaultCellHeight(ctx, cell, style, colSize) {
38822
+ function getDefaultCellHeight(ctx, cell, style, locale, colSize) {
38767
38823
  if (!cell || (!cell.isFormula && !cell.content)) {
38768
38824
  return DEFAULT_CELL_HEIGHT;
38769
38825
  }
38770
- const content = cell.isFormula ? "" : cell.content;
38826
+ let content = "";
38827
+ try {
38828
+ if (!cell.isFormula) {
38829
+ const localeFormat = { format: cell.format, locale };
38830
+ content = formatValue(parseLiteral(cell.content, locale), localeFormat);
38831
+ }
38832
+ }
38833
+ catch {
38834
+ content = CellErrorType.GenericError;
38835
+ }
38771
38836
  return getCellContentHeight(ctx, content, style, colSize);
38772
38837
  }
38773
38838
  function getCellContentHeight(ctx, content, style, colSize) {
@@ -40389,15 +40454,15 @@
40389
40454
  if (!extensionsLoaded) {
40390
40455
  registerChartJSExtensions();
40391
40456
  }
40392
- if (!globalThis.Chart.registry.controllers.get(type)) {
40393
- console.log(`Chart of type "${type}" is not registered in Chart.js library.`);
40457
+ const config = deepCopy(runtime.chartJsConfig);
40458
+ config.plugins = [backgroundColorChartJSPlugin];
40459
+ if (!globalThis.Chart.registry.controllers.get(config.type)) {
40460
+ console.log(`Chart of type "${config.type}" is not registered in Chart.js library.`);
40394
40461
  if (!extensionsLoaded) {
40395
40462
  unregisterChartJsExtensions();
40396
40463
  }
40397
40464
  return imageUrl;
40398
40465
  }
40399
- const config = deepCopy(runtime.chartJsConfig);
40400
- config.plugins = [backgroundColorChartJSPlugin];
40401
40466
  const chart = new globalThis.Chart(canvas, config);
40402
40467
  try {
40403
40468
  imageUrl = await canvasToObjectUrl(canvas);
@@ -41073,12 +41138,10 @@
41073
41138
  this.trackedCells[formula] = {};
41074
41139
  }
41075
41140
  for (const sheetId of this.getters.getSheetIds()) {
41076
- const cells = this.getters.getCells(sheetId);
41077
- for (const cellId in cells) {
41078
- const cell = cells[cellId];
41141
+ for (const cell of this.getters.getCells(sheetId)) {
41079
41142
  for (const formula of trackedFormulas) {
41080
41143
  if (doesCellContainFunction(cell, formula)) {
41081
- this.history.update("trackedCells", formula, cell.id, true);
41144
+ this.history.update("trackedCells", formula, cell.id, cell.id);
41082
41145
  }
41083
41146
  }
41084
41147
  }
@@ -41097,7 +41160,7 @@
41097
41160
  }
41098
41161
  for (const formula of trackedFormulas) {
41099
41162
  if (doesCellContainFunction(cell, formula)) {
41100
- this.history.update("trackedCells", formula, cell.id, true);
41163
+ this.history.update("trackedCells", formula, cell.id, cell.id);
41101
41164
  }
41102
41165
  else if (this.trackedCells[formula][cell.id]) {
41103
41166
  this.history.update("trackedCells", formula, cell.id, undefined);
@@ -41108,7 +41171,9 @@
41108
41171
  }
41109
41172
  }
41110
41173
  getCellsWithTrackedFormula(formula) {
41111
- return Object.keys(this.trackedCells[formula] || {}).filter((cellId) => this.trackedCells[formula][cellId] && this.getters.tryGetCellPosition(cellId));
41174
+ return Object.values(this.trackedCells[formula] || {}).filter((cellId) => cellId !== undefined &&
41175
+ this.trackedCells[formula][cellId] &&
41176
+ this.getters.tryGetCellPosition(cellId));
41112
41177
  }
41113
41178
  }
41114
41179
 
@@ -41136,6 +41201,7 @@
41136
41201
  handle(cmd) {
41137
41202
  switch (cmd.type) {
41138
41203
  case "START":
41204
+ case "UPDATE_LOCALE":
41139
41205
  for (const sheetId of this.getters.getSheetIds()) {
41140
41206
  this.initializeSheet(sheetId);
41141
41207
  }
@@ -41273,7 +41339,7 @@
41273
41339
  const cell = this.getters.getCell(position);
41274
41340
  const style = this.getters.getCellStyle(position);
41275
41341
  const colSize = this.getters.getColSize(position.sheetId, position.col);
41276
- return getDefaultCellHeight(this.ctx, cell, style, colSize);
41342
+ return getDefaultCellHeight(this.ctx, cell, style, this.getters.getLocale(), colSize);
41277
41343
  }
41278
41344
  isInMultiRowMerge(position) {
41279
41345
  const merge = this.getters.getMerge(position);
@@ -41287,7 +41353,7 @@
41287
41353
  if (userRowSize !== undefined) {
41288
41354
  return undefined;
41289
41355
  }
41290
- const cellIds = this.getters.getRowCells(sheetId, row);
41356
+ const cellIds = this.getters.getRowCellIds(sheetId, row);
41291
41357
  let maxHeight = 0;
41292
41358
  let tallestCell = undefined;
41293
41359
  for (let i = 0; i < cellIds.length; i++) {
@@ -42221,8 +42287,8 @@
42221
42287
  }
42222
42288
  const unusedPivots = new Set(this.getters.getPivotIds());
42223
42289
  for (const sheetId of this.getters.getSheetIds()) {
42224
- for (const cellId in this.getters.getCells(sheetId)) {
42225
- const position = this.getters.getCellPosition(cellId);
42290
+ for (const cell of this.getters.getCells(sheetId)) {
42291
+ const position = this.getters.getCellPosition(cell.id);
42226
42292
  const pivotId = this.getPivotIdFromPosition(position);
42227
42293
  if (pivotId) {
42228
42294
  unusedPivots.delete(pivotId);
@@ -48734,7 +48800,7 @@
48734
48800
  .add("cell_icon", CellIconPlugin)
48735
48801
  .add("formula_tracker", FormulaTrackerPlugin);
48736
48802
 
48737
- class RangeAdapter {
48803
+ class RangeAdapterPlugin {
48738
48804
  getters;
48739
48805
  providers = [];
48740
48806
  isAdaptingRanges = false;
@@ -48742,7 +48808,6 @@
48742
48808
  this.getters = getters;
48743
48809
  }
48744
48810
  static getters = [
48745
- "adaptFormulaStringDependencies",
48746
48811
  "copyFormulaStringForSheet",
48747
48812
  "extendRange",
48748
48813
  "getRangeString",
@@ -48773,8 +48838,8 @@
48773
48838
  throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
48774
48839
  }
48775
48840
  const rangeAdapter = getRangeAdapter(cmd);
48776
- if (rangeAdapter?.applyChange) {
48777
- this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
48841
+ if (rangeAdapter) {
48842
+ this.executeOnAllRanges(rangeAdapter);
48778
48843
  }
48779
48844
  }
48780
48845
  finalize() { }
@@ -48793,11 +48858,15 @@
48793
48858
  return result;
48794
48859
  };
48795
48860
  }
48796
- executeOnAllRanges(adaptRange, sheetId, sheetName) {
48861
+ executeOnAllRanges(rangeAdapter) {
48797
48862
  this.isAdaptingRanges = true;
48798
- const func = this.verifyRangeRemoved(adaptRange);
48863
+ const adapterFunctions = {
48864
+ applyChange: this.verifyRangeRemoved(rangeAdapter.applyChange),
48865
+ adaptRangeString: (defaultSheetId, sheetXC) => adaptStringRange(defaultSheetId, sheetXC, rangeAdapter),
48866
+ adaptFormulaString: (defaultSheetId, formula) => adaptFormulaStringRanges(defaultSheetId, formula, rangeAdapter),
48867
+ };
48799
48868
  for (const provider of this.providers) {
48800
- provider(func, sheetId, sheetName);
48869
+ provider(adapterFunctions, rangeAdapter.sheetId, rangeAdapter.sheetName);
48801
48870
  }
48802
48871
  this.isAdaptingRanges = false;
48803
48872
  }
@@ -48965,18 +49034,6 @@
48965
49034
  const unionOfZones = unionUnboundedZones(...zones);
48966
49035
  return this.getRangeFromZone(ranges[0].sheetId, unionOfZones);
48967
49036
  }
48968
- adaptFormulaStringDependencies(sheetId, formula, applyChange) {
48969
- if (!formula.startsWith("=")) {
48970
- return formula;
48971
- }
48972
- const compiledFormula = compile(formula);
48973
- const updatedDependencies = compiledFormula.dependencies.map((dep) => {
48974
- const range = this.getters.getRangeFromSheetXC(sheetId, dep);
48975
- const changedRange = applyChange(range);
48976
- return changedRange.changeType === "NONE" ? range : changedRange.range;
48977
- });
48978
- return this.getters.getFormulaString(sheetId, compiledFormula.tokens, updatedDependencies);
48979
- }
48980
49037
  /**
48981
49038
  * Copy a formula string to another sheet.
48982
49039
  *
@@ -49960,6 +50017,7 @@
49960
50017
  <c:order val="${dsIndex}"/>
49961
50018
  ${extractTrendline(dataset.trend, color)}
49962
50019
  ${extractDataSetLabel(dataset.label)}
50020
+ ${insertDataLabels({ showValues: chart.showValues })}
49963
50021
  ${dataShapeProperty}
49964
50022
  ${chart.labelRange ? escapeXml /*xml*/ `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
49965
50023
  <c:val> <!-- x-coordinate values -->
@@ -49987,6 +50045,7 @@
49987
50045
  <!-- each data marker in the series does not have a different color -->
49988
50046
  <c:varyColors val="0"/>
49989
50047
  ${joinXmlNodes(leftDataSetsNodes)}
50048
+ ${insertDataLabels({ showValues: chart.showValues })}
49990
50049
  <c:axId val="${catAxId}" />
49991
50050
  <c:axId val="${valAxId}" />
49992
50051
  </c:barChart>
@@ -50035,6 +50094,7 @@
50035
50094
  <c:order val="0"/>
50036
50095
  ${extractTrendline(dataSet.trend, firstColor)}
50037
50096
  ${extractDataSetLabel(dataSet.label)}
50097
+ ${insertDataLabels({ showValues: chart.showValues })}
50038
50098
  ${shapeProperty({
50039
50099
  backgroundColor: firstColor,
50040
50100
  line: { color: firstColor },
@@ -50067,6 +50127,7 @@
50067
50127
  </c:marker>
50068
50128
  ${extractTrendline(dataSet.trend, color)}
50069
50129
  ${extractDataSetLabel(dataSet.label)}
50130
+ ${insertDataLabels({ showValues: chart.showValues })}
50070
50131
  ${dataShapeProperty}
50071
50132
  ${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
50072
50133
  <!-- x-coordinate values -->
@@ -50092,6 +50153,7 @@
50092
50153
  <!-- each data marker in the series does not have a different color -->
50093
50154
  <c:varyColors val="0"/>
50094
50155
  ${barDataSetNode}
50156
+ ${insertDataLabels({ showValues: chart.showValues })}
50095
50157
  <c:axId val="${useRightAxisForBarSerie ? secondaryCatAxId : catAxId}" />
50096
50158
  <c:axId val="${useRightAxisForBarSerie ? secondaryValAxId : valAxId}" />
50097
50159
  </c:barChart>
@@ -50101,6 +50163,7 @@
50101
50163
  <c:grouping val="standard"/>
50102
50164
  <!-- each data marker in the series does not have a different color -->
50103
50165
  <c:varyColors val="0"/>
50166
+ ${insertDataLabels({ showValues: chart.showValues })}
50104
50167
  ${joinXmlNodes(leftDataSetsNodes)}
50105
50168
  <c:axId val="${catAxId}" />
50106
50169
  <c:axId val="${valAxId}" />
@@ -50113,6 +50176,7 @@
50113
50176
  <c:grouping val="standard"/>
50114
50177
  <!-- each data marker in the series does not have a different color -->
50115
50178
  <c:varyColors val="0"/>
50179
+ ${insertDataLabels({ showValues: chart.showValues })}
50116
50180
  ${joinXmlNodes(rightDataSetsNodes)}
50117
50181
  <c:axId val="${secondaryCatAxId}" />
50118
50182
  <c:axId val="${secondaryValAxId}" />
@@ -50151,6 +50215,7 @@
50151
50215
  <c:order val="0"/>
50152
50216
  <c:invertIfNegative val="0" />
50153
50217
  ${extractDataSetLabel(leftDataSet.label)}
50218
+ ${insertDataLabels({ showValues: chart.showValues })}
50154
50219
  ${shapeProperty({
50155
50220
  backgroundColor: firstColor,
50156
50221
  line: { color: firstColor },
@@ -50168,6 +50233,7 @@
50168
50233
  <c:order val="1"/>
50169
50234
  <c:invertIfNegative val="0" />
50170
50235
  ${extractDataSetLabel(rightDataSet.label)}
50236
+ ${insertDataLabels({ showValues: chart.showValues })}
50171
50237
  ${shapeProperty({
50172
50238
  backgroundColor: secondColor,
50173
50239
  line: { color: secondColor },
@@ -50185,6 +50251,7 @@
50185
50251
  <c:grouping val="clustered"/>
50186
50252
  <c:varyColors val="0" />
50187
50253
  ${leftBarDataSetNode}
50254
+ ${insertDataLabels({ showValues: chart.showValues })}
50188
50255
  <c:gapWidth val="50" />
50189
50256
  <c:axId val="${catAxId}" />
50190
50257
  <c:axId val="${valAxId}" />
@@ -50194,6 +50261,7 @@
50194
50261
  <c:grouping val="clustered"/>
50195
50262
  <c:varyColors val="0" />
50196
50263
  ${rightBarDataSetNode}
50264
+ ${insertDataLabels({ showValues: chart.showValues })}
50197
50265
  <c:gapWidth val="50" />
50198
50266
  <c:axId val="${secondaryCatAxId}" />
50199
50267
  <c:axId val="${secondaryValAxId}" />
@@ -50247,6 +50315,7 @@
50247
50315
  </c:marker>
50248
50316
  ${extractTrendline(dataset.trend, color)}
50249
50317
  ${extractDataSetLabel(dataset.label)}
50318
+ ${insertDataLabels({ showValues: chart.showValues })}
50250
50319
  ${dataShapeProperty}
50251
50320
  ${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
50252
50321
  <c:val> <!-- x-coordinate values -->
@@ -50270,6 +50339,7 @@
50270
50339
  <!-- each data marker in the series does not have a different color -->
50271
50340
  <c:varyColors val="0"/>
50272
50341
  ${joinXmlNodes(leftDataSetsNodes)}
50342
+ ${insertDataLabels({ showValues: chart.showValues })}
50273
50343
  <c:axId val="${catAxId}" />
50274
50344
  <c:axId val="${valAxId}" />
50275
50345
  </c:lineChart>
@@ -50284,6 +50354,7 @@
50284
50354
  <!-- each data marker in the series does not have a different color -->
50285
50355
  <c:varyColors val="0"/>
50286
50356
  ${joinXmlNodes(rightDataSetsNodes)}
50357
+ ${insertDataLabels({ showValues: chart.showValues })}
50287
50358
  <c:axId val="${catAxId + 1}" />
50288
50359
  <c:axId val="${valAxId + 1}" />
50289
50360
  </c:lineChart>
@@ -50319,6 +50390,7 @@
50319
50390
  </c:marker>
50320
50391
  ${extractTrendline(dataset.trend, color)}
50321
50392
  ${extractDataSetLabel(dataset.label)}
50393
+ ${insertDataLabels({ showValues: chart.showValues })}
50322
50394
  ${chart.labelRange
50323
50395
  ? escapeXml /*xml*/ `<c:xVal> <!-- x-coordinate values -->
50324
50396
  ${numberRef(chart.labelRange)}
@@ -50344,6 +50416,7 @@
50344
50416
  <c:varyColors val="0"/>
50345
50417
  <c:scatterStyle val="lineMarker"/>
50346
50418
  ${joinXmlNodes(leftDataSetsNodes)}
50419
+ ${insertDataLabels({ showValues: chart.showValues })}
50347
50420
  <c:axId val="${catAxId}" />
50348
50421
  <c:axId val="${valAxId}" />
50349
50422
  </c:scatterChart>
@@ -50358,6 +50431,7 @@
50358
50431
  <c:varyColors val="0"/>
50359
50432
  <c:scatterStyle val="lineMarker"/>
50360
50433
  ${joinXmlNodes(rightDataSetsNodes)}
50434
+ ${insertDataLabels({ showValues: chart.showValues })}
50361
50435
  <c:axId val="${catAxId + 1}" />
50362
50436
  <c:axId val="${valAxId + 1}" />
50363
50437
  </c:scatterChart>
@@ -50390,6 +50464,7 @@
50390
50464
  ${shapeProperty({ backgroundColor: color, line: { color } })}
50391
50465
  </c:marker>
50392
50466
  ${extractDataSetLabel(dataset.label)}
50467
+ ${insertDataLabels({ showValues: chart.showValues })}
50393
50468
  ${dataShapeProperty}
50394
50469
  ${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
50395
50470
  <c:val> <!-- x-coordinate values -->
@@ -50405,6 +50480,7 @@
50405
50480
  <c:radarStyle val="marker"/>
50406
50481
  <c:varyColors val="0"/>
50407
50482
  ${joinXmlNodes(dataSetsNodes)}
50483
+ ${insertDataLabels({ showValues: chart.showValues })}
50408
50484
  <c:axId val="${catAxId}" />
50409
50485
  <c:axId val="${valAxId}" />
50410
50486
  </c:radarChart>
@@ -50440,7 +50516,7 @@
50440
50516
  <c:order val="${dsIndex}"/>
50441
50517
  ${extractDataSetLabel(dataset.label)}
50442
50518
  ${joinXmlNodes(dataPoints)}
50443
- ${insertDataLabels({ showLeaderLines: true })}
50519
+ ${insertDataLabels({ showLeaderLines: true, showValues: chart.showValues })}
50444
50520
  ${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
50445
50521
  <c:val>
50446
50522
  ${numberRef(dataset.range)}
@@ -50452,22 +50528,25 @@
50452
50528
  <c:doughnutChart>
50453
50529
  <c:varyColors val="1" />
50454
50530
  <c:holeSize val="${chart.pieHolePercentage ?? (chart.isDoughnut ? DEFAULT_DOUGHNUT_CHART_HOLE_SIZE : 0)}" />
50455
- ${insertDataLabels()}
50456
50531
  ${joinXmlNodes(dataSetsNodes)}
50532
+ ${insertDataLabels({ showValues: chart.showValues })}
50457
50533
  </c:doughnutChart>
50458
50534
  `;
50459
50535
  }
50460
- function insertDataLabels({ showLeaderLines } = { showLeaderLines: false }) {
50536
+ function insertDataLabels({ showLeaderLines, showValues } = {
50537
+ showLeaderLines: false,
50538
+ showValues: false,
50539
+ }) {
50461
50540
  return escapeXml /*xml*/ `
50462
- <dLbls>
50541
+ <c:dLbls>
50463
50542
  <c:showLegendKey val="0"/>
50464
- <c:showVal val="0"/>
50543
+ <c:showVal val="${showValues ? "1" : "0"}"/>
50465
50544
  <c:showCatName val="0"/>
50466
50545
  <c:showSerName val="0"/>
50467
50546
  <c:showPercent val="0"/>
50468
50547
  <c:showBubbleSize val="0"/>
50469
50548
  <c:showLeaderLines val="${showLeaderLines ? "1" : "0"}"/>
50470
- </dLbls>
50549
+ </c:dLbls>
50471
50550
  `;
50472
50551
  }
50473
50552
  function addAx(position, axisName, axId, crossAxId, title, defaultFontColor, deleteAxis = 0, orientation = "minMax", crossPosition, tickLabelPosition = "nextTo", maxValue, majorUnit, format = "General") {
@@ -51429,6 +51508,12 @@
51429
51508
  if (style.alignment && style.alignment.wrapText) {
51430
51509
  alignAttrs.push(["wrapText", "1"]);
51431
51510
  }
51511
+ if (style.alignment && style.alignment.textRotation) {
51512
+ alignAttrs.push(["textRotation", style.alignment.textRotation]);
51513
+ }
51514
+ if (style.alignment && style.alignment.shrinkToFit) {
51515
+ alignAttrs.push(["shrinkToFit", "1"]);
51516
+ }
51432
51517
  if (alignAttrs.length > 0) {
51433
51518
  attributes.push(["applyAlignment", "1"]); // for Libre Office
51434
51519
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
@@ -52227,7 +52312,7 @@
52227
52312
  this.config = this.setupConfig(config);
52228
52313
  this.session = this.setupSession(workbookData.revisionId);
52229
52314
  this.coreGetters = {};
52230
- this.range = new RangeAdapter(this.coreGetters);
52315
+ this.range = new RangeAdapterPlugin(this.coreGetters);
52231
52316
  this.coreGetters.getRangeString = this.range.getRangeString.bind(this.range);
52232
52317
  this.coreGetters.getRangeFromSheetXC = this.range.getRangeFromSheetXC.bind(this.range);
52233
52318
  this.coreGetters.createAdaptedRanges = this.range.createAdaptedRanges.bind(this.range);
@@ -52241,8 +52326,6 @@
52241
52326
  this.coreGetters.extendRange = this.range.extendRange.bind(this.range);
52242
52327
  this.coreGetters.getRangesUnion = this.range.getRangesUnion.bind(this.range);
52243
52328
  this.coreGetters.removeRangesSheetPrefix = this.range.removeRangesSheetPrefix.bind(this.range);
52244
- this.coreGetters.adaptFormulaStringDependencies =
52245
- this.range.adaptFormulaStringDependencies.bind(this.range);
52246
52329
  this.coreGetters.copyFormulaStringForSheet = this.range.copyFormulaStringForSheet.bind(this.range);
52247
52330
  this.getters = {
52248
52331
  isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
@@ -52823,8 +52906,8 @@
52823
52906
 
52824
52907
 
52825
52908
  __info__.version = "19.1.0-alpha.3";
52826
- __info__.date = "2026-01-14T10:01:30.535Z";
52827
- __info__.hash = "e5cbf18";
52909
+ __info__.date = "2026-01-21T11:07:49.673Z";
52910
+ __info__.hash = "fa080c2";
52828
52911
 
52829
52912
 
52830
52913
  })(this.o_spreadsheet_engine = this.o_spreadsheet_engine || {});