@odoo/o-spreadsheet 19.1.2 → 19.1.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-07T16:20:59.139Z
7
- * @hash febc3e9
6
+ * @date 2026-01-21T11:06:38.842Z
7
+ * @hash ceae12a
8
8
  */
9
9
 
10
10
  (function (exports) {
@@ -2520,7 +2520,11 @@
2520
2520
  if (operator === "<>" || operator === "=") {
2521
2521
  let result;
2522
2522
  if (typeof value === typeof operand) {
2523
- if (typeof value === "string" && typeof operand === "string") {
2523
+ if (value === "" && operand === "") {
2524
+ // fast path to avoid regex evaluation
2525
+ result = true;
2526
+ }
2527
+ else if (typeof value === "string" && typeof operand === "string") {
2524
2528
  result = wildcardToRegExp(operand).test(value);
2525
2529
  }
2526
2530
  else {
@@ -2874,7 +2878,16 @@
2874
2878
  }
2875
2879
  acceptToVectorize.push(!argDefinition.acceptMatrix);
2876
2880
  }
2877
- return applyVectorization(errorHandlingCompute.bind(this), args, acceptToVectorize);
2881
+ return replaceErrorPlaceholderInResult(applyVectorization(errorHandlingCompute.bind(this), args, acceptToVectorize));
2882
+ }
2883
+ function replaceErrorPlaceholderInResult(result) {
2884
+ if (!isMatrix(result)) {
2885
+ replaceFunctionNamePlaceholder(result, descr.name);
2886
+ }
2887
+ else {
2888
+ matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, descr.name));
2889
+ }
2890
+ return result;
2878
2891
  }
2879
2892
  function errorHandlingCompute(...args) {
2880
2893
  for (let i = 0; i < args.length; i++) {
@@ -2903,13 +2916,12 @@
2903
2916
  const result = descr.compute.apply(this, args);
2904
2917
  if (!isMatrix(result)) {
2905
2918
  if (typeof result === "object" && result !== null && "value" in result) {
2906
- replaceFunctionNamePlaceholder(result, descr.name);
2907
2919
  return result;
2908
2920
  }
2921
+ descr.name;
2909
2922
  return { value: result };
2910
2923
  }
2911
2924
  if (typeof result[0][0] === "object" && result[0][0] !== null && "value" in result[0][0]) {
2912
- matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, descr.name));
2913
2925
  return result;
2914
2926
  }
2915
2927
  return matrixMap(result, (row) => ({ value: row }));
@@ -15076,9 +15088,10 @@
15076
15088
  throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
15077
15089
  }
15078
15090
  }
15079
- function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
15091
+ function addPivotDependencies(evalContext, pivotId, forMeasures) {
15080
15092
  //TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
15081
15093
  const dependencies = [];
15094
+ const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
15082
15095
  if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
15083
15096
  const { sheetId, zone } = coreDefinition.dataSet;
15084
15097
  const xc = zoneToXc(zone);
@@ -15095,8 +15108,7 @@
15095
15108
  }
15096
15109
  for (const measure of forMeasures) {
15097
15110
  if (measure.computedBy) {
15098
- const formula = evalContext.getters.getMeasureCompiledFormula(measure);
15099
- dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
15111
+ dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
15100
15112
  }
15101
15113
  }
15102
15114
  const originPosition = evalContext.__originCellPosition;
@@ -15593,7 +15605,7 @@
15593
15605
  assertDomainLength(domainArgs);
15594
15606
  const pivot = this.getters.getPivot(pivotId);
15595
15607
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
15596
- addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
15608
+ addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
15597
15609
  pivot.init({ reload: pivot.needsReevaluation });
15598
15610
  const error = pivot.assertIsValid({ throwOnError: false });
15599
15611
  if (error) {
@@ -15626,8 +15638,7 @@
15626
15638
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
15627
15639
  assertDomainLength(domainArgs);
15628
15640
  const pivot = this.getters.getPivot(_pivotId);
15629
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
15630
- addPivotDependencies(this, coreDefinition, []);
15641
+ addPivotDependencies(this, _pivotId, []);
15631
15642
  pivot.init({ reload: pivot.needsReevaluation });
15632
15643
  const error = pivot.assertIsValid({ throwOnError: false });
15633
15644
  if (error) {
@@ -15679,7 +15690,7 @@
15679
15690
  if (pivotStyle.numberOfColumns < 0) {
15680
15691
  return new EvaluationError(_t("The number of columns must be positive."));
15681
15692
  }
15682
- addPivotDependencies(this, coreDefinition, coreDefinition.measures);
15693
+ addPivotDependencies(this, pivotId, coreDefinition.measures);
15683
15694
  pivot.init({ reload: pivot.needsReevaluation });
15684
15695
  const error = pivot.assertIsValid({ throwOnError: false });
15685
15696
  if (error) {
@@ -18422,7 +18433,7 @@
18422
18433
  const groups = groupConsecutive(elements);
18423
18434
  return (range) => {
18424
18435
  if (range.sheetId !== cmd.sheetId) {
18425
- return { changeType: "NONE" };
18436
+ return { changeType: "NONE", range };
18426
18437
  }
18427
18438
  let newRange = range;
18428
18439
  let changeType = "NONE";
@@ -18449,10 +18460,7 @@
18449
18460
  newRange = createAdaptedRange(newRange, dimension, changeType, -(max - min + 1));
18450
18461
  }
18451
18462
  }
18452
- if (changeType !== "NONE") {
18453
- return { changeType, range: newRange };
18454
- }
18455
- return { changeType: "NONE" };
18463
+ return { changeType, range: newRange };
18456
18464
  };
18457
18465
  }
18458
18466
  function getApplyRangeChangeAddColRow(cmd) {
@@ -18461,7 +18469,7 @@
18461
18469
  const dimension = cmd.dimension === "COL" ? "columns" : "rows";
18462
18470
  return (range) => {
18463
18471
  if (range.sheetId !== cmd.sheetId) {
18464
- return { changeType: "NONE" };
18472
+ return { changeType: "NONE", range };
18465
18473
  }
18466
18474
  if (cmd.position === "after") {
18467
18475
  if (range.zone[start] <= cmd.base && cmd.base < range.zone[end]) {
@@ -18491,13 +18499,13 @@
18491
18499
  };
18492
18500
  }
18493
18501
  }
18494
- return { changeType: "NONE" };
18502
+ return { changeType: "NONE", range };
18495
18503
  };
18496
18504
  }
18497
18505
  function getApplyRangeChangeDeleteSheet(cmd) {
18498
18506
  return (range) => {
18499
18507
  if (range.sheetId !== cmd.sheetId && range.invalidSheetName !== cmd.sheetName) {
18500
- return { changeType: "NONE" };
18508
+ return { changeType: "NONE", range };
18501
18509
  }
18502
18510
  const invalidSheetName = cmd.sheetName;
18503
18511
  range = {
@@ -18524,14 +18532,14 @@
18524
18532
  const newRange = { ...range, sheetId, invalidSheetName };
18525
18533
  return { changeType: "CHANGE", range: newRange };
18526
18534
  }
18527
- return { changeType: "NONE" };
18535
+ return { changeType: "NONE", range };
18528
18536
  };
18529
18537
  }
18530
18538
  function getApplyRangeChangeMoveRange(cmd) {
18531
18539
  const originZone = cmd.target[0];
18532
18540
  return (range) => {
18533
18541
  if (range.sheetId !== cmd.sheetId || !isZoneInside(range.zone, originZone)) {
18534
- return { changeType: "NONE" };
18542
+ return { changeType: "NONE", range };
18535
18543
  }
18536
18544
  const targetSheetId = cmd.targetSheetId;
18537
18545
  const offsetX = cmd.col - originZone.left;
@@ -20063,7 +20071,7 @@
20063
20071
  continue;
20064
20072
  }
20065
20073
  const sheetXC = tokens[tokenIdx].value;
20066
- const newSheetXC = adaptStringRange(defaultSheetId, sheetXC, applyChange);
20074
+ const newSheetXC = adaptStringRange(defaultSheetId, sheetXC, applyChange).range;
20067
20075
  if (sheetXC !== newSheetXC) {
20068
20076
  tokens[tokenIdx] = {
20069
20077
  value: newSheetXC,
@@ -20073,23 +20081,30 @@
20073
20081
  }
20074
20082
  return concat(tokens.map((token) => token.value));
20075
20083
  }
20076
- function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20084
+ function adaptStringRange(defaultSheetId, sheetXC, rangeAdapter) {
20077
20085
  const sheetName = splitReference(sheetXC).sheetName;
20078
20086
  if (sheetName
20079
- ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
20080
- : defaultSheetId !== applyChange.sheetId) {
20081
- return sheetXC;
20087
+ ? !isSheetNameEqual(sheetName, rangeAdapter.sheetName.old)
20088
+ : defaultSheetId !== rangeAdapter.sheetId) {
20089
+ return { changeType: "NONE", range: sheetXC };
20082
20090
  }
20083
- const sheetId = sheetName ? applyChange.sheetId : defaultSheetId;
20091
+ const sheetId = sheetName ? rangeAdapter.sheetId : defaultSheetId;
20084
20092
  const range = getRange(sheetXC, sheetId);
20085
20093
  if (range.invalidXc) {
20086
- return sheetXC;
20094
+ return { changeType: "NONE", range: sheetXC };
20087
20095
  }
20088
- const change = applyChange.applyChange(range);
20096
+ const change = rangeAdapter.applyChange(range);
20089
20097
  if (change.changeType === "NONE" || change.changeType === "REMOVE") {
20090
- return sheetXC;
20098
+ return { changeType: change.changeType, range: sheetXC };
20091
20099
  }
20092
- return getRangeString(change.range, defaultSheetId, getSheetNameGetter(applyChange));
20100
+ const rangeStr = getRangeString(change.range, defaultSheetId, getSheetNameGetter(rangeAdapter));
20101
+ if (rangeStr === CellErrorType.InvalidReference) {
20102
+ return { changeType: "REMOVE", range: rangeStr };
20103
+ }
20104
+ return {
20105
+ changeType: change.changeType,
20106
+ range: rangeStr,
20107
+ };
20093
20108
  }
20094
20109
  function getSheetNameGetter(applyChange) {
20095
20110
  return (sheetId) => {
@@ -20304,7 +20319,7 @@
20304
20319
  cmd.cf.rule = {
20305
20320
  ...rule,
20306
20321
  rangeValues: rule.rangeValues
20307
- ? adaptStringRange(cmd.sheetId, rule.rangeValues, applyChange)
20322
+ ? adaptStringRange(cmd.sheetId, rule.rangeValues, applyChange).range
20308
20323
  : undefined,
20309
20324
  };
20310
20325
  }
@@ -22785,6 +22800,405 @@
22785
22800
  */
22786
22801
  const DEFAULT_SYSTEM_COLOR = "FF000000";
22787
22802
 
22803
+ const globalReverseLookup$1 = new WeakMap();
22804
+ const globalIdCounter = new WeakMap();
22805
+ /**
22806
+ * Get the id of the given item (its key in the given dictionary).
22807
+ * If the given item does not exist in the dictionary, it creates one with a new id.
22808
+ */
22809
+ function getItemId(item, itemsDic) {
22810
+ if (!globalReverseLookup$1.has(itemsDic)) {
22811
+ globalReverseLookup$1.set(itemsDic, new Map());
22812
+ globalIdCounter.set(itemsDic, 0);
22813
+ }
22814
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
22815
+ const canonical = getCanonicalRepresentation(item);
22816
+ if (reverseLookup.has(canonical)) {
22817
+ const id = reverseLookup.get(canonical);
22818
+ itemsDic[id] = item;
22819
+ return id;
22820
+ }
22821
+ // Generate new Id if the item didn't exist in the dictionary
22822
+ const newId = globalIdCounter.get(itemsDic) + 1;
22823
+ reverseLookup.set(canonical, newId);
22824
+ globalIdCounter.set(itemsDic, newId);
22825
+ itemsDic[newId] = item;
22826
+ return newId;
22827
+ }
22828
+ function groupItemIdsByZones(positionsByItemId) {
22829
+ const result = {};
22830
+ for (const itemId in positionsByItemId) {
22831
+ const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
22832
+ for (const zone of zones) {
22833
+ result[zoneToXc(zone)] = Number(itemId);
22834
+ }
22835
+ }
22836
+ return result;
22837
+ }
22838
+ function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
22839
+ for (const zoneXc in itemIdsByZones) {
22840
+ const zone = toZone(zoneXc);
22841
+ const itemId = itemIdsByZones[zoneXc];
22842
+ for (let row = zone.top; row <= zone.bottom; row++) {
22843
+ for (let col = zone.left; col <= zone.right; col++) {
22844
+ const position = { sheetId, col, row };
22845
+ yield [position, itemId];
22846
+ }
22847
+ }
22848
+ }
22849
+ }
22850
+ function getCanonicalRepresentation(item) {
22851
+ if (item === null)
22852
+ return "null";
22853
+ if (item === undefined)
22854
+ return "undefined";
22855
+ if (typeof item !== "object")
22856
+ return String(item);
22857
+ if (Array.isArray(item)) {
22858
+ const len = item.length;
22859
+ let result = "[";
22860
+ for (let i = 0; i < len; i++) {
22861
+ if (i > 0)
22862
+ result += ",";
22863
+ result += getCanonicalRepresentation(item[i]);
22864
+ }
22865
+ return result + "]";
22866
+ }
22867
+ const keys = Object.keys(item).sort();
22868
+ let repr = "{";
22869
+ for (const key of keys) {
22870
+ if (item[key] !== undefined) {
22871
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
22872
+ }
22873
+ }
22874
+ repr += "}";
22875
+ return repr;
22876
+ }
22877
+
22878
+ // -------------------------------------
22879
+ // CF HELPERS
22880
+ // -------------------------------------
22881
+ /**
22882
+ * Convert the conditional formatting o-spreadsheet operator to
22883
+ * the corresponding excel operator.
22884
+ * */
22885
+ function convertOperator(operator) {
22886
+ switch (operator) {
22887
+ case "isNotEmpty":
22888
+ return "notContainsBlanks";
22889
+ case "isEmpty":
22890
+ return "containsBlanks";
22891
+ case "notContainsText":
22892
+ return "notContainsBlanks";
22893
+ case "containsText":
22894
+ return "containsText";
22895
+ case "beginsWithText":
22896
+ return "beginsWith";
22897
+ case "endsWithText":
22898
+ return "endsWith";
22899
+ case "isGreaterThan":
22900
+ return "greaterThan";
22901
+ case "isGreaterOrEqualTo":
22902
+ return "greaterThanOrEqual";
22903
+ case "isLessThan":
22904
+ return "lessThan";
22905
+ case "isLessOrEqualTo":
22906
+ return "lessThanOrEqual";
22907
+ case "isBetween":
22908
+ return "between";
22909
+ case "isNotBetween":
22910
+ return "notBetween";
22911
+ case "isEqual":
22912
+ return "equal";
22913
+ case "isNotEqual":
22914
+ return "notEqual";
22915
+ case "customFormula":
22916
+ return "";
22917
+ case "dateIs":
22918
+ return "";
22919
+ case "dateIsBefore":
22920
+ return "lessThan";
22921
+ case "dateIsAfter":
22922
+ return "greaterThan";
22923
+ case "dateIsOnOrAfter":
22924
+ return "greaterThanOrEqual";
22925
+ case "dateIsOnOrBefore":
22926
+ return "lessThanOrEqual";
22927
+ }
22928
+ }
22929
+ // -------------------------------------
22930
+ // WORKSHEET HELPERS
22931
+ // -------------------------------------
22932
+ function getCellType(value) {
22933
+ switch (typeof value) {
22934
+ case "boolean":
22935
+ return "b";
22936
+ case "string":
22937
+ return "str";
22938
+ case "number":
22939
+ return "n";
22940
+ default:
22941
+ return undefined;
22942
+ }
22943
+ }
22944
+ function convertHeightToExcel(height) {
22945
+ return Math.round(HEIGHT_FACTOR * height * 100) / 100;
22946
+ }
22947
+ function convertWidthToExcel(width) {
22948
+ return Math.round(WIDTH_FACTOR * width * 100) / 100;
22949
+ }
22950
+ function convertHeightFromExcel(height) {
22951
+ if (!height)
22952
+ return height;
22953
+ return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
22954
+ }
22955
+ function convertWidthFromExcel(width) {
22956
+ if (!width)
22957
+ return width;
22958
+ return Math.round((width / WIDTH_FACTOR) * 100) / 100;
22959
+ }
22960
+ function extractStyle(data, content, styleId, formatId, borderId) {
22961
+ const style = styleId ? data.styles[styleId] : {};
22962
+ const format = formatId ? data.formats[formatId] : undefined;
22963
+ const styles = {
22964
+ font: {
22965
+ size: style?.fontSize || DEFAULT_FONT_SIZE,
22966
+ color: { rgb: style?.textColor ? style.textColor : "000000" },
22967
+ family: 2,
22968
+ name: "Arial",
22969
+ },
22970
+ fill: style?.fillColor
22971
+ ? {
22972
+ fgColor: { rgb: style.fillColor },
22973
+ }
22974
+ : { reservedAttribute: "none" },
22975
+ numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
22976
+ border: borderId || 0,
22977
+ alignment: {
22978
+ horizontal: style.align,
22979
+ vertical: style.verticalAlign
22980
+ ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
22981
+ : undefined,
22982
+ wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
22983
+ textRotation: style.rotation ? rotationToXLSX(style.rotation) : undefined,
22984
+ shrinkToFit: style.wrapping === "clip" ? true : undefined,
22985
+ },
22986
+ };
22987
+ styles.font["strike"] = !!style?.strikethrough || undefined;
22988
+ styles.font["underline"] = !!style?.underline || undefined;
22989
+ styles.font["bold"] = !!style?.bold || undefined;
22990
+ styles.font["italic"] = !!style?.italic || undefined;
22991
+ return styles;
22992
+ }
22993
+ function rotationToXLSX(rad) {
22994
+ let deg = Math.round((-rad / Math.PI) * 180) % 180;
22995
+ if (deg > 90) {
22996
+ deg -= 180;
22997
+ }
22998
+ else if (deg < -90) {
22999
+ deg += 180;
23000
+ }
23001
+ if (deg >= 0) {
23002
+ return deg;
23003
+ }
23004
+ else {
23005
+ return 90 - deg;
23006
+ }
23007
+ }
23008
+ function rotationFromXLSX(deg) {
23009
+ if (deg <= 90) {
23010
+ return -(deg / 180) * Math.PI;
23011
+ }
23012
+ else {
23013
+ return (-(90 - deg) / 180) * Math.PI;
23014
+ }
23015
+ }
23016
+ function normalizeStyle(construct, styles) {
23017
+ // Normalize this
23018
+ const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
23019
+ const style = {
23020
+ fontId: pushElement(styles.font, construct.fonts),
23021
+ fillId: pushElement(styles.fill, construct.fills),
23022
+ borderId: styles.border,
23023
+ numFmtId,
23024
+ alignment: {
23025
+ vertical: styles.alignment.vertical,
23026
+ horizontal: styles.alignment.horizontal,
23027
+ wrapText: styles.alignment.wrapText,
23028
+ textRotation: styles.alignment.textRotation,
23029
+ shrinkToFit: styles.alignment.shrinkToFit,
23030
+ },
23031
+ };
23032
+ return pushElement(style, construct.styles);
23033
+ }
23034
+ function convertFormat(format, numFmtStructure) {
23035
+ if (!format) {
23036
+ return 0;
23037
+ }
23038
+ let formatId = XLSX_FORMAT_MAP[format.format];
23039
+ if (!formatId) {
23040
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23041
+ }
23042
+ return formatId;
23043
+ }
23044
+ /**
23045
+ * Add a relation to the given file and return its id.
23046
+ */
23047
+ function addRelsToFile(relsFiles, path, rel) {
23048
+ const relsFile = relsFiles.find((file) => file.path === path);
23049
+ // the id is a one-based int casted as string
23050
+ let id;
23051
+ if (!relsFile) {
23052
+ id = "rId1";
23053
+ relsFiles.push({ path, rels: [{ ...rel, id }] });
23054
+ }
23055
+ else {
23056
+ id = `rId${(relsFile.rels.length + 1).toString()}`;
23057
+ relsFile.rels.push({
23058
+ ...rel,
23059
+ id,
23060
+ });
23061
+ }
23062
+ return id;
23063
+ }
23064
+ const globalReverseLookup = new WeakMap();
23065
+ function pushElement(property, propertyList) {
23066
+ let reverseLookup = globalReverseLookup.get(propertyList);
23067
+ if (!reverseLookup) {
23068
+ reverseLookup = new Map();
23069
+ for (let i = 0; i < propertyList.length; i++) {
23070
+ const canonical = getCanonicalRepresentation(propertyList[i]);
23071
+ reverseLookup.set(canonical, i);
23072
+ }
23073
+ globalReverseLookup.set(propertyList, reverseLookup);
23074
+ }
23075
+ const canonical = getCanonicalRepresentation(property);
23076
+ if (reverseLookup.has(canonical)) {
23077
+ return reverseLookup.get(canonical);
23078
+ }
23079
+ const maxId = propertyList.length;
23080
+ propertyList.push(property);
23081
+ reverseLookup.set(canonical, maxId);
23082
+ return maxId;
23083
+ }
23084
+ /**
23085
+ * Convert a chart o-spreadsheet id to a xlsx id which
23086
+ * are unsigned integers (starting from 1).
23087
+ */
23088
+ function convertChartId(chartId, construct) {
23089
+ const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23090
+ if (xlsxId === -1) {
23091
+ construct.chartIds.push(chartId);
23092
+ return construct.chartIds.length;
23093
+ }
23094
+ return xlsxId + 1;
23095
+ }
23096
+ const imageIds = [];
23097
+ /**
23098
+ * Convert a image o-spreadsheet id to a xlsx id which
23099
+ * are unsigned integers (starting from 1).
23100
+ */
23101
+ function convertImageId(imageId) {
23102
+ const xlsxId = imageIds.findIndex((id) => id === imageId);
23103
+ if (xlsxId === -1) {
23104
+ imageIds.push(imageId);
23105
+ return imageIds.length;
23106
+ }
23107
+ return xlsxId + 1;
23108
+ }
23109
+ /**
23110
+ * Convert a value expressed in dot to EMU.
23111
+ * EMU = English Metrical Unit
23112
+ * There are 914400 EMU per inch.
23113
+ *
23114
+ * /!\ A value expressed in EMU cannot be fractional.
23115
+ * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23116
+ */
23117
+ function convertDotValueToEMU(value) {
23118
+ const DPI = 96;
23119
+ return Math.round((value * 914400) / DPI);
23120
+ }
23121
+ function getRangeSize(reference, defaultSheetIndex, data) {
23122
+ let xc = reference;
23123
+ let sheetName = undefined;
23124
+ ({ xc, sheetName } = splitReference(reference));
23125
+ let rangeSheetIndex;
23126
+ if (sheetName) {
23127
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23128
+ if (index < 0) {
23129
+ throw new Error("Unable to find a sheet with the name " + sheetName);
23130
+ }
23131
+ rangeSheetIndex = index;
23132
+ }
23133
+ else {
23134
+ rangeSheetIndex = Number(defaultSheetIndex);
23135
+ }
23136
+ const zone = toUnboundedZone(xc);
23137
+ if (zone.right === undefined) {
23138
+ zone.right = data.sheets[rangeSheetIndex].colNumber;
23139
+ }
23140
+ if (zone.bottom === undefined) {
23141
+ zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23142
+ }
23143
+ return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23144
+ }
23145
+ function convertEMUToDotValue(value) {
23146
+ const DPI = 96;
23147
+ return Math.round((value * DPI) / 914400);
23148
+ }
23149
+ /**
23150
+ * Get the position of the start of a column in Excel (in px).
23151
+ */
23152
+ function getColPosition(colIndex, sheetData) {
23153
+ let position = 0;
23154
+ for (let i = 0; i < colIndex; i++) {
23155
+ const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23156
+ if (colAtIndex?.width) {
23157
+ position += colAtIndex.width;
23158
+ }
23159
+ else if (sheetData.sheetFormat?.defaultColWidth) {
23160
+ position += sheetData.sheetFormat.defaultColWidth;
23161
+ }
23162
+ else {
23163
+ position += EXCEL_DEFAULT_COL_WIDTH;
23164
+ }
23165
+ }
23166
+ return position / WIDTH_FACTOR;
23167
+ }
23168
+ /**
23169
+ * Get the position of the start of a row in Excel (in px).
23170
+ */
23171
+ function getRowPosition(rowIndex, sheetData) {
23172
+ let position = 0;
23173
+ for (let i = 0; i < rowIndex; i++) {
23174
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23175
+ if (rowAtIndex?.height) {
23176
+ position += rowAtIndex.height;
23177
+ }
23178
+ else if (sheetData.sheetFormat?.defaultRowHeight) {
23179
+ position += sheetData.sheetFormat.defaultRowHeight;
23180
+ }
23181
+ else {
23182
+ position += EXCEL_DEFAULT_ROW_HEIGHT;
23183
+ }
23184
+ }
23185
+ return position / HEIGHT_FACTOR;
23186
+ }
23187
+ /**
23188
+ * Convert the o-spreadsheet data validation decimal
23189
+ * criterion type to the corresponding excel operator.
23190
+ */
23191
+ function convertDecimalCriterionTypeToExcelOperator(operator) {
23192
+ return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23193
+ }
23194
+ /**
23195
+ * Convert the o-spreadsheet data validation date
23196
+ * criterion type to the corresponding excel operator.
23197
+ */
23198
+ function convertDateCriterionTypeToExcelOperator(operator) {
23199
+ return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23200
+ }
23201
+
22788
23202
  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;
22789
23203
  /**
22790
23204
  * Convert excel format to o_spreadsheet format
@@ -22884,6 +23298,9 @@
22884
23298
  align: styleStruct.alignment?.horizontal
22885
23299
  ? H_ALIGNMENT_CONVERSION_MAP[styleStruct.alignment.horizontal]
22886
23300
  : undefined,
23301
+ rotation: styleStruct.alignment?.textRotation
23302
+ ? rotationFromXLSX(styleStruct.alignment.textRotation)
23303
+ : undefined,
22887
23304
  // 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
22888
23305
  fillColor: styleStruct.fillStyle?.patternType === "solid"
22889
23306
  ? convertColor(styleStruct.fillStyle?.fgColor)
@@ -23183,378 +23600,6 @@
23183
23600
  }
23184
23601
  }
23185
23602
 
23186
- const globalReverseLookup$1 = new WeakMap();
23187
- const globalIdCounter = new WeakMap();
23188
- /**
23189
- * Get the id of the given item (its key in the given dictionary).
23190
- * If the given item does not exist in the dictionary, it creates one with a new id.
23191
- */
23192
- function getItemId(item, itemsDic) {
23193
- if (!globalReverseLookup$1.has(itemsDic)) {
23194
- globalReverseLookup$1.set(itemsDic, new Map());
23195
- globalIdCounter.set(itemsDic, 0);
23196
- }
23197
- const reverseLookup = globalReverseLookup$1.get(itemsDic);
23198
- const canonical = getCanonicalRepresentation(item);
23199
- if (reverseLookup.has(canonical)) {
23200
- const id = reverseLookup.get(canonical);
23201
- itemsDic[id] = item;
23202
- return id;
23203
- }
23204
- // Generate new Id if the item didn't exist in the dictionary
23205
- const newId = globalIdCounter.get(itemsDic) + 1;
23206
- reverseLookup.set(canonical, newId);
23207
- globalIdCounter.set(itemsDic, newId);
23208
- itemsDic[newId] = item;
23209
- return newId;
23210
- }
23211
- function groupItemIdsByZones(positionsByItemId) {
23212
- const result = {};
23213
- for (const itemId in positionsByItemId) {
23214
- const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
23215
- for (const zone of zones) {
23216
- result[zoneToXc(zone)] = Number(itemId);
23217
- }
23218
- }
23219
- return result;
23220
- }
23221
- function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
23222
- for (const zoneXc in itemIdsByZones) {
23223
- const zone = toZone(zoneXc);
23224
- const itemId = itemIdsByZones[zoneXc];
23225
- for (let row = zone.top; row <= zone.bottom; row++) {
23226
- for (let col = zone.left; col <= zone.right; col++) {
23227
- const position = { sheetId, col, row };
23228
- yield [position, itemId];
23229
- }
23230
- }
23231
- }
23232
- }
23233
- function getCanonicalRepresentation(item) {
23234
- if (item === null)
23235
- return "null";
23236
- if (item === undefined)
23237
- return "undefined";
23238
- if (typeof item !== "object")
23239
- return String(item);
23240
- if (Array.isArray(item)) {
23241
- const len = item.length;
23242
- let result = "[";
23243
- for (let i = 0; i < len; i++) {
23244
- if (i > 0)
23245
- result += ",";
23246
- result += getCanonicalRepresentation(item[i]);
23247
- }
23248
- return result + "]";
23249
- }
23250
- const keys = Object.keys(item).sort();
23251
- let repr = "{";
23252
- for (const key of keys) {
23253
- if (item[key] !== undefined) {
23254
- repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
23255
- }
23256
- }
23257
- repr += "}";
23258
- return repr;
23259
- }
23260
-
23261
- // -------------------------------------
23262
- // CF HELPERS
23263
- // -------------------------------------
23264
- /**
23265
- * Convert the conditional formatting o-spreadsheet operator to
23266
- * the corresponding excel operator.
23267
- * */
23268
- function convertOperator(operator) {
23269
- switch (operator) {
23270
- case "isNotEmpty":
23271
- return "notContainsBlanks";
23272
- case "isEmpty":
23273
- return "containsBlanks";
23274
- case "notContainsText":
23275
- return "notContainsBlanks";
23276
- case "containsText":
23277
- return "containsText";
23278
- case "beginsWithText":
23279
- return "beginsWith";
23280
- case "endsWithText":
23281
- return "endsWith";
23282
- case "isGreaterThan":
23283
- return "greaterThan";
23284
- case "isGreaterOrEqualTo":
23285
- return "greaterThanOrEqual";
23286
- case "isLessThan":
23287
- return "lessThan";
23288
- case "isLessOrEqualTo":
23289
- return "lessThanOrEqual";
23290
- case "isBetween":
23291
- return "between";
23292
- case "isNotBetween":
23293
- return "notBetween";
23294
- case "isEqual":
23295
- return "equal";
23296
- case "isNotEqual":
23297
- return "notEqual";
23298
- case "customFormula":
23299
- return "";
23300
- case "dateIs":
23301
- return "";
23302
- case "dateIsBefore":
23303
- return "lessThan";
23304
- case "dateIsAfter":
23305
- return "greaterThan";
23306
- case "dateIsOnOrAfter":
23307
- return "greaterThanOrEqual";
23308
- case "dateIsOnOrBefore":
23309
- return "lessThanOrEqual";
23310
- }
23311
- }
23312
- // -------------------------------------
23313
- // WORKSHEET HELPERS
23314
- // -------------------------------------
23315
- function getCellType(value) {
23316
- switch (typeof value) {
23317
- case "boolean":
23318
- return "b";
23319
- case "string":
23320
- return "str";
23321
- case "number":
23322
- return "n";
23323
- default:
23324
- return undefined;
23325
- }
23326
- }
23327
- function convertHeightToExcel(height) {
23328
- return Math.round(HEIGHT_FACTOR * height * 100) / 100;
23329
- }
23330
- function convertWidthToExcel(width) {
23331
- return Math.round(WIDTH_FACTOR * width * 100) / 100;
23332
- }
23333
- function convertHeightFromExcel(height) {
23334
- if (!height)
23335
- return height;
23336
- return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
23337
- }
23338
- function convertWidthFromExcel(width) {
23339
- if (!width)
23340
- return width;
23341
- return Math.round((width / WIDTH_FACTOR) * 100) / 100;
23342
- }
23343
- function extractStyle(data, content, styleId, formatId, borderId) {
23344
- const style = styleId ? data.styles[styleId] : {};
23345
- const format = formatId ? data.formats[formatId] : undefined;
23346
- const styles = {
23347
- font: {
23348
- size: style?.fontSize || DEFAULT_FONT_SIZE,
23349
- color: { rgb: style?.textColor ? style.textColor : "000000" },
23350
- family: 2,
23351
- name: "Arial",
23352
- },
23353
- fill: style?.fillColor
23354
- ? {
23355
- fgColor: { rgb: style.fillColor },
23356
- }
23357
- : { reservedAttribute: "none" },
23358
- numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
23359
- border: borderId || 0,
23360
- alignment: {
23361
- horizontal: style.align,
23362
- vertical: style.verticalAlign
23363
- ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
23364
- : undefined,
23365
- wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
23366
- },
23367
- };
23368
- styles.font["strike"] = !!style?.strikethrough || undefined;
23369
- styles.font["underline"] = !!style?.underline || undefined;
23370
- styles.font["bold"] = !!style?.bold || undefined;
23371
- styles.font["italic"] = !!style?.italic || undefined;
23372
- return styles;
23373
- }
23374
- function normalizeStyle(construct, styles) {
23375
- // Normalize this
23376
- const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
23377
- const style = {
23378
- fontId: pushElement(styles.font, construct.fonts),
23379
- fillId: pushElement(styles.fill, construct.fills),
23380
- borderId: styles.border,
23381
- numFmtId,
23382
- alignment: {
23383
- vertical: styles.alignment.vertical,
23384
- horizontal: styles.alignment.horizontal,
23385
- wrapText: styles.alignment.wrapText,
23386
- },
23387
- };
23388
- return pushElement(style, construct.styles);
23389
- }
23390
- function convertFormat(format, numFmtStructure) {
23391
- if (!format) {
23392
- return 0;
23393
- }
23394
- let formatId = XLSX_FORMAT_MAP[format.format];
23395
- if (!formatId) {
23396
- formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23397
- }
23398
- return formatId;
23399
- }
23400
- /**
23401
- * Add a relation to the given file and return its id.
23402
- */
23403
- function addRelsToFile(relsFiles, path, rel) {
23404
- const relsFile = relsFiles.find((file) => file.path === path);
23405
- // the id is a one-based int casted as string
23406
- let id;
23407
- if (!relsFile) {
23408
- id = "rId1";
23409
- relsFiles.push({ path, rels: [{ ...rel, id }] });
23410
- }
23411
- else {
23412
- id = `rId${(relsFile.rels.length + 1).toString()}`;
23413
- relsFile.rels.push({
23414
- ...rel,
23415
- id,
23416
- });
23417
- }
23418
- return id;
23419
- }
23420
- const globalReverseLookup = new WeakMap();
23421
- function pushElement(property, propertyList) {
23422
- let reverseLookup = globalReverseLookup.get(propertyList);
23423
- if (!reverseLookup) {
23424
- reverseLookup = new Map();
23425
- for (let i = 0; i < propertyList.length; i++) {
23426
- const canonical = getCanonicalRepresentation(propertyList[i]);
23427
- reverseLookup.set(canonical, i);
23428
- }
23429
- globalReverseLookup.set(propertyList, reverseLookup);
23430
- }
23431
- const canonical = getCanonicalRepresentation(property);
23432
- if (reverseLookup.has(canonical)) {
23433
- return reverseLookup.get(canonical);
23434
- }
23435
- const maxId = propertyList.length;
23436
- propertyList.push(property);
23437
- reverseLookup.set(canonical, maxId);
23438
- return maxId;
23439
- }
23440
- /**
23441
- * Convert a chart o-spreadsheet id to a xlsx id which
23442
- * are unsigned integers (starting from 1).
23443
- */
23444
- function convertChartId(chartId, construct) {
23445
- const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23446
- if (xlsxId === -1) {
23447
- construct.chartIds.push(chartId);
23448
- return construct.chartIds.length;
23449
- }
23450
- return xlsxId + 1;
23451
- }
23452
- const imageIds = [];
23453
- /**
23454
- * Convert a image o-spreadsheet id to a xlsx id which
23455
- * are unsigned integers (starting from 1).
23456
- */
23457
- function convertImageId(imageId) {
23458
- const xlsxId = imageIds.findIndex((id) => id === imageId);
23459
- if (xlsxId === -1) {
23460
- imageIds.push(imageId);
23461
- return imageIds.length;
23462
- }
23463
- return xlsxId + 1;
23464
- }
23465
- /**
23466
- * Convert a value expressed in dot to EMU.
23467
- * EMU = English Metrical Unit
23468
- * There are 914400 EMU per inch.
23469
- *
23470
- * /!\ A value expressed in EMU cannot be fractional.
23471
- * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23472
- */
23473
- function convertDotValueToEMU(value) {
23474
- const DPI = 96;
23475
- return Math.round((value * 914400) / DPI);
23476
- }
23477
- function getRangeSize(reference, defaultSheetIndex, data) {
23478
- let xc = reference;
23479
- let sheetName = undefined;
23480
- ({ xc, sheetName } = splitReference(reference));
23481
- let rangeSheetIndex;
23482
- if (sheetName) {
23483
- const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23484
- if (index < 0) {
23485
- throw new Error("Unable to find a sheet with the name " + sheetName);
23486
- }
23487
- rangeSheetIndex = index;
23488
- }
23489
- else {
23490
- rangeSheetIndex = Number(defaultSheetIndex);
23491
- }
23492
- const zone = toUnboundedZone(xc);
23493
- if (zone.right === undefined) {
23494
- zone.right = data.sheets[rangeSheetIndex].colNumber;
23495
- }
23496
- if (zone.bottom === undefined) {
23497
- zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23498
- }
23499
- return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23500
- }
23501
- function convertEMUToDotValue(value) {
23502
- const DPI = 96;
23503
- return Math.round((value * DPI) / 914400);
23504
- }
23505
- /**
23506
- * Get the position of the start of a column in Excel (in px).
23507
- */
23508
- function getColPosition(colIndex, sheetData) {
23509
- let position = 0;
23510
- for (let i = 0; i < colIndex; i++) {
23511
- const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23512
- if (colAtIndex?.width) {
23513
- position += colAtIndex.width;
23514
- }
23515
- else if (sheetData.sheetFormat?.defaultColWidth) {
23516
- position += sheetData.sheetFormat.defaultColWidth;
23517
- }
23518
- else {
23519
- position += EXCEL_DEFAULT_COL_WIDTH;
23520
- }
23521
- }
23522
- return position / WIDTH_FACTOR;
23523
- }
23524
- /**
23525
- * Get the position of the start of a row in Excel (in px).
23526
- */
23527
- function getRowPosition(rowIndex, sheetData) {
23528
- let position = 0;
23529
- for (let i = 0; i < rowIndex; i++) {
23530
- const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23531
- if (rowAtIndex?.height) {
23532
- position += rowAtIndex.height;
23533
- }
23534
- else if (sheetData.sheetFormat?.defaultRowHeight) {
23535
- position += sheetData.sheetFormat.defaultRowHeight;
23536
- }
23537
- else {
23538
- position += EXCEL_DEFAULT_ROW_HEIGHT;
23539
- }
23540
- }
23541
- return position / HEIGHT_FACTOR;
23542
- }
23543
- /**
23544
- * Convert the o-spreadsheet data validation decimal
23545
- * criterion type to the corresponding excel operator.
23546
- */
23547
- function convertDecimalCriterionTypeToExcelOperator(operator) {
23548
- return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23549
- }
23550
- /**
23551
- * Convert the o-spreadsheet data validation date
23552
- * criterion type to the corresponding excel operator.
23553
- */
23554
- function convertDateCriterionTypeToExcelOperator(operator) {
23555
- return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23556
- }
23557
-
23558
23603
  function convertFigures(sheetData) {
23559
23604
  let id = 1;
23560
23605
  return sheetData.figures
@@ -27546,7 +27591,7 @@
27546
27591
  * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
27547
27592
  * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
27548
27593
  */
27549
- adaptRanges(applyChange, sheetId, sheetName) { }
27594
+ adaptRanges(rangeAdapterFunctions, sheetId, sheetName) { }
27550
27595
  }
27551
27596
 
27552
27597
  class BordersPlugin extends CorePlugin {
@@ -27620,7 +27665,7 @@
27620
27665
  }
27621
27666
  }
27622
27667
  }
27623
- adaptRanges(applyChange, sheetId) {
27668
+ adaptRanges({ applyChange }, sheetId) {
27624
27669
  const newBorders = [];
27625
27670
  for (const border of this.borders[sheetId] ?? []) {
27626
27671
  const change = applyChange(this.getters.getRangeFromZone(sheetId, border.zone));
@@ -28101,7 +28146,7 @@
28101
28146
  ];
28102
28147
  nextId = 1;
28103
28148
  cells = {};
28104
- adaptRanges(applyChange, sheetId, sheetName) {
28149
+ adaptRanges({ applyChange }, sheetId, sheetName) {
28105
28150
  for (const sheet of Object.keys(this.cells)) {
28106
28151
  for (const cell of Object.values(this.cells[sheet] || {})) {
28107
28152
  if (cell.isFormula) {
@@ -28662,12 +28707,12 @@
28662
28707
  charts = {};
28663
28708
  createChart = chartFactory(this.getters);
28664
28709
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
28665
- adaptRanges(applyChange, sheetId, adaptSheetName) {
28710
+ adaptRanges(rangeAdapters) {
28666
28711
  for (const [chartId, chart] of Object.entries(this.charts)) {
28667
28712
  if (!chart) {
28668
28713
  continue;
28669
28714
  }
28670
- const newChart = chart.chart.updateRanges(applyChange, sheetId, adaptSheetName);
28715
+ const newChart = chart.chart.updateRanges(rangeAdapters);
28671
28716
  this.history.update("charts", chartId, newChart ? { figureId: chart.figureId, chart: newChart } : undefined);
28672
28717
  }
28673
28718
  }
@@ -29488,7 +29533,7 @@
29488
29533
  "getAdaptedCfRanges",
29489
29534
  ];
29490
29535
  cfRules = {};
29491
- adaptCFFormulas(applyChange) {
29536
+ adaptCFFormulas({ applyChange, adaptFormulaString }) {
29492
29537
  for (const sheetId in this.cfRules) {
29493
29538
  for (const rule of this.cfRules[sheetId]) {
29494
29539
  if (rule.rule.type === "DataBarRule" && rule.rule.rangeValues) {
@@ -29512,7 +29557,7 @@
29512
29557
  for (let i = 0; i < rule.rule.values.length; i++) {
29513
29558
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29514
29559
  //@ts-expect-error
29515
- "values", i, this.getters.adaptFormulaStringDependencies(sheetId, rule.rule.values[i], applyChange));
29560
+ "values", i, adaptFormulaString(sheetId, rule.rule.values[i]));
29516
29561
  }
29517
29562
  }
29518
29563
  else if (rule.rule.type === "IconSetRule") {
@@ -29520,7 +29565,7 @@
29520
29565
  if (rule.rule[inflectionPoint].type === "formula") {
29521
29566
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29522
29567
  //@ts-expect-error
29523
- inflectionPoint, "value", this.getters.adaptFormulaStringDependencies(sheetId, rule.rule[inflectionPoint].value, applyChange));
29568
+ inflectionPoint, "value", adaptFormulaString(sheetId, rule.rule[inflectionPoint].value));
29524
29569
  }
29525
29570
  }
29526
29571
  }
@@ -29530,14 +29575,14 @@
29530
29575
  if (ruleValue?.type === "formula" && ruleValue?.value) {
29531
29576
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29532
29577
  //@ts-expect-error
29533
- value, "value", this.getters.adaptFormulaStringDependencies(sheetId, ruleValue.value, applyChange));
29578
+ value, "value", adaptFormulaString(sheetId, ruleValue.value));
29534
29579
  }
29535
29580
  }
29536
29581
  }
29537
29582
  }
29538
29583
  }
29539
29584
  }
29540
- adaptCFRanges(sheetId, applyChange) {
29585
+ adaptCFRanges(sheetId, { applyChange }) {
29541
29586
  for (const rule of this.cfRules[sheetId]) {
29542
29587
  for (const range of rule.ranges) {
29543
29588
  const change = applyChange(range);
@@ -29561,12 +29606,12 @@
29561
29606
  }
29562
29607
  }
29563
29608
  }
29564
- adaptRanges(applyChange, sheetId) {
29609
+ adaptRanges(rangeAdapters, sheetId) {
29565
29610
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
29566
29611
  for (const sheetId of sheetIds) {
29567
- this.adaptCFRanges(sheetId, applyChange);
29612
+ this.adaptCFRanges(sheetId, rangeAdapters);
29568
29613
  }
29569
- this.adaptCFFormulas(applyChange);
29614
+ this.adaptCFFormulas(rangeAdapters);
29570
29615
  }
29571
29616
  // ---------------------------------------------------------------------------
29572
29617
  // Command Handling
@@ -29943,23 +29988,23 @@
29943
29988
  "getValidationRuleForCell",
29944
29989
  ];
29945
29990
  rules = {};
29946
- adaptRanges(applyChange, sheetId) {
29947
- this.adaptDVRanges(sheetId, applyChange);
29948
- this.adaptDVFormulas(applyChange);
29991
+ adaptRanges(rangeAdapters, sheetId) {
29992
+ this.adaptDVRanges(sheetId, rangeAdapters);
29993
+ this.adaptDVFormulas(rangeAdapters);
29949
29994
  }
29950
- adaptDVFormulas(applyChange) {
29995
+ adaptDVFormulas({ adaptFormulaString }) {
29951
29996
  for (const sheetId in this.rules) {
29952
29997
  const rules = this.rules[sheetId];
29953
29998
  for (let ruleIndex = rules.length - 1; ruleIndex >= 0; ruleIndex--) {
29954
29999
  const rule = this.rules[sheetId][ruleIndex];
29955
30000
  for (let valueIndex = 0; valueIndex < rule.criterion.values.length; valueIndex++) {
29956
- const value = this.getters.adaptFormulaStringDependencies(sheetId, rule.criterion.values[valueIndex], applyChange);
30001
+ const value = adaptFormulaString(sheetId, rule.criterion.values[valueIndex]);
29957
30002
  this.history.update("rules", sheetId, ruleIndex, "criterion", "values", valueIndex, value);
29958
30003
  }
29959
30004
  }
29960
30005
  }
29961
30006
  }
29962
- adaptDVRanges(sheetId, applyChange) {
30007
+ adaptDVRanges(sheetId, { applyChange }) {
29963
30008
  const rules = this.rules[sheetId];
29964
30009
  for (let ruleIndex = rules.length - 1; ruleIndex >= 0; ruleIndex--) {
29965
30010
  const rule = this.rules[sheetId][ruleIndex];
@@ -30233,7 +30278,7 @@
30233
30278
  // ---------------------------------------------------------------------------
30234
30279
  // Command Handling
30235
30280
  // ---------------------------------------------------------------------------
30236
- adaptRanges(applyChange, sheetId) {
30281
+ adaptRanges({ applyChange }, sheetId) {
30237
30282
  for (const figure of this.getFigures(sheetId)) {
30238
30283
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
30239
30284
  left: figure.col,
@@ -31473,8 +31518,8 @@
31473
31518
  break;
31474
31519
  }
31475
31520
  }
31476
- adaptRanges(applyChange, sheetId) {
31477
- this.applyRangeChangeOnSheet(sheetId, applyChange);
31521
+ adaptRanges(rangeAdapters, sheetId) {
31522
+ this.applyRangeChangeOnSheet(sheetId, rangeAdapters);
31478
31523
  }
31479
31524
  // ---------------------------------------------------------------------------
31480
31525
  // Getters
@@ -31774,7 +31819,7 @@
31774
31819
  /**
31775
31820
  * Apply a range change on merges of a particular sheet.
31776
31821
  */
31777
- applyRangeChangeOnSheet(sheetId, applyChange) {
31822
+ applyRangeChangeOnSheet(sheetId, { applyChange }) {
31778
31823
  const merges = Object.entries(this.merges[sheetId] || {});
31779
31824
  for (const [mergeId, range] of merges) {
31780
31825
  if (range) {
@@ -33393,8 +33438,6 @@
33393
33438
  }
33394
33439
  const change = applyChange(range);
33395
33440
  switch (change.changeType) {
33396
- case "NONE":
33397
- return range;
33398
33441
  case "REMOVE":
33399
33442
  return undefined;
33400
33443
  default:
@@ -33412,6 +33455,7 @@
33412
33455
  "getMeasureCompiledFormula",
33413
33456
  "getPivotName",
33414
33457
  "isExistingPivot",
33458
+ "getMeasureFullDependencies",
33415
33459
  ];
33416
33460
  nextFormulaId = 1;
33417
33461
  pivots = {};
@@ -33497,12 +33541,12 @@
33497
33541
  }
33498
33542
  case "UPDATE_PIVOT": {
33499
33543
  this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
33500
- this.compileCalculatedMeasures(cmd.pivot.measures);
33544
+ this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
33501
33545
  break;
33502
33546
  }
33503
33547
  }
33504
33548
  }
33505
- adaptRanges(applyChange) {
33549
+ adaptRanges({ applyChange, adaptFormulaString }) {
33506
33550
  for (const pivotId in this.pivots) {
33507
33551
  const definition = deepCopy(this.pivots[pivotId]?.definition);
33508
33552
  if (!definition) {
@@ -33515,22 +33559,22 @@
33515
33559
  this.history.update("pivots", pivotId, "definition", newDefinition);
33516
33560
  }
33517
33561
  }
33518
- for (const sheetId in this.compiledMeasureFormulas) {
33519
- for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
33520
- const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
33521
- const newDependencies = [];
33522
- for (const range of compiledFormula.dependencies) {
33523
- const change = applyChange(range);
33524
- if (change.changeType === "NONE") {
33525
- newDependencies.push(range);
33526
- }
33527
- else {
33528
- newDependencies.push(change.range);
33529
- }
33562
+ for (const pivotId in this.compiledMeasureFormulas) {
33563
+ for (const measureId in this.compiledMeasureFormulas[pivotId]) {
33564
+ const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
33565
+ if (!measure || !measure.computedBy) {
33566
+ continue;
33530
33567
  }
33531
- const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
33532
- if (newFormulaString !== formulaString) {
33533
- this.replaceMeasureFormula(sheetId, formulaString, newFormulaString);
33568
+ const sheetId = measure.computedBy.sheetId;
33569
+ const { formula: compiledFormula, dependencies: indirectDependencies } = this.compiledMeasureFormulas[pivotId][measureId];
33570
+ // adapt direct dependencies
33571
+ this.history.update("compiledMeasureFormulas", pivotId, measureId, "formula", "dependencies", compiledFormula.dependencies.map((range) => applyChange(range).range));
33572
+ // adapt all dependencies (including indirect)
33573
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", indirectDependencies.map((range) => applyChange(range).range));
33574
+ const oldFormulaString = measure.computedBy.formula;
33575
+ const newFormulaString = adaptFormulaString(sheetId, oldFormulaString);
33576
+ if (newFormulaString !== oldFormulaString) {
33577
+ this.replaceMeasureFormula(pivotId, measure, newFormulaString);
33534
33578
  }
33535
33579
  }
33536
33580
  }
@@ -33568,31 +33612,60 @@
33568
33612
  isExistingPivot(pivotId) {
33569
33613
  return pivotId in this.pivots;
33570
33614
  }
33571
- getMeasureCompiledFormula(measure) {
33615
+ getMeasureCompiledFormula(pivotId, measure) {
33572
33616
  if (!measure.computedBy) {
33573
33617
  throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
33574
33618
  }
33575
- const sheetId = measure.computedBy.sheetId;
33576
- return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
33619
+ return this.compiledMeasureFormulas[pivotId][measure.id].formula;
33620
+ }
33621
+ getMeasureFullDependencies(pivotId, measure) {
33622
+ if (!measure.computedBy) {
33623
+ throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
33624
+ }
33625
+ return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
33577
33626
  }
33578
33627
  // -------------------------------------------------------------------------
33579
33628
  // Private
33580
33629
  // -------------------------------------------------------------------------
33581
33630
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
33582
33631
  this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
33583
- this.compileCalculatedMeasures(pivot.measures);
33632
+ this.compileCalculatedMeasures(pivotId, pivot.measures);
33584
33633
  this.history.update("formulaIds", formulaId, pivotId);
33585
33634
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
33586
33635
  }
33587
- compileCalculatedMeasures(measures) {
33636
+ compileCalculatedMeasures(pivotId, measures) {
33588
33637
  for (const measure of measures) {
33589
33638
  if (measure.computedBy) {
33590
- const sheetId = measure.computedBy.sheetId;
33591
33639
  const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
33592
- this.history.update("compiledMeasureFormulas", sheetId, measure.computedBy.formula, compiledFormula);
33640
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
33641
+ }
33642
+ }
33643
+ for (const measure of measures) {
33644
+ if (measure.computedBy) {
33645
+ const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
33646
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
33593
33647
  }
33594
33648
  }
33595
33649
  }
33650
+ computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
33651
+ const rangeDependencies = [];
33652
+ const definition = this.getPivotCoreDefinition(pivotId);
33653
+ const formula = this.getMeasureCompiledFormula(pivotId, measure);
33654
+ exploredMeasures.add(measure.id);
33655
+ for (const token of formula.tokens) {
33656
+ if (token.type !== "SYMBOL") {
33657
+ continue;
33658
+ }
33659
+ const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
33660
+ measure.id !== measureCandidate.id);
33661
+ if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
33662
+ continue;
33663
+ }
33664
+ rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
33665
+ }
33666
+ rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
33667
+ return rangeDependencies;
33668
+ }
33596
33669
  insertPivot(position, formulaId, table) {
33597
33670
  this.resizeSheet(position.sheetId, position, table);
33598
33671
  const pivotCells = table.getPivotCells();
@@ -33651,21 +33724,16 @@
33651
33724
  dependencies: rangeDependencies,
33652
33725
  };
33653
33726
  }
33654
- replaceMeasureFormula(sheetId, formulaString, newFormulaString) {
33655
- this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
33656
- this.history.update("compiledMeasureFormulas", sheetId, newFormulaString, this.compileMeasureFormula(sheetId, newFormulaString));
33657
- for (const pivotId in this.pivots) {
33658
- const pivot = this.pivots[pivotId];
33659
- if (!pivot) {
33660
- continue;
33661
- }
33662
- for (const measure of pivot.definition.measures) {
33663
- if (measure.computedBy?.formula === formulaString) {
33664
- const measureIndex = pivot.definition.measures.indexOf(measure);
33665
- this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
33666
- }
33667
- }
33727
+ replaceMeasureFormula(pivotId, measure, newFormulaString) {
33728
+ const pivot = this.pivots[pivotId];
33729
+ if (!pivot) {
33730
+ return;
33668
33731
  }
33732
+ const measureIndex = pivot.definition.measures.indexOf(measure);
33733
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
33734
+ formula: newFormulaString,
33735
+ sheetId: measure.computedBy.sheetId,
33736
+ });
33669
33737
  }
33670
33738
  checkSortedColumnInMeasures(definition) {
33671
33739
  const measures = definition.measures.map((measure) => measure.id);
@@ -34726,7 +34794,7 @@
34726
34794
  case "UPDATE_CELL":
34727
34795
  if (cmd.style !== undefined) {
34728
34796
  if (cmd.style !== null) {
34729
- this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style);
34797
+ this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style, { force: true });
34730
34798
  }
34731
34799
  else {
34732
34800
  this.clearStyle(cmd.sheetId, [positionToZone(cmd)]);
@@ -34752,7 +34820,7 @@
34752
34820
  break;
34753
34821
  }
34754
34822
  }
34755
- adaptRanges(applyChange, sheetId) {
34823
+ adaptRanges({ applyChange }, sheetId) {
34756
34824
  const newStyles = [];
34757
34825
  for (const style of this.styles[sheetId] ?? []) {
34758
34826
  const change = applyChange(this.getters.getRangeFromZone(sheetId, style.zone));
@@ -34794,16 +34862,22 @@
34794
34862
  }
34795
34863
  }
34796
34864
  styleIsDefault(style) {
34797
- return deepEquals(this.removeDefaultStyleValues(style), {});
34865
+ for (const key in style) {
34866
+ if (DEFAULT_STYLE_NO_ALIGN[key] !== style[key]) {
34867
+ return false;
34868
+ }
34869
+ }
34870
+ return true;
34798
34871
  }
34799
34872
  removeDefaultStyleValues(style) {
34800
34873
  const cleanedStyle = { ...style };
34801
- for (const property in DEFAULT_STYLE_NO_ALIGN) {
34802
- if (cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
34874
+ for (const property in style) {
34875
+ if (cleanedStyle[property] === undefined ||
34876
+ cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
34803
34877
  delete cleanedStyle[property];
34804
34878
  }
34805
34879
  }
34806
- return cleanedStyle;
34880
+ return Object.keys(cleanedStyle).length > 0 ? cleanedStyle : undefined;
34807
34881
  }
34808
34882
  onMerge(sheetId, zone) {
34809
34883
  this.setStyle(sheetId, zone, this.getCellStyle({ sheetId, col: zone.left, row: zone.top }), {
@@ -34839,13 +34913,13 @@
34839
34913
  }
34840
34914
  editingZone = recomputeZones(editingZone, [inter]);
34841
34915
  }
34916
+ style = this.removeDefaultStyleValues(style);
34842
34917
  if (style) {
34843
- const newStyle = this.removeDefaultStyleValues(style);
34844
34918
  styles.push(...editingZone.map((zone) => {
34845
- return { zone, style: newStyle };
34919
+ return { zone, style };
34846
34920
  }));
34847
34921
  }
34848
- this.history.update("styles", sheetId, styles.filter((zoneStyle) => !this.styleIsDefault(zoneStyle.style)));
34922
+ this.history.update("styles", sheetId, styles);
34849
34923
  }
34850
34924
  clearStyle(sheetId, zones) {
34851
34925
  this.setStyles(sheetId, zones, undefined, { force: true });
@@ -35252,7 +35326,7 @@
35252
35326
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
35253
35327
  tables = {};
35254
35328
  nextTableId = 1;
35255
- adaptRanges(applyChange, sheetId) {
35329
+ adaptRanges({ applyChange }, sheetId) {
35256
35330
  for (const table of this.getCoreTables(sheetId)) {
35257
35331
  this.applyRangeChangeOnTable(sheetId, table, applyChange);
35258
35332
  }
@@ -37118,11 +37192,16 @@
37118
37192
  return this.arrayFormulasToResults.get(formulasPosition);
37119
37193
  }
37120
37194
  /**
37121
- * Remove a node, also remove it from other nodes adjacency list
37195
+ * Remove a spreading relation for a given array formula position
37196
+ * and its result zone
37122
37197
  */
37123
37198
  removeNode(position) {
37199
+ const resultZone = this.arrayFormulasToResults.get(position);
37200
+ if (!resultZone) {
37201
+ return;
37202
+ }
37124
37203
  this.resultsToArrayFormulas.remove({
37125
- boundingBox: { sheetId: position.sheetId, zone: positionToZone(position) },
37204
+ boundingBox: { sheetId: position.sheetId, zone: resultZone },
37126
37205
  data: position,
37127
37206
  });
37128
37207
  this.arrayFormulasToResults.delete(position);
@@ -37449,6 +37528,10 @@
37449
37528
  // empty matrix
37450
37529
  return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
37451
37530
  }
37531
+ if (nbRows === 1 && nbColumns === 1) {
37532
+ // single value matrix
37533
+ return createEvaluatedCell(validateNumberValue(formulaReturn[0][0]), this.getters.getLocale(), cellData);
37534
+ }
37452
37535
  const resultZone = {
37453
37536
  top: formulaPosition.row,
37454
37537
  bottom: formulaPosition.row + nbRows - 1,
@@ -37964,11 +38047,20 @@
37964
38047
  /**
37965
38048
  * Get the default height of the cell given its style.
37966
38049
  */
37967
- function getDefaultCellHeight(ctx, cell, style, colSize) {
38050
+ function getDefaultCellHeight(ctx, cell, style, locale, colSize) {
37968
38051
  if (!cell || (!cell.isFormula && !cell.content)) {
37969
38052
  return DEFAULT_CELL_HEIGHT;
37970
38053
  }
37971
- const content = cell.isFormula ? "" : cell.content;
38054
+ let content = "";
38055
+ try {
38056
+ if (!cell.isFormula) {
38057
+ const localeFormat = { format: cell.format, locale };
38058
+ content = formatValue(parseLiteral(cell.content, locale), localeFormat);
38059
+ }
38060
+ }
38061
+ catch {
38062
+ content = CellErrorType.GenericError;
38063
+ }
37972
38064
  return getCellContentHeight(ctx, content, style, colSize);
37973
38065
  }
37974
38066
  function getCellContentHeight(ctx, content, style, colSize) {
@@ -39547,15 +39639,15 @@
39547
39639
  if (!extensionsLoaded) {
39548
39640
  registerChartJSExtensions();
39549
39641
  }
39550
- if (!globalThis.Chart.registry.controllers.get(type)) {
39551
- console.log(`Chart of type "${type}" is not registered in Chart.js library.`);
39642
+ const config = deepCopy(runtime.chartJsConfig);
39643
+ config.plugins = [backgroundColorChartJSPlugin];
39644
+ if (!globalThis.Chart.registry.controllers.get(config.type)) {
39645
+ console.log(`Chart of type "${config.type}" is not registered in Chart.js library.`);
39552
39646
  if (!extensionsLoaded) {
39553
39647
  unregisterChartJsExtensions();
39554
39648
  }
39555
39649
  return imageUrl;
39556
39650
  }
39557
- const config = deepCopy(runtime.chartJsConfig);
39558
- config.plugins = [backgroundColorChartJSPlugin];
39559
39651
  const chart = new globalThis.Chart(canvas, config);
39560
39652
  try {
39561
39653
  imageUrl = await canvasToObjectUrl(canvas);
@@ -40221,6 +40313,7 @@
40221
40313
  handle(cmd) {
40222
40314
  switch (cmd.type) {
40223
40315
  case "START":
40316
+ case "UPDATE_LOCALE":
40224
40317
  for (const sheetId of this.getters.getSheetIds()) {
40225
40318
  this.initializeSheet(sheetId);
40226
40319
  }
@@ -40358,7 +40451,7 @@
40358
40451
  const cell = this.getters.getCell(position);
40359
40452
  const style = this.getters.getCellStyle(position);
40360
40453
  const colSize = this.getters.getColSize(position.sheetId, position.col);
40361
- return getDefaultCellHeight(this.ctx, cell, style, colSize);
40454
+ return getDefaultCellHeight(this.ctx, cell, style, this.getters.getLocale(), colSize);
40362
40455
  }
40363
40456
  isInMultiRowMerge(position) {
40364
40457
  const merge = this.getters.getMerge(position);
@@ -40487,14 +40580,16 @@
40487
40580
  function withPivotPresentationLayer (PivotClass) {
40488
40581
  class PivotPresentationLayer extends PivotClass {
40489
40582
  getters;
40583
+ pivotId;
40490
40584
  cache = {};
40491
40585
  rankAsc = {};
40492
40586
  rankDesc = {};
40493
40587
  runningTotal = {};
40494
40588
  runningTotalInPercent = {};
40495
- constructor(custom, params) {
40589
+ constructor(pivotId, custom, params) {
40496
40590
  super(custom, params);
40497
40591
  this.getters = params.getters;
40592
+ this.pivotId = pivotId;
40498
40593
  }
40499
40594
  markAsDirtyForEvaluation() {
40500
40595
  this.cache = {};
@@ -40544,7 +40639,7 @@
40544
40639
  return handleError(error, measure.aggregator.toUpperCase());
40545
40640
  }
40546
40641
  }
40547
- const formula = this.getters.getMeasureCompiledFormula(measure);
40642
+ const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
40548
40643
  const getSymbolValue = (symbolName) => {
40549
40644
  const { columns, rows } = this.definition;
40550
40645
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
@@ -41291,7 +41386,7 @@
41291
41386
  const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
41292
41387
  if (!(pivotId in this.pivots)) {
41293
41388
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
41294
- this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
41389
+ this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
41295
41390
  }
41296
41391
  else if (recreate) {
41297
41392
  this.pivots[pivotId].onDefinitionChange(definition);
@@ -47599,7 +47694,7 @@
47599
47694
  .add("pivot_ui", PivotUIPlugin)
47600
47695
  .add("cell_icon", CellIconPlugin);
47601
47696
 
47602
- class RangeAdapter {
47697
+ class RangeAdapterPlugin {
47603
47698
  getters;
47604
47699
  providers = [];
47605
47700
  isAdaptingRanges = false;
@@ -47607,7 +47702,6 @@
47607
47702
  this.getters = getters;
47608
47703
  }
47609
47704
  static getters = [
47610
- "adaptFormulaStringDependencies",
47611
47705
  "copyFormulaStringForSheet",
47612
47706
  "extendRange",
47613
47707
  "getRangeString",
@@ -47638,8 +47732,8 @@
47638
47732
  throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
47639
47733
  }
47640
47734
  const rangeAdapter = getRangeAdapter(cmd);
47641
- if (rangeAdapter?.applyChange) {
47642
- this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
47735
+ if (rangeAdapter) {
47736
+ this.executeOnAllRanges(rangeAdapter);
47643
47737
  }
47644
47738
  }
47645
47739
  finalize() { }
@@ -47658,11 +47752,15 @@
47658
47752
  return result;
47659
47753
  };
47660
47754
  }
47661
- executeOnAllRanges(adaptRange, sheetId, sheetName) {
47755
+ executeOnAllRanges(rangeAdapter) {
47662
47756
  this.isAdaptingRanges = true;
47663
- const func = this.verifyRangeRemoved(adaptRange);
47757
+ const adapterFunctions = {
47758
+ applyChange: this.verifyRangeRemoved(rangeAdapter.applyChange),
47759
+ adaptRangeString: (defaultSheetId, sheetXC) => adaptStringRange(defaultSheetId, sheetXC, rangeAdapter),
47760
+ adaptFormulaString: (defaultSheetId, formula) => adaptFormulaStringRanges(defaultSheetId, formula, rangeAdapter),
47761
+ };
47664
47762
  for (const provider of this.providers) {
47665
- provider(func, sheetId, sheetName);
47763
+ provider(adapterFunctions, rangeAdapter.sheetId, rangeAdapter.sheetName);
47666
47764
  }
47667
47765
  this.isAdaptingRanges = false;
47668
47766
  }
@@ -47830,18 +47928,6 @@
47830
47928
  const unionOfZones = unionUnboundedZones(...zones);
47831
47929
  return this.getRangeFromZone(ranges[0].sheetId, unionOfZones);
47832
47930
  }
47833
- adaptFormulaStringDependencies(sheetId, formula, applyChange) {
47834
- if (!formula.startsWith("=")) {
47835
- return formula;
47836
- }
47837
- const compiledFormula = compile(formula);
47838
- const updatedDependencies = compiledFormula.dependencies.map((dep) => {
47839
- const range = this.getters.getRangeFromSheetXC(sheetId, dep);
47840
- const changedRange = applyChange(range);
47841
- return changedRange.changeType === "NONE" ? range : changedRange.range;
47842
- });
47843
- return this.getters.getFormulaString(sheetId, compiledFormula.tokens, updatedDependencies);
47844
- }
47845
47931
  /**
47846
47932
  * Copy a formula string to another sheet.
47847
47933
  *
@@ -50283,6 +50369,12 @@
50283
50369
  if (style.alignment && style.alignment.wrapText) {
50284
50370
  alignAttrs.push(["wrapText", "1"]);
50285
50371
  }
50372
+ if (style.alignment && style.alignment.textRotation) {
50373
+ alignAttrs.push(["textRotation", style.alignment.textRotation]);
50374
+ }
50375
+ if (style.alignment && style.alignment.shrinkToFit) {
50376
+ alignAttrs.push(["shrinkToFit", "1"]);
50377
+ }
50286
50378
  if (alignAttrs.length > 0) {
50287
50379
  attributes.push(["applyAlignment", "1"]); // for Libre Office
50288
50380
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
@@ -51077,7 +51169,7 @@
51077
51169
  this.config = this.setupConfig(config);
51078
51170
  this.session = this.setupSession(workbookData.revisionId);
51079
51171
  this.coreGetters = {};
51080
- this.range = new RangeAdapter(this.coreGetters);
51172
+ this.range = new RangeAdapterPlugin(this.coreGetters);
51081
51173
  this.coreGetters.getRangeString = this.range.getRangeString.bind(this.range);
51082
51174
  this.coreGetters.getRangeFromSheetXC = this.range.getRangeFromSheetXC.bind(this.range);
51083
51175
  this.coreGetters.createAdaptedRanges = this.range.createAdaptedRanges.bind(this.range);
@@ -51091,8 +51183,6 @@
51091
51183
  this.coreGetters.extendRange = this.range.extendRange.bind(this.range);
51092
51184
  this.coreGetters.getRangesUnion = this.range.getRangesUnion.bind(this.range);
51093
51185
  this.coreGetters.removeRangesSheetPrefix = this.range.removeRangesSheetPrefix.bind(this.range);
51094
- this.coreGetters.adaptFormulaStringDependencies =
51095
- this.range.adaptFormulaStringDependencies.bind(this.range);
51096
51186
  this.coreGetters.copyFormulaStringForSheet = this.range.copyFormulaStringForSheet.bind(this.range);
51097
51187
  this.getters = {
51098
51188
  isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
@@ -51672,8 +51762,8 @@
51672
51762
 
51673
51763
 
51674
51764
  __info__.version = "19.1.0-alpha.3";
51675
- __info__.date = "2026-01-07T16:20:59.139Z";
51676
- __info__.hash = "febc3e9";
51765
+ __info__.date = "2026-01-21T11:06:38.842Z";
51766
+ __info__.hash = "ceae12a";
51677
51767
 
51678
51768
 
51679
51769
  })(this.o_spreadsheet_engine = this.o_spreadsheet_engine || {});