@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
  class FunctionCodeBuilder {
@@ -2517,7 +2517,11 @@ function evaluatePredicate(value = "", criterion, locale) {
2517
2517
  if (operator === "<>" || operator === "=") {
2518
2518
  let result;
2519
2519
  if (typeof value === typeof operand) {
2520
- if (typeof value === "string" && typeof operand === "string") {
2520
+ if (value === "" && operand === "") {
2521
+ // fast path to avoid regex evaluation
2522
+ result = true;
2523
+ }
2524
+ else if (typeof value === "string" && typeof operand === "string") {
2521
2525
  result = wildcardToRegExp(operand).test(value);
2522
2526
  }
2523
2527
  else {
@@ -2871,7 +2875,16 @@ function createComputeFunction(descr) {
2871
2875
  }
2872
2876
  acceptToVectorize.push(!argDefinition.acceptMatrix);
2873
2877
  }
2874
- return applyVectorization(errorHandlingCompute.bind(this), args, acceptToVectorize);
2878
+ return replaceErrorPlaceholderInResult(applyVectorization(errorHandlingCompute.bind(this), args, acceptToVectorize));
2879
+ }
2880
+ function replaceErrorPlaceholderInResult(result) {
2881
+ if (!isMatrix(result)) {
2882
+ replaceFunctionNamePlaceholder(result, descr.name);
2883
+ }
2884
+ else {
2885
+ matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, descr.name));
2886
+ }
2887
+ return result;
2875
2888
  }
2876
2889
  function errorHandlingCompute(...args) {
2877
2890
  for (let i = 0; i < args.length; i++) {
@@ -2900,13 +2913,12 @@ function createComputeFunction(descr) {
2900
2913
  const result = descr.compute.apply(this, args);
2901
2914
  if (!isMatrix(result)) {
2902
2915
  if (typeof result === "object" && result !== null && "value" in result) {
2903
- replaceFunctionNamePlaceholder(result, descr.name);
2904
2916
  return result;
2905
2917
  }
2918
+ descr.name;
2906
2919
  return { value: result };
2907
2920
  }
2908
2921
  if (typeof result[0][0] === "object" && result[0][0] !== null && "value" in result[0][0]) {
2909
- matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, descr.name));
2910
2922
  return result;
2911
2923
  }
2912
2924
  return matrixMap(result, (row) => ({ value: row }));
@@ -15073,9 +15085,10 @@ function assertDomainLength(domain) {
15073
15085
  throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
15074
15086
  }
15075
15087
  }
15076
- function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
15088
+ function addPivotDependencies(evalContext, pivotId, forMeasures) {
15077
15089
  //TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
15078
15090
  const dependencies = [];
15091
+ const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
15079
15092
  if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
15080
15093
  const { sheetId, zone } = coreDefinition.dataSet;
15081
15094
  const xc = zoneToXc(zone);
@@ -15092,8 +15105,7 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
15092
15105
  }
15093
15106
  for (const measure of forMeasures) {
15094
15107
  if (measure.computedBy) {
15095
- const formula = evalContext.getters.getMeasureCompiledFormula(measure);
15096
- dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
15108
+ dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
15097
15109
  }
15098
15110
  }
15099
15111
  const originPosition = evalContext.__originCellPosition;
@@ -15590,7 +15602,7 @@ const PIVOT_VALUE = {
15590
15602
  assertDomainLength(domainArgs);
15591
15603
  const pivot = this.getters.getPivot(pivotId);
15592
15604
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
15593
- addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
15605
+ addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
15594
15606
  pivot.init({ reload: pivot.needsReevaluation });
15595
15607
  const error = pivot.assertIsValid({ throwOnError: false });
15596
15608
  if (error) {
@@ -15623,8 +15635,7 @@ const PIVOT_HEADER = {
15623
15635
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
15624
15636
  assertDomainLength(domainArgs);
15625
15637
  const pivot = this.getters.getPivot(_pivotId);
15626
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
15627
- addPivotDependencies(this, coreDefinition, []);
15638
+ addPivotDependencies(this, _pivotId, []);
15628
15639
  pivot.init({ reload: pivot.needsReevaluation });
15629
15640
  const error = pivot.assertIsValid({ throwOnError: false });
15630
15641
  if (error) {
@@ -15676,7 +15687,7 @@ const PIVOT = {
15676
15687
  if (pivotStyle.numberOfColumns < 0) {
15677
15688
  return new EvaluationError(_t("The number of columns must be positive."));
15678
15689
  }
15679
- addPivotDependencies(this, coreDefinition, coreDefinition.measures);
15690
+ addPivotDependencies(this, pivotId, coreDefinition.measures);
15680
15691
  pivot.init({ reload: pivot.needsReevaluation });
15681
15692
  const error = pivot.assertIsValid({ throwOnError: false });
15682
15693
  if (error) {
@@ -18419,7 +18430,7 @@ function getApplyRangeChangeRemoveColRow(cmd) {
18419
18430
  const groups = groupConsecutive(elements);
18420
18431
  return (range) => {
18421
18432
  if (range.sheetId !== cmd.sheetId) {
18422
- return { changeType: "NONE" };
18433
+ return { changeType: "NONE", range };
18423
18434
  }
18424
18435
  let newRange = range;
18425
18436
  let changeType = "NONE";
@@ -18446,10 +18457,7 @@ function getApplyRangeChangeRemoveColRow(cmd) {
18446
18457
  newRange = createAdaptedRange(newRange, dimension, changeType, -(max - min + 1));
18447
18458
  }
18448
18459
  }
18449
- if (changeType !== "NONE") {
18450
- return { changeType, range: newRange };
18451
- }
18452
- return { changeType: "NONE" };
18460
+ return { changeType, range: newRange };
18453
18461
  };
18454
18462
  }
18455
18463
  function getApplyRangeChangeAddColRow(cmd) {
@@ -18458,7 +18466,7 @@ function getApplyRangeChangeAddColRow(cmd) {
18458
18466
  const dimension = cmd.dimension === "COL" ? "columns" : "rows";
18459
18467
  return (range) => {
18460
18468
  if (range.sheetId !== cmd.sheetId) {
18461
- return { changeType: "NONE" };
18469
+ return { changeType: "NONE", range };
18462
18470
  }
18463
18471
  if (cmd.position === "after") {
18464
18472
  if (range.zone[start] <= cmd.base && cmd.base < range.zone[end]) {
@@ -18488,13 +18496,13 @@ function getApplyRangeChangeAddColRow(cmd) {
18488
18496
  };
18489
18497
  }
18490
18498
  }
18491
- return { changeType: "NONE" };
18499
+ return { changeType: "NONE", range };
18492
18500
  };
18493
18501
  }
18494
18502
  function getApplyRangeChangeDeleteSheet(cmd) {
18495
18503
  return (range) => {
18496
18504
  if (range.sheetId !== cmd.sheetId && range.invalidSheetName !== cmd.sheetName) {
18497
- return { changeType: "NONE" };
18505
+ return { changeType: "NONE", range };
18498
18506
  }
18499
18507
  const invalidSheetName = cmd.sheetName;
18500
18508
  range = {
@@ -18521,14 +18529,14 @@ function getApplyRangeChangeRenameSheet(cmd) {
18521
18529
  const newRange = { ...range, sheetId, invalidSheetName };
18522
18530
  return { changeType: "CHANGE", range: newRange };
18523
18531
  }
18524
- return { changeType: "NONE" };
18532
+ return { changeType: "NONE", range };
18525
18533
  };
18526
18534
  }
18527
18535
  function getApplyRangeChangeMoveRange(cmd) {
18528
18536
  const originZone = cmd.target[0];
18529
18537
  return (range) => {
18530
18538
  if (range.sheetId !== cmd.sheetId || !isZoneInside(range.zone, originZone)) {
18531
- return { changeType: "NONE" };
18539
+ return { changeType: "NONE", range };
18532
18540
  }
18533
18541
  const targetSheetId = cmd.targetSheetId;
18534
18542
  const offsetX = cmd.col - originZone.left;
@@ -20060,7 +20068,7 @@ function adaptFormulaStringRanges(defaultSheetId, formula, applyChange) {
20060
20068
  continue;
20061
20069
  }
20062
20070
  const sheetXC = tokens[tokenIdx].value;
20063
- const newSheetXC = adaptStringRange(defaultSheetId, sheetXC, applyChange);
20071
+ const newSheetXC = adaptStringRange(defaultSheetId, sheetXC, applyChange).range;
20064
20072
  if (sheetXC !== newSheetXC) {
20065
20073
  tokens[tokenIdx] = {
20066
20074
  value: newSheetXC,
@@ -20070,23 +20078,30 @@ function adaptFormulaStringRanges(defaultSheetId, formula, applyChange) {
20070
20078
  }
20071
20079
  return concat(tokens.map((token) => token.value));
20072
20080
  }
20073
- function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20081
+ function adaptStringRange(defaultSheetId, sheetXC, rangeAdapter) {
20074
20082
  const sheetName = splitReference(sheetXC).sheetName;
20075
20083
  if (sheetName
20076
- ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
20077
- : defaultSheetId !== applyChange.sheetId) {
20078
- return sheetXC;
20084
+ ? !isSheetNameEqual(sheetName, rangeAdapter.sheetName.old)
20085
+ : defaultSheetId !== rangeAdapter.sheetId) {
20086
+ return { changeType: "NONE", range: sheetXC };
20079
20087
  }
20080
- const sheetId = sheetName ? applyChange.sheetId : defaultSheetId;
20088
+ const sheetId = sheetName ? rangeAdapter.sheetId : defaultSheetId;
20081
20089
  const range = getRange(sheetXC, sheetId);
20082
20090
  if (range.invalidXc) {
20083
- return sheetXC;
20091
+ return { changeType: "NONE", range: sheetXC };
20084
20092
  }
20085
- const change = applyChange.applyChange(range);
20093
+ const change = rangeAdapter.applyChange(range);
20086
20094
  if (change.changeType === "NONE" || change.changeType === "REMOVE") {
20087
- return sheetXC;
20095
+ return { changeType: change.changeType, range: sheetXC };
20088
20096
  }
20089
- return getRangeString(change.range, defaultSheetId, getSheetNameGetter(applyChange));
20097
+ const rangeStr = getRangeString(change.range, defaultSheetId, getSheetNameGetter(rangeAdapter));
20098
+ if (rangeStr === CellErrorType.InvalidReference) {
20099
+ return { changeType: "REMOVE", range: rangeStr };
20100
+ }
20101
+ return {
20102
+ changeType: change.changeType,
20103
+ range: rangeStr,
20104
+ };
20090
20105
  }
20091
20106
  function getSheetNameGetter(applyChange) {
20092
20107
  return (sheetId) => {
@@ -20301,7 +20316,7 @@ function addConditionalFormatCommandAdaptRange(cmd, applyChange) {
20301
20316
  cmd.cf.rule = {
20302
20317
  ...rule,
20303
20318
  rangeValues: rule.rangeValues
20304
- ? adaptStringRange(cmd.sheetId, rule.rangeValues, applyChange)
20319
+ ? adaptStringRange(cmd.sheetId, rule.rangeValues, applyChange).range
20305
20320
  : undefined,
20306
20321
  };
20307
20322
  }
@@ -22782,6 +22797,405 @@ function hexaToInt(hex) {
22782
22797
  */
22783
22798
  const DEFAULT_SYSTEM_COLOR = "FF000000";
22784
22799
 
22800
+ const globalReverseLookup$1 = new WeakMap();
22801
+ const globalIdCounter = new WeakMap();
22802
+ /**
22803
+ * Get the id of the given item (its key in the given dictionary).
22804
+ * If the given item does not exist in the dictionary, it creates one with a new id.
22805
+ */
22806
+ function getItemId(item, itemsDic) {
22807
+ if (!globalReverseLookup$1.has(itemsDic)) {
22808
+ globalReverseLookup$1.set(itemsDic, new Map());
22809
+ globalIdCounter.set(itemsDic, 0);
22810
+ }
22811
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
22812
+ const canonical = getCanonicalRepresentation(item);
22813
+ if (reverseLookup.has(canonical)) {
22814
+ const id = reverseLookup.get(canonical);
22815
+ itemsDic[id] = item;
22816
+ return id;
22817
+ }
22818
+ // Generate new Id if the item didn't exist in the dictionary
22819
+ const newId = globalIdCounter.get(itemsDic) + 1;
22820
+ reverseLookup.set(canonical, newId);
22821
+ globalIdCounter.set(itemsDic, newId);
22822
+ itemsDic[newId] = item;
22823
+ return newId;
22824
+ }
22825
+ function groupItemIdsByZones(positionsByItemId) {
22826
+ const result = {};
22827
+ for (const itemId in positionsByItemId) {
22828
+ const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
22829
+ for (const zone of zones) {
22830
+ result[zoneToXc(zone)] = Number(itemId);
22831
+ }
22832
+ }
22833
+ return result;
22834
+ }
22835
+ function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
22836
+ for (const zoneXc in itemIdsByZones) {
22837
+ const zone = toZone(zoneXc);
22838
+ const itemId = itemIdsByZones[zoneXc];
22839
+ for (let row = zone.top; row <= zone.bottom; row++) {
22840
+ for (let col = zone.left; col <= zone.right; col++) {
22841
+ const position = { sheetId, col, row };
22842
+ yield [position, itemId];
22843
+ }
22844
+ }
22845
+ }
22846
+ }
22847
+ function getCanonicalRepresentation(item) {
22848
+ if (item === null)
22849
+ return "null";
22850
+ if (item === undefined)
22851
+ return "undefined";
22852
+ if (typeof item !== "object")
22853
+ return String(item);
22854
+ if (Array.isArray(item)) {
22855
+ const len = item.length;
22856
+ let result = "[";
22857
+ for (let i = 0; i < len; i++) {
22858
+ if (i > 0)
22859
+ result += ",";
22860
+ result += getCanonicalRepresentation(item[i]);
22861
+ }
22862
+ return result + "]";
22863
+ }
22864
+ const keys = Object.keys(item).sort();
22865
+ let repr = "{";
22866
+ for (const key of keys) {
22867
+ if (item[key] !== undefined) {
22868
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
22869
+ }
22870
+ }
22871
+ repr += "}";
22872
+ return repr;
22873
+ }
22874
+
22875
+ // -------------------------------------
22876
+ // CF HELPERS
22877
+ // -------------------------------------
22878
+ /**
22879
+ * Convert the conditional formatting o-spreadsheet operator to
22880
+ * the corresponding excel operator.
22881
+ * */
22882
+ function convertOperator(operator) {
22883
+ switch (operator) {
22884
+ case "isNotEmpty":
22885
+ return "notContainsBlanks";
22886
+ case "isEmpty":
22887
+ return "containsBlanks";
22888
+ case "notContainsText":
22889
+ return "notContainsBlanks";
22890
+ case "containsText":
22891
+ return "containsText";
22892
+ case "beginsWithText":
22893
+ return "beginsWith";
22894
+ case "endsWithText":
22895
+ return "endsWith";
22896
+ case "isGreaterThan":
22897
+ return "greaterThan";
22898
+ case "isGreaterOrEqualTo":
22899
+ return "greaterThanOrEqual";
22900
+ case "isLessThan":
22901
+ return "lessThan";
22902
+ case "isLessOrEqualTo":
22903
+ return "lessThanOrEqual";
22904
+ case "isBetween":
22905
+ return "between";
22906
+ case "isNotBetween":
22907
+ return "notBetween";
22908
+ case "isEqual":
22909
+ return "equal";
22910
+ case "isNotEqual":
22911
+ return "notEqual";
22912
+ case "customFormula":
22913
+ return "";
22914
+ case "dateIs":
22915
+ return "";
22916
+ case "dateIsBefore":
22917
+ return "lessThan";
22918
+ case "dateIsAfter":
22919
+ return "greaterThan";
22920
+ case "dateIsOnOrAfter":
22921
+ return "greaterThanOrEqual";
22922
+ case "dateIsOnOrBefore":
22923
+ return "lessThanOrEqual";
22924
+ }
22925
+ }
22926
+ // -------------------------------------
22927
+ // WORKSHEET HELPERS
22928
+ // -------------------------------------
22929
+ function getCellType(value) {
22930
+ switch (typeof value) {
22931
+ case "boolean":
22932
+ return "b";
22933
+ case "string":
22934
+ return "str";
22935
+ case "number":
22936
+ return "n";
22937
+ default:
22938
+ return undefined;
22939
+ }
22940
+ }
22941
+ function convertHeightToExcel(height) {
22942
+ return Math.round(HEIGHT_FACTOR * height * 100) / 100;
22943
+ }
22944
+ function convertWidthToExcel(width) {
22945
+ return Math.round(WIDTH_FACTOR * width * 100) / 100;
22946
+ }
22947
+ function convertHeightFromExcel(height) {
22948
+ if (!height)
22949
+ return height;
22950
+ return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
22951
+ }
22952
+ function convertWidthFromExcel(width) {
22953
+ if (!width)
22954
+ return width;
22955
+ return Math.round((width / WIDTH_FACTOR) * 100) / 100;
22956
+ }
22957
+ function extractStyle(data, content, styleId, formatId, borderId) {
22958
+ const style = styleId ? data.styles[styleId] : {};
22959
+ const format = formatId ? data.formats[formatId] : undefined;
22960
+ const styles = {
22961
+ font: {
22962
+ size: style?.fontSize || DEFAULT_FONT_SIZE,
22963
+ color: { rgb: style?.textColor ? style.textColor : "000000" },
22964
+ family: 2,
22965
+ name: "Arial",
22966
+ },
22967
+ fill: style?.fillColor
22968
+ ? {
22969
+ fgColor: { rgb: style.fillColor },
22970
+ }
22971
+ : { reservedAttribute: "none" },
22972
+ numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
22973
+ border: borderId || 0,
22974
+ alignment: {
22975
+ horizontal: style.align,
22976
+ vertical: style.verticalAlign
22977
+ ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
22978
+ : undefined,
22979
+ wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
22980
+ textRotation: style.rotation ? rotationToXLSX(style.rotation) : undefined,
22981
+ shrinkToFit: style.wrapping === "clip" ? true : undefined,
22982
+ },
22983
+ };
22984
+ styles.font["strike"] = !!style?.strikethrough || undefined;
22985
+ styles.font["underline"] = !!style?.underline || undefined;
22986
+ styles.font["bold"] = !!style?.bold || undefined;
22987
+ styles.font["italic"] = !!style?.italic || undefined;
22988
+ return styles;
22989
+ }
22990
+ function rotationToXLSX(rad) {
22991
+ let deg = Math.round((-rad / Math.PI) * 180) % 180;
22992
+ if (deg > 90) {
22993
+ deg -= 180;
22994
+ }
22995
+ else if (deg < -90) {
22996
+ deg += 180;
22997
+ }
22998
+ if (deg >= 0) {
22999
+ return deg;
23000
+ }
23001
+ else {
23002
+ return 90 - deg;
23003
+ }
23004
+ }
23005
+ function rotationFromXLSX(deg) {
23006
+ if (deg <= 90) {
23007
+ return -(deg / 180) * Math.PI;
23008
+ }
23009
+ else {
23010
+ return (-(90 - deg) / 180) * Math.PI;
23011
+ }
23012
+ }
23013
+ function normalizeStyle(construct, styles) {
23014
+ // Normalize this
23015
+ const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
23016
+ const style = {
23017
+ fontId: pushElement(styles.font, construct.fonts),
23018
+ fillId: pushElement(styles.fill, construct.fills),
23019
+ borderId: styles.border,
23020
+ numFmtId,
23021
+ alignment: {
23022
+ vertical: styles.alignment.vertical,
23023
+ horizontal: styles.alignment.horizontal,
23024
+ wrapText: styles.alignment.wrapText,
23025
+ textRotation: styles.alignment.textRotation,
23026
+ shrinkToFit: styles.alignment.shrinkToFit,
23027
+ },
23028
+ };
23029
+ return pushElement(style, construct.styles);
23030
+ }
23031
+ function convertFormat(format, numFmtStructure) {
23032
+ if (!format) {
23033
+ return 0;
23034
+ }
23035
+ let formatId = XLSX_FORMAT_MAP[format.format];
23036
+ if (!formatId) {
23037
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23038
+ }
23039
+ return formatId;
23040
+ }
23041
+ /**
23042
+ * Add a relation to the given file and return its id.
23043
+ */
23044
+ function addRelsToFile(relsFiles, path, rel) {
23045
+ const relsFile = relsFiles.find((file) => file.path === path);
23046
+ // the id is a one-based int casted as string
23047
+ let id;
23048
+ if (!relsFile) {
23049
+ id = "rId1";
23050
+ relsFiles.push({ path, rels: [{ ...rel, id }] });
23051
+ }
23052
+ else {
23053
+ id = `rId${(relsFile.rels.length + 1).toString()}`;
23054
+ relsFile.rels.push({
23055
+ ...rel,
23056
+ id,
23057
+ });
23058
+ }
23059
+ return id;
23060
+ }
23061
+ const globalReverseLookup = new WeakMap();
23062
+ function pushElement(property, propertyList) {
23063
+ let reverseLookup = globalReverseLookup.get(propertyList);
23064
+ if (!reverseLookup) {
23065
+ reverseLookup = new Map();
23066
+ for (let i = 0; i < propertyList.length; i++) {
23067
+ const canonical = getCanonicalRepresentation(propertyList[i]);
23068
+ reverseLookup.set(canonical, i);
23069
+ }
23070
+ globalReverseLookup.set(propertyList, reverseLookup);
23071
+ }
23072
+ const canonical = getCanonicalRepresentation(property);
23073
+ if (reverseLookup.has(canonical)) {
23074
+ return reverseLookup.get(canonical);
23075
+ }
23076
+ const maxId = propertyList.length;
23077
+ propertyList.push(property);
23078
+ reverseLookup.set(canonical, maxId);
23079
+ return maxId;
23080
+ }
23081
+ /**
23082
+ * Convert a chart o-spreadsheet id to a xlsx id which
23083
+ * are unsigned integers (starting from 1).
23084
+ */
23085
+ function convertChartId(chartId, construct) {
23086
+ const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23087
+ if (xlsxId === -1) {
23088
+ construct.chartIds.push(chartId);
23089
+ return construct.chartIds.length;
23090
+ }
23091
+ return xlsxId + 1;
23092
+ }
23093
+ const imageIds = [];
23094
+ /**
23095
+ * Convert a image o-spreadsheet id to a xlsx id which
23096
+ * are unsigned integers (starting from 1).
23097
+ */
23098
+ function convertImageId(imageId) {
23099
+ const xlsxId = imageIds.findIndex((id) => id === imageId);
23100
+ if (xlsxId === -1) {
23101
+ imageIds.push(imageId);
23102
+ return imageIds.length;
23103
+ }
23104
+ return xlsxId + 1;
23105
+ }
23106
+ /**
23107
+ * Convert a value expressed in dot to EMU.
23108
+ * EMU = English Metrical Unit
23109
+ * There are 914400 EMU per inch.
23110
+ *
23111
+ * /!\ A value expressed in EMU cannot be fractional.
23112
+ * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23113
+ */
23114
+ function convertDotValueToEMU(value) {
23115
+ const DPI = 96;
23116
+ return Math.round((value * 914400) / DPI);
23117
+ }
23118
+ function getRangeSize(reference, defaultSheetIndex, data) {
23119
+ let xc = reference;
23120
+ let sheetName = undefined;
23121
+ ({ xc, sheetName } = splitReference(reference));
23122
+ let rangeSheetIndex;
23123
+ if (sheetName) {
23124
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23125
+ if (index < 0) {
23126
+ throw new Error("Unable to find a sheet with the name " + sheetName);
23127
+ }
23128
+ rangeSheetIndex = index;
23129
+ }
23130
+ else {
23131
+ rangeSheetIndex = Number(defaultSheetIndex);
23132
+ }
23133
+ const zone = toUnboundedZone(xc);
23134
+ if (zone.right === undefined) {
23135
+ zone.right = data.sheets[rangeSheetIndex].colNumber;
23136
+ }
23137
+ if (zone.bottom === undefined) {
23138
+ zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23139
+ }
23140
+ return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23141
+ }
23142
+ function convertEMUToDotValue(value) {
23143
+ const DPI = 96;
23144
+ return Math.round((value * DPI) / 914400);
23145
+ }
23146
+ /**
23147
+ * Get the position of the start of a column in Excel (in px).
23148
+ */
23149
+ function getColPosition(colIndex, sheetData) {
23150
+ let position = 0;
23151
+ for (let i = 0; i < colIndex; i++) {
23152
+ const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23153
+ if (colAtIndex?.width) {
23154
+ position += colAtIndex.width;
23155
+ }
23156
+ else if (sheetData.sheetFormat?.defaultColWidth) {
23157
+ position += sheetData.sheetFormat.defaultColWidth;
23158
+ }
23159
+ else {
23160
+ position += EXCEL_DEFAULT_COL_WIDTH;
23161
+ }
23162
+ }
23163
+ return position / WIDTH_FACTOR;
23164
+ }
23165
+ /**
23166
+ * Get the position of the start of a row in Excel (in px).
23167
+ */
23168
+ function getRowPosition(rowIndex, sheetData) {
23169
+ let position = 0;
23170
+ for (let i = 0; i < rowIndex; i++) {
23171
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23172
+ if (rowAtIndex?.height) {
23173
+ position += rowAtIndex.height;
23174
+ }
23175
+ else if (sheetData.sheetFormat?.defaultRowHeight) {
23176
+ position += sheetData.sheetFormat.defaultRowHeight;
23177
+ }
23178
+ else {
23179
+ position += EXCEL_DEFAULT_ROW_HEIGHT;
23180
+ }
23181
+ }
23182
+ return position / HEIGHT_FACTOR;
23183
+ }
23184
+ /**
23185
+ * Convert the o-spreadsheet data validation decimal
23186
+ * criterion type to the corresponding excel operator.
23187
+ */
23188
+ function convertDecimalCriterionTypeToExcelOperator(operator) {
23189
+ return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23190
+ }
23191
+ /**
23192
+ * Convert the o-spreadsheet data validation date
23193
+ * criterion type to the corresponding excel operator.
23194
+ */
23195
+ function convertDateCriterionTypeToExcelOperator(operator) {
23196
+ return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23197
+ }
23198
+
22785
23199
  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;
22786
23200
  /**
22787
23201
  * Convert excel format to o_spreadsheet format
@@ -22881,6 +23295,9 @@ function convertStyle(styleStruct, warningManager) {
22881
23295
  align: styleStruct.alignment?.horizontal
22882
23296
  ? H_ALIGNMENT_CONVERSION_MAP[styleStruct.alignment.horizontal]
22883
23297
  : undefined,
23298
+ rotation: styleStruct.alignment?.textRotation
23299
+ ? rotationFromXLSX(styleStruct.alignment.textRotation)
23300
+ : undefined,
22884
23301
  // 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
22885
23302
  fillColor: styleStruct.fillStyle?.patternType === "solid"
22886
23303
  ? convertColor(styleStruct.fillStyle?.fgColor)
@@ -23180,378 +23597,6 @@ function addCfConversionWarnings(cf, dxfs, warningManager) {
23180
23597
  }
23181
23598
  }
23182
23599
 
23183
- const globalReverseLookup$1 = new WeakMap();
23184
- const globalIdCounter = new WeakMap();
23185
- /**
23186
- * Get the id of the given item (its key in the given dictionary).
23187
- * If the given item does not exist in the dictionary, it creates one with a new id.
23188
- */
23189
- function getItemId(item, itemsDic) {
23190
- if (!globalReverseLookup$1.has(itemsDic)) {
23191
- globalReverseLookup$1.set(itemsDic, new Map());
23192
- globalIdCounter.set(itemsDic, 0);
23193
- }
23194
- const reverseLookup = globalReverseLookup$1.get(itemsDic);
23195
- const canonical = getCanonicalRepresentation(item);
23196
- if (reverseLookup.has(canonical)) {
23197
- const id = reverseLookup.get(canonical);
23198
- itemsDic[id] = item;
23199
- return id;
23200
- }
23201
- // Generate new Id if the item didn't exist in the dictionary
23202
- const newId = globalIdCounter.get(itemsDic) + 1;
23203
- reverseLookup.set(canonical, newId);
23204
- globalIdCounter.set(itemsDic, newId);
23205
- itemsDic[newId] = item;
23206
- return newId;
23207
- }
23208
- function groupItemIdsByZones(positionsByItemId) {
23209
- const result = {};
23210
- for (const itemId in positionsByItemId) {
23211
- const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
23212
- for (const zone of zones) {
23213
- result[zoneToXc(zone)] = Number(itemId);
23214
- }
23215
- }
23216
- return result;
23217
- }
23218
- function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
23219
- for (const zoneXc in itemIdsByZones) {
23220
- const zone = toZone(zoneXc);
23221
- const itemId = itemIdsByZones[zoneXc];
23222
- for (let row = zone.top; row <= zone.bottom; row++) {
23223
- for (let col = zone.left; col <= zone.right; col++) {
23224
- const position = { sheetId, col, row };
23225
- yield [position, itemId];
23226
- }
23227
- }
23228
- }
23229
- }
23230
- function getCanonicalRepresentation(item) {
23231
- if (item === null)
23232
- return "null";
23233
- if (item === undefined)
23234
- return "undefined";
23235
- if (typeof item !== "object")
23236
- return String(item);
23237
- if (Array.isArray(item)) {
23238
- const len = item.length;
23239
- let result = "[";
23240
- for (let i = 0; i < len; i++) {
23241
- if (i > 0)
23242
- result += ",";
23243
- result += getCanonicalRepresentation(item[i]);
23244
- }
23245
- return result + "]";
23246
- }
23247
- const keys = Object.keys(item).sort();
23248
- let repr = "{";
23249
- for (const key of keys) {
23250
- if (item[key] !== undefined) {
23251
- repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
23252
- }
23253
- }
23254
- repr += "}";
23255
- return repr;
23256
- }
23257
-
23258
- // -------------------------------------
23259
- // CF HELPERS
23260
- // -------------------------------------
23261
- /**
23262
- * Convert the conditional formatting o-spreadsheet operator to
23263
- * the corresponding excel operator.
23264
- * */
23265
- function convertOperator(operator) {
23266
- switch (operator) {
23267
- case "isNotEmpty":
23268
- return "notContainsBlanks";
23269
- case "isEmpty":
23270
- return "containsBlanks";
23271
- case "notContainsText":
23272
- return "notContainsBlanks";
23273
- case "containsText":
23274
- return "containsText";
23275
- case "beginsWithText":
23276
- return "beginsWith";
23277
- case "endsWithText":
23278
- return "endsWith";
23279
- case "isGreaterThan":
23280
- return "greaterThan";
23281
- case "isGreaterOrEqualTo":
23282
- return "greaterThanOrEqual";
23283
- case "isLessThan":
23284
- return "lessThan";
23285
- case "isLessOrEqualTo":
23286
- return "lessThanOrEqual";
23287
- case "isBetween":
23288
- return "between";
23289
- case "isNotBetween":
23290
- return "notBetween";
23291
- case "isEqual":
23292
- return "equal";
23293
- case "isNotEqual":
23294
- return "notEqual";
23295
- case "customFormula":
23296
- return "";
23297
- case "dateIs":
23298
- return "";
23299
- case "dateIsBefore":
23300
- return "lessThan";
23301
- case "dateIsAfter":
23302
- return "greaterThan";
23303
- case "dateIsOnOrAfter":
23304
- return "greaterThanOrEqual";
23305
- case "dateIsOnOrBefore":
23306
- return "lessThanOrEqual";
23307
- }
23308
- }
23309
- // -------------------------------------
23310
- // WORKSHEET HELPERS
23311
- // -------------------------------------
23312
- function getCellType(value) {
23313
- switch (typeof value) {
23314
- case "boolean":
23315
- return "b";
23316
- case "string":
23317
- return "str";
23318
- case "number":
23319
- return "n";
23320
- default:
23321
- return undefined;
23322
- }
23323
- }
23324
- function convertHeightToExcel(height) {
23325
- return Math.round(HEIGHT_FACTOR * height * 100) / 100;
23326
- }
23327
- function convertWidthToExcel(width) {
23328
- return Math.round(WIDTH_FACTOR * width * 100) / 100;
23329
- }
23330
- function convertHeightFromExcel(height) {
23331
- if (!height)
23332
- return height;
23333
- return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
23334
- }
23335
- function convertWidthFromExcel(width) {
23336
- if (!width)
23337
- return width;
23338
- return Math.round((width / WIDTH_FACTOR) * 100) / 100;
23339
- }
23340
- function extractStyle(data, content, styleId, formatId, borderId) {
23341
- const style = styleId ? data.styles[styleId] : {};
23342
- const format = formatId ? data.formats[formatId] : undefined;
23343
- const styles = {
23344
- font: {
23345
- size: style?.fontSize || DEFAULT_FONT_SIZE,
23346
- color: { rgb: style?.textColor ? style.textColor : "000000" },
23347
- family: 2,
23348
- name: "Arial",
23349
- },
23350
- fill: style?.fillColor
23351
- ? {
23352
- fgColor: { rgb: style.fillColor },
23353
- }
23354
- : { reservedAttribute: "none" },
23355
- numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
23356
- border: borderId || 0,
23357
- alignment: {
23358
- horizontal: style.align,
23359
- vertical: style.verticalAlign
23360
- ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
23361
- : undefined,
23362
- wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
23363
- },
23364
- };
23365
- styles.font["strike"] = !!style?.strikethrough || undefined;
23366
- styles.font["underline"] = !!style?.underline || undefined;
23367
- styles.font["bold"] = !!style?.bold || undefined;
23368
- styles.font["italic"] = !!style?.italic || undefined;
23369
- return styles;
23370
- }
23371
- function normalizeStyle(construct, styles) {
23372
- // Normalize this
23373
- const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
23374
- const style = {
23375
- fontId: pushElement(styles.font, construct.fonts),
23376
- fillId: pushElement(styles.fill, construct.fills),
23377
- borderId: styles.border,
23378
- numFmtId,
23379
- alignment: {
23380
- vertical: styles.alignment.vertical,
23381
- horizontal: styles.alignment.horizontal,
23382
- wrapText: styles.alignment.wrapText,
23383
- },
23384
- };
23385
- return pushElement(style, construct.styles);
23386
- }
23387
- function convertFormat(format, numFmtStructure) {
23388
- if (!format) {
23389
- return 0;
23390
- }
23391
- let formatId = XLSX_FORMAT_MAP[format.format];
23392
- if (!formatId) {
23393
- formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23394
- }
23395
- return formatId;
23396
- }
23397
- /**
23398
- * Add a relation to the given file and return its id.
23399
- */
23400
- function addRelsToFile(relsFiles, path, rel) {
23401
- const relsFile = relsFiles.find((file) => file.path === path);
23402
- // the id is a one-based int casted as string
23403
- let id;
23404
- if (!relsFile) {
23405
- id = "rId1";
23406
- relsFiles.push({ path, rels: [{ ...rel, id }] });
23407
- }
23408
- else {
23409
- id = `rId${(relsFile.rels.length + 1).toString()}`;
23410
- relsFile.rels.push({
23411
- ...rel,
23412
- id,
23413
- });
23414
- }
23415
- return id;
23416
- }
23417
- const globalReverseLookup = new WeakMap();
23418
- function pushElement(property, propertyList) {
23419
- let reverseLookup = globalReverseLookup.get(propertyList);
23420
- if (!reverseLookup) {
23421
- reverseLookup = new Map();
23422
- for (let i = 0; i < propertyList.length; i++) {
23423
- const canonical = getCanonicalRepresentation(propertyList[i]);
23424
- reverseLookup.set(canonical, i);
23425
- }
23426
- globalReverseLookup.set(propertyList, reverseLookup);
23427
- }
23428
- const canonical = getCanonicalRepresentation(property);
23429
- if (reverseLookup.has(canonical)) {
23430
- return reverseLookup.get(canonical);
23431
- }
23432
- const maxId = propertyList.length;
23433
- propertyList.push(property);
23434
- reverseLookup.set(canonical, maxId);
23435
- return maxId;
23436
- }
23437
- /**
23438
- * Convert a chart o-spreadsheet id to a xlsx id which
23439
- * are unsigned integers (starting from 1).
23440
- */
23441
- function convertChartId(chartId, construct) {
23442
- const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23443
- if (xlsxId === -1) {
23444
- construct.chartIds.push(chartId);
23445
- return construct.chartIds.length;
23446
- }
23447
- return xlsxId + 1;
23448
- }
23449
- const imageIds = [];
23450
- /**
23451
- * Convert a image o-spreadsheet id to a xlsx id which
23452
- * are unsigned integers (starting from 1).
23453
- */
23454
- function convertImageId(imageId) {
23455
- const xlsxId = imageIds.findIndex((id) => id === imageId);
23456
- if (xlsxId === -1) {
23457
- imageIds.push(imageId);
23458
- return imageIds.length;
23459
- }
23460
- return xlsxId + 1;
23461
- }
23462
- /**
23463
- * Convert a value expressed in dot to EMU.
23464
- * EMU = English Metrical Unit
23465
- * There are 914400 EMU per inch.
23466
- *
23467
- * /!\ A value expressed in EMU cannot be fractional.
23468
- * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23469
- */
23470
- function convertDotValueToEMU(value) {
23471
- const DPI = 96;
23472
- return Math.round((value * 914400) / DPI);
23473
- }
23474
- function getRangeSize(reference, defaultSheetIndex, data) {
23475
- let xc = reference;
23476
- let sheetName = undefined;
23477
- ({ xc, sheetName } = splitReference(reference));
23478
- let rangeSheetIndex;
23479
- if (sheetName) {
23480
- const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23481
- if (index < 0) {
23482
- throw new Error("Unable to find a sheet with the name " + sheetName);
23483
- }
23484
- rangeSheetIndex = index;
23485
- }
23486
- else {
23487
- rangeSheetIndex = Number(defaultSheetIndex);
23488
- }
23489
- const zone = toUnboundedZone(xc);
23490
- if (zone.right === undefined) {
23491
- zone.right = data.sheets[rangeSheetIndex].colNumber;
23492
- }
23493
- if (zone.bottom === undefined) {
23494
- zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23495
- }
23496
- return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23497
- }
23498
- function convertEMUToDotValue(value) {
23499
- const DPI = 96;
23500
- return Math.round((value * DPI) / 914400);
23501
- }
23502
- /**
23503
- * Get the position of the start of a column in Excel (in px).
23504
- */
23505
- function getColPosition(colIndex, sheetData) {
23506
- let position = 0;
23507
- for (let i = 0; i < colIndex; i++) {
23508
- const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23509
- if (colAtIndex?.width) {
23510
- position += colAtIndex.width;
23511
- }
23512
- else if (sheetData.sheetFormat?.defaultColWidth) {
23513
- position += sheetData.sheetFormat.defaultColWidth;
23514
- }
23515
- else {
23516
- position += EXCEL_DEFAULT_COL_WIDTH;
23517
- }
23518
- }
23519
- return position / WIDTH_FACTOR;
23520
- }
23521
- /**
23522
- * Get the position of the start of a row in Excel (in px).
23523
- */
23524
- function getRowPosition(rowIndex, sheetData) {
23525
- let position = 0;
23526
- for (let i = 0; i < rowIndex; i++) {
23527
- const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23528
- if (rowAtIndex?.height) {
23529
- position += rowAtIndex.height;
23530
- }
23531
- else if (sheetData.sheetFormat?.defaultRowHeight) {
23532
- position += sheetData.sheetFormat.defaultRowHeight;
23533
- }
23534
- else {
23535
- position += EXCEL_DEFAULT_ROW_HEIGHT;
23536
- }
23537
- }
23538
- return position / HEIGHT_FACTOR;
23539
- }
23540
- /**
23541
- * Convert the o-spreadsheet data validation decimal
23542
- * criterion type to the corresponding excel operator.
23543
- */
23544
- function convertDecimalCriterionTypeToExcelOperator(operator) {
23545
- return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23546
- }
23547
- /**
23548
- * Convert the o-spreadsheet data validation date
23549
- * criterion type to the corresponding excel operator.
23550
- */
23551
- function convertDateCriterionTypeToExcelOperator(operator) {
23552
- return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23553
- }
23554
-
23555
23600
  function convertFigures(sheetData) {
23556
23601
  let id = 1;
23557
23602
  return sheetData.figures
@@ -27543,7 +27588,7 @@ class CorePlugin extends BasePlugin {
27543
27588
  * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
27544
27589
  * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
27545
27590
  */
27546
- adaptRanges(applyChange, sheetId, sheetName) { }
27591
+ adaptRanges(rangeAdapterFunctions, sheetId, sheetName) { }
27547
27592
  }
27548
27593
 
27549
27594
  class BordersPlugin extends CorePlugin {
@@ -27617,7 +27662,7 @@ class BordersPlugin extends CorePlugin {
27617
27662
  }
27618
27663
  }
27619
27664
  }
27620
- adaptRanges(applyChange, sheetId) {
27665
+ adaptRanges({ applyChange }, sheetId) {
27621
27666
  const newBorders = [];
27622
27667
  for (const border of this.borders[sheetId] ?? []) {
27623
27668
  const change = applyChange(this.getters.getRangeFromZone(sheetId, border.zone));
@@ -28098,7 +28143,7 @@ class CellPlugin extends CorePlugin {
28098
28143
  ];
28099
28144
  nextId = 1;
28100
28145
  cells = {};
28101
- adaptRanges(applyChange, sheetId, sheetName) {
28146
+ adaptRanges({ applyChange }, sheetId, sheetName) {
28102
28147
  for (const sheet of Object.keys(this.cells)) {
28103
28148
  for (const cell of Object.values(this.cells[sheet] || {})) {
28104
28149
  if (cell.isFormula) {
@@ -28659,12 +28704,12 @@ class ChartPlugin extends CorePlugin {
28659
28704
  charts = {};
28660
28705
  createChart = chartFactory(this.getters);
28661
28706
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
28662
- adaptRanges(applyChange, sheetId, adaptSheetName) {
28707
+ adaptRanges(rangeAdapters) {
28663
28708
  for (const [chartId, chart] of Object.entries(this.charts)) {
28664
28709
  if (!chart) {
28665
28710
  continue;
28666
28711
  }
28667
- const newChart = chart.chart.updateRanges(applyChange, sheetId, adaptSheetName);
28712
+ const newChart = chart.chart.updateRanges(rangeAdapters);
28668
28713
  this.history.update("charts", chartId, newChart ? { figureId: chart.figureId, chart: newChart } : undefined);
28669
28714
  }
28670
28715
  }
@@ -29485,7 +29530,7 @@ class ConditionalFormatPlugin extends CorePlugin {
29485
29530
  "getAdaptedCfRanges",
29486
29531
  ];
29487
29532
  cfRules = {};
29488
- adaptCFFormulas(applyChange) {
29533
+ adaptCFFormulas({ applyChange, adaptFormulaString }) {
29489
29534
  for (const sheetId in this.cfRules) {
29490
29535
  for (const rule of this.cfRules[sheetId]) {
29491
29536
  if (rule.rule.type === "DataBarRule" && rule.rule.rangeValues) {
@@ -29509,7 +29554,7 @@ class ConditionalFormatPlugin extends CorePlugin {
29509
29554
  for (let i = 0; i < rule.rule.values.length; i++) {
29510
29555
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29511
29556
  //@ts-expect-error
29512
- "values", i, this.getters.adaptFormulaStringDependencies(sheetId, rule.rule.values[i], applyChange));
29557
+ "values", i, adaptFormulaString(sheetId, rule.rule.values[i]));
29513
29558
  }
29514
29559
  }
29515
29560
  else if (rule.rule.type === "IconSetRule") {
@@ -29517,7 +29562,7 @@ class ConditionalFormatPlugin extends CorePlugin {
29517
29562
  if (rule.rule[inflectionPoint].type === "formula") {
29518
29563
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29519
29564
  //@ts-expect-error
29520
- inflectionPoint, "value", this.getters.adaptFormulaStringDependencies(sheetId, rule.rule[inflectionPoint].value, applyChange));
29565
+ inflectionPoint, "value", adaptFormulaString(sheetId, rule.rule[inflectionPoint].value));
29521
29566
  }
29522
29567
  }
29523
29568
  }
@@ -29527,14 +29572,14 @@ class ConditionalFormatPlugin extends CorePlugin {
29527
29572
  if (ruleValue?.type === "formula" && ruleValue?.value) {
29528
29573
  this.history.update("cfRules", sheetId, this.cfRules[sheetId].indexOf(rule), "rule",
29529
29574
  //@ts-expect-error
29530
- value, "value", this.getters.adaptFormulaStringDependencies(sheetId, ruleValue.value, applyChange));
29575
+ value, "value", adaptFormulaString(sheetId, ruleValue.value));
29531
29576
  }
29532
29577
  }
29533
29578
  }
29534
29579
  }
29535
29580
  }
29536
29581
  }
29537
- adaptCFRanges(sheetId, applyChange) {
29582
+ adaptCFRanges(sheetId, { applyChange }) {
29538
29583
  for (const rule of this.cfRules[sheetId]) {
29539
29584
  for (const range of rule.ranges) {
29540
29585
  const change = applyChange(range);
@@ -29558,12 +29603,12 @@ class ConditionalFormatPlugin extends CorePlugin {
29558
29603
  }
29559
29604
  }
29560
29605
  }
29561
- adaptRanges(applyChange, sheetId) {
29606
+ adaptRanges(rangeAdapters, sheetId) {
29562
29607
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
29563
29608
  for (const sheetId of sheetIds) {
29564
- this.adaptCFRanges(sheetId, applyChange);
29609
+ this.adaptCFRanges(sheetId, rangeAdapters);
29565
29610
  }
29566
- this.adaptCFFormulas(applyChange);
29611
+ this.adaptCFFormulas(rangeAdapters);
29567
29612
  }
29568
29613
  // ---------------------------------------------------------------------------
29569
29614
  // Command Handling
@@ -29940,23 +29985,23 @@ class DataValidationPlugin extends CorePlugin {
29940
29985
  "getValidationRuleForCell",
29941
29986
  ];
29942
29987
  rules = {};
29943
- adaptRanges(applyChange, sheetId) {
29944
- this.adaptDVRanges(sheetId, applyChange);
29945
- this.adaptDVFormulas(applyChange);
29988
+ adaptRanges(rangeAdapters, sheetId) {
29989
+ this.adaptDVRanges(sheetId, rangeAdapters);
29990
+ this.adaptDVFormulas(rangeAdapters);
29946
29991
  }
29947
- adaptDVFormulas(applyChange) {
29992
+ adaptDVFormulas({ adaptFormulaString }) {
29948
29993
  for (const sheetId in this.rules) {
29949
29994
  const rules = this.rules[sheetId];
29950
29995
  for (let ruleIndex = rules.length - 1; ruleIndex >= 0; ruleIndex--) {
29951
29996
  const rule = this.rules[sheetId][ruleIndex];
29952
29997
  for (let valueIndex = 0; valueIndex < rule.criterion.values.length; valueIndex++) {
29953
- const value = this.getters.adaptFormulaStringDependencies(sheetId, rule.criterion.values[valueIndex], applyChange);
29998
+ const value = adaptFormulaString(sheetId, rule.criterion.values[valueIndex]);
29954
29999
  this.history.update("rules", sheetId, ruleIndex, "criterion", "values", valueIndex, value);
29955
30000
  }
29956
30001
  }
29957
30002
  }
29958
30003
  }
29959
- adaptDVRanges(sheetId, applyChange) {
30004
+ adaptDVRanges(sheetId, { applyChange }) {
29960
30005
  const rules = this.rules[sheetId];
29961
30006
  for (let ruleIndex = rules.length - 1; ruleIndex >= 0; ruleIndex--) {
29962
30007
  const rule = this.rules[sheetId][ruleIndex];
@@ -30230,7 +30275,7 @@ class FigurePlugin extends CorePlugin {
30230
30275
  // ---------------------------------------------------------------------------
30231
30276
  // Command Handling
30232
30277
  // ---------------------------------------------------------------------------
30233
- adaptRanges(applyChange, sheetId) {
30278
+ adaptRanges({ applyChange }, sheetId) {
30234
30279
  for (const figure of this.getFigures(sheetId)) {
30235
30280
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
30236
30281
  left: figure.col,
@@ -31470,8 +31515,8 @@ class MergePlugin extends CorePlugin {
31470
31515
  break;
31471
31516
  }
31472
31517
  }
31473
- adaptRanges(applyChange, sheetId) {
31474
- this.applyRangeChangeOnSheet(sheetId, applyChange);
31518
+ adaptRanges(rangeAdapters, sheetId) {
31519
+ this.applyRangeChangeOnSheet(sheetId, rangeAdapters);
31475
31520
  }
31476
31521
  // ---------------------------------------------------------------------------
31477
31522
  // Getters
@@ -31771,7 +31816,7 @@ class MergePlugin extends CorePlugin {
31771
31816
  /**
31772
31817
  * Apply a range change on merges of a particular sheet.
31773
31818
  */
31774
- applyRangeChangeOnSheet(sheetId, applyChange) {
31819
+ applyRangeChangeOnSheet(sheetId, { applyChange }) {
31775
31820
  const merges = Object.entries(this.merges[sheetId] || {});
31776
31821
  for (const [mergeId, range] of merges) {
31777
31822
  if (range) {
@@ -33390,8 +33435,6 @@ function adaptPivotRange(range, applyChange) {
33390
33435
  }
33391
33436
  const change = applyChange(range);
33392
33437
  switch (change.changeType) {
33393
- case "NONE":
33394
- return range;
33395
33438
  case "REMOVE":
33396
33439
  return undefined;
33397
33440
  default:
@@ -33409,6 +33452,7 @@ class PivotCorePlugin extends CorePlugin {
33409
33452
  "getMeasureCompiledFormula",
33410
33453
  "getPivotName",
33411
33454
  "isExistingPivot",
33455
+ "getMeasureFullDependencies",
33412
33456
  ];
33413
33457
  nextFormulaId = 1;
33414
33458
  pivots = {};
@@ -33494,12 +33538,12 @@ class PivotCorePlugin extends CorePlugin {
33494
33538
  }
33495
33539
  case "UPDATE_PIVOT": {
33496
33540
  this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
33497
- this.compileCalculatedMeasures(cmd.pivot.measures);
33541
+ this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
33498
33542
  break;
33499
33543
  }
33500
33544
  }
33501
33545
  }
33502
- adaptRanges(applyChange) {
33546
+ adaptRanges({ applyChange, adaptFormulaString }) {
33503
33547
  for (const pivotId in this.pivots) {
33504
33548
  const definition = deepCopy(this.pivots[pivotId]?.definition);
33505
33549
  if (!definition) {
@@ -33512,22 +33556,22 @@ class PivotCorePlugin extends CorePlugin {
33512
33556
  this.history.update("pivots", pivotId, "definition", newDefinition);
33513
33557
  }
33514
33558
  }
33515
- for (const sheetId in this.compiledMeasureFormulas) {
33516
- for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
33517
- const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
33518
- const newDependencies = [];
33519
- for (const range of compiledFormula.dependencies) {
33520
- const change = applyChange(range);
33521
- if (change.changeType === "NONE") {
33522
- newDependencies.push(range);
33523
- }
33524
- else {
33525
- newDependencies.push(change.range);
33526
- }
33559
+ for (const pivotId in this.compiledMeasureFormulas) {
33560
+ for (const measureId in this.compiledMeasureFormulas[pivotId]) {
33561
+ const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
33562
+ if (!measure || !measure.computedBy) {
33563
+ continue;
33527
33564
  }
33528
- const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
33529
- if (newFormulaString !== formulaString) {
33530
- this.replaceMeasureFormula(sheetId, formulaString, newFormulaString);
33565
+ const sheetId = measure.computedBy.sheetId;
33566
+ const { formula: compiledFormula, dependencies: indirectDependencies } = this.compiledMeasureFormulas[pivotId][measureId];
33567
+ // adapt direct dependencies
33568
+ this.history.update("compiledMeasureFormulas", pivotId, measureId, "formula", "dependencies", compiledFormula.dependencies.map((range) => applyChange(range).range));
33569
+ // adapt all dependencies (including indirect)
33570
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", indirectDependencies.map((range) => applyChange(range).range));
33571
+ const oldFormulaString = measure.computedBy.formula;
33572
+ const newFormulaString = adaptFormulaString(sheetId, oldFormulaString);
33573
+ if (newFormulaString !== oldFormulaString) {
33574
+ this.replaceMeasureFormula(pivotId, measure, newFormulaString);
33531
33575
  }
33532
33576
  }
33533
33577
  }
@@ -33565,31 +33609,60 @@ class PivotCorePlugin extends CorePlugin {
33565
33609
  isExistingPivot(pivotId) {
33566
33610
  return pivotId in this.pivots;
33567
33611
  }
33568
- getMeasureCompiledFormula(measure) {
33612
+ getMeasureCompiledFormula(pivotId, measure) {
33569
33613
  if (!measure.computedBy) {
33570
33614
  throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
33571
33615
  }
33572
- const sheetId = measure.computedBy.sheetId;
33573
- return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
33616
+ return this.compiledMeasureFormulas[pivotId][measure.id].formula;
33617
+ }
33618
+ getMeasureFullDependencies(pivotId, measure) {
33619
+ if (!measure.computedBy) {
33620
+ throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
33621
+ }
33622
+ return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
33574
33623
  }
33575
33624
  // -------------------------------------------------------------------------
33576
33625
  // Private
33577
33626
  // -------------------------------------------------------------------------
33578
33627
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
33579
33628
  this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
33580
- this.compileCalculatedMeasures(pivot.measures);
33629
+ this.compileCalculatedMeasures(pivotId, pivot.measures);
33581
33630
  this.history.update("formulaIds", formulaId, pivotId);
33582
33631
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
33583
33632
  }
33584
- compileCalculatedMeasures(measures) {
33633
+ compileCalculatedMeasures(pivotId, measures) {
33585
33634
  for (const measure of measures) {
33586
33635
  if (measure.computedBy) {
33587
- const sheetId = measure.computedBy.sheetId;
33588
33636
  const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
33589
- this.history.update("compiledMeasureFormulas", sheetId, measure.computedBy.formula, compiledFormula);
33637
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
33638
+ }
33639
+ }
33640
+ for (const measure of measures) {
33641
+ if (measure.computedBy) {
33642
+ const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
33643
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
33590
33644
  }
33591
33645
  }
33592
33646
  }
33647
+ computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
33648
+ const rangeDependencies = [];
33649
+ const definition = this.getPivotCoreDefinition(pivotId);
33650
+ const formula = this.getMeasureCompiledFormula(pivotId, measure);
33651
+ exploredMeasures.add(measure.id);
33652
+ for (const token of formula.tokens) {
33653
+ if (token.type !== "SYMBOL") {
33654
+ continue;
33655
+ }
33656
+ const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
33657
+ measure.id !== measureCandidate.id);
33658
+ if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
33659
+ continue;
33660
+ }
33661
+ rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
33662
+ }
33663
+ rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
33664
+ return rangeDependencies;
33665
+ }
33593
33666
  insertPivot(position, formulaId, table) {
33594
33667
  this.resizeSheet(position.sheetId, position, table);
33595
33668
  const pivotCells = table.getPivotCells();
@@ -33648,21 +33721,16 @@ class PivotCorePlugin extends CorePlugin {
33648
33721
  dependencies: rangeDependencies,
33649
33722
  };
33650
33723
  }
33651
- replaceMeasureFormula(sheetId, formulaString, newFormulaString) {
33652
- this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
33653
- this.history.update("compiledMeasureFormulas", sheetId, newFormulaString, this.compileMeasureFormula(sheetId, newFormulaString));
33654
- for (const pivotId in this.pivots) {
33655
- const pivot = this.pivots[pivotId];
33656
- if (!pivot) {
33657
- continue;
33658
- }
33659
- for (const measure of pivot.definition.measures) {
33660
- if (measure.computedBy?.formula === formulaString) {
33661
- const measureIndex = pivot.definition.measures.indexOf(measure);
33662
- this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
33663
- }
33664
- }
33724
+ replaceMeasureFormula(pivotId, measure, newFormulaString) {
33725
+ const pivot = this.pivots[pivotId];
33726
+ if (!pivot) {
33727
+ return;
33665
33728
  }
33729
+ const measureIndex = pivot.definition.measures.indexOf(measure);
33730
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
33731
+ formula: newFormulaString,
33732
+ sheetId: measure.computedBy.sheetId,
33733
+ });
33666
33734
  }
33667
33735
  checkSortedColumnInMeasures(definition) {
33668
33736
  const measures = definition.measures.map((measure) => measure.id);
@@ -34723,7 +34791,7 @@ class StylePlugin extends CorePlugin {
34723
34791
  case "UPDATE_CELL":
34724
34792
  if (cmd.style !== undefined) {
34725
34793
  if (cmd.style !== null) {
34726
- this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style);
34794
+ this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style, { force: true });
34727
34795
  }
34728
34796
  else {
34729
34797
  this.clearStyle(cmd.sheetId, [positionToZone(cmd)]);
@@ -34749,7 +34817,7 @@ class StylePlugin extends CorePlugin {
34749
34817
  break;
34750
34818
  }
34751
34819
  }
34752
- adaptRanges(applyChange, sheetId) {
34820
+ adaptRanges({ applyChange }, sheetId) {
34753
34821
  const newStyles = [];
34754
34822
  for (const style of this.styles[sheetId] ?? []) {
34755
34823
  const change = applyChange(this.getters.getRangeFromZone(sheetId, style.zone));
@@ -34791,16 +34859,22 @@ class StylePlugin extends CorePlugin {
34791
34859
  }
34792
34860
  }
34793
34861
  styleIsDefault(style) {
34794
- return deepEquals(this.removeDefaultStyleValues(style), {});
34862
+ for (const key in style) {
34863
+ if (DEFAULT_STYLE_NO_ALIGN[key] !== style[key]) {
34864
+ return false;
34865
+ }
34866
+ }
34867
+ return true;
34795
34868
  }
34796
34869
  removeDefaultStyleValues(style) {
34797
34870
  const cleanedStyle = { ...style };
34798
- for (const property in DEFAULT_STYLE_NO_ALIGN) {
34799
- if (cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
34871
+ for (const property in style) {
34872
+ if (cleanedStyle[property] === undefined ||
34873
+ cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
34800
34874
  delete cleanedStyle[property];
34801
34875
  }
34802
34876
  }
34803
- return cleanedStyle;
34877
+ return Object.keys(cleanedStyle).length > 0 ? cleanedStyle : undefined;
34804
34878
  }
34805
34879
  onMerge(sheetId, zone) {
34806
34880
  this.setStyle(sheetId, zone, this.getCellStyle({ sheetId, col: zone.left, row: zone.top }), {
@@ -34836,13 +34910,13 @@ class StylePlugin extends CorePlugin {
34836
34910
  }
34837
34911
  editingZone = recomputeZones(editingZone, [inter]);
34838
34912
  }
34913
+ style = this.removeDefaultStyleValues(style);
34839
34914
  if (style) {
34840
- const newStyle = this.removeDefaultStyleValues(style);
34841
34915
  styles.push(...editingZone.map((zone) => {
34842
- return { zone, style: newStyle };
34916
+ return { zone, style };
34843
34917
  }));
34844
34918
  }
34845
- this.history.update("styles", sheetId, styles.filter((zoneStyle) => !this.styleIsDefault(zoneStyle.style)));
34919
+ this.history.update("styles", sheetId, styles);
34846
34920
  }
34847
34921
  clearStyle(sheetId, zones) {
34848
34922
  this.setStyles(sheetId, zones, undefined, { force: true });
@@ -35249,7 +35323,7 @@ class TablePlugin extends CorePlugin {
35249
35323
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
35250
35324
  tables = {};
35251
35325
  nextTableId = 1;
35252
- adaptRanges(applyChange, sheetId) {
35326
+ adaptRanges({ applyChange }, sheetId) {
35253
35327
  for (const table of this.getCoreTables(sheetId)) {
35254
35328
  this.applyRangeChangeOnTable(sheetId, table, applyChange);
35255
35329
  }
@@ -37115,11 +37189,16 @@ class SpreadingRelation {
37115
37189
  return this.arrayFormulasToResults.get(formulasPosition);
37116
37190
  }
37117
37191
  /**
37118
- * Remove a node, also remove it from other nodes adjacency list
37192
+ * Remove a spreading relation for a given array formula position
37193
+ * and its result zone
37119
37194
  */
37120
37195
  removeNode(position) {
37196
+ const resultZone = this.arrayFormulasToResults.get(position);
37197
+ if (!resultZone) {
37198
+ return;
37199
+ }
37121
37200
  this.resultsToArrayFormulas.remove({
37122
- boundingBox: { sheetId: position.sheetId, zone: positionToZone(position) },
37201
+ boundingBox: { sheetId: position.sheetId, zone: resultZone },
37123
37202
  data: position,
37124
37203
  });
37125
37204
  this.arrayFormulasToResults.delete(position);
@@ -37446,6 +37525,10 @@ class Evaluator {
37446
37525
  // empty matrix
37447
37526
  return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
37448
37527
  }
37528
+ if (nbRows === 1 && nbColumns === 1) {
37529
+ // single value matrix
37530
+ return createEvaluatedCell(validateNumberValue(formulaReturn[0][0]), this.getters.getLocale(), cellData);
37531
+ }
37449
37532
  const resultZone = {
37450
37533
  top: formulaPosition.row,
37451
37534
  bottom: formulaPosition.row + nbRows - 1,
@@ -37961,11 +38044,20 @@ function getCanvas(width = 100, height = 100) {
37961
38044
  /**
37962
38045
  * Get the default height of the cell given its style.
37963
38046
  */
37964
- function getDefaultCellHeight(ctx, cell, style, colSize) {
38047
+ function getDefaultCellHeight(ctx, cell, style, locale, colSize) {
37965
38048
  if (!cell || (!cell.isFormula && !cell.content)) {
37966
38049
  return DEFAULT_CELL_HEIGHT;
37967
38050
  }
37968
- const content = cell.isFormula ? "" : cell.content;
38051
+ let content = "";
38052
+ try {
38053
+ if (!cell.isFormula) {
38054
+ const localeFormat = { format: cell.format, locale };
38055
+ content = formatValue(parseLiteral(cell.content, locale), localeFormat);
38056
+ }
38057
+ }
38058
+ catch {
38059
+ content = CellErrorType.GenericError;
38060
+ }
37969
38061
  return getCellContentHeight(ctx, content, style, colSize);
37970
38062
  }
37971
38063
  function getCellContentHeight(ctx, content, style, colSize) {
@@ -39544,15 +39636,15 @@ async function chartToImageUrl(runtime, figure, type) {
39544
39636
  if (!extensionsLoaded) {
39545
39637
  registerChartJSExtensions();
39546
39638
  }
39547
- if (!globalThis.Chart.registry.controllers.get(type)) {
39548
- console.log(`Chart of type "${type}" is not registered in Chart.js library.`);
39639
+ const config = deepCopy(runtime.chartJsConfig);
39640
+ config.plugins = [backgroundColorChartJSPlugin];
39641
+ if (!globalThis.Chart.registry.controllers.get(config.type)) {
39642
+ console.log(`Chart of type "${config.type}" is not registered in Chart.js library.`);
39549
39643
  if (!extensionsLoaded) {
39550
39644
  unregisterChartJsExtensions();
39551
39645
  }
39552
39646
  return imageUrl;
39553
39647
  }
39554
- const config = deepCopy(runtime.chartJsConfig);
39555
- config.plugins = [backgroundColorChartJSPlugin];
39556
39648
  const chart = new globalThis.Chart(canvas, config);
39557
39649
  try {
39558
39650
  imageUrl = await canvasToObjectUrl(canvas);
@@ -40218,6 +40310,7 @@ class HeaderSizeUIPlugin extends CoreViewPlugin {
40218
40310
  handle(cmd) {
40219
40311
  switch (cmd.type) {
40220
40312
  case "START":
40313
+ case "UPDATE_LOCALE":
40221
40314
  for (const sheetId of this.getters.getSheetIds()) {
40222
40315
  this.initializeSheet(sheetId);
40223
40316
  }
@@ -40355,7 +40448,7 @@ class HeaderSizeUIPlugin extends CoreViewPlugin {
40355
40448
  const cell = this.getters.getCell(position);
40356
40449
  const style = this.getters.getCellStyle(position);
40357
40450
  const colSize = this.getters.getColSize(position.sheetId, position.col);
40358
- return getDefaultCellHeight(this.ctx, cell, style, colSize);
40451
+ return getDefaultCellHeight(this.ctx, cell, style, this.getters.getLocale(), colSize);
40359
40452
  }
40360
40453
  isInMultiRowMerge(position) {
40361
40454
  const merge = this.getters.getMerge(position);
@@ -40484,14 +40577,16 @@ const PERCENT_FORMAT = "0.00%";
40484
40577
  function withPivotPresentationLayer (PivotClass) {
40485
40578
  class PivotPresentationLayer extends PivotClass {
40486
40579
  getters;
40580
+ pivotId;
40487
40581
  cache = {};
40488
40582
  rankAsc = {};
40489
40583
  rankDesc = {};
40490
40584
  runningTotal = {};
40491
40585
  runningTotalInPercent = {};
40492
- constructor(custom, params) {
40586
+ constructor(pivotId, custom, params) {
40493
40587
  super(custom, params);
40494
40588
  this.getters = params.getters;
40589
+ this.pivotId = pivotId;
40495
40590
  }
40496
40591
  markAsDirtyForEvaluation() {
40497
40592
  this.cache = {};
@@ -40541,7 +40636,7 @@ function withPivotPresentationLayer (PivotClass) {
40541
40636
  return handleError(error, measure.aggregator.toUpperCase());
40542
40637
  }
40543
40638
  }
40544
- const formula = this.getters.getMeasureCompiledFormula(measure);
40639
+ const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
40545
40640
  const getSymbolValue = (symbolName) => {
40546
40641
  const { columns, rows } = this.definition;
40547
40642
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
@@ -41288,7 +41383,7 @@ class PivotUIPlugin extends CoreViewPlugin {
41288
41383
  const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
41289
41384
  if (!(pivotId in this.pivots)) {
41290
41385
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
41291
- this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
41386
+ this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
41292
41387
  }
41293
41388
  else if (recreate) {
41294
41389
  this.pivots[pivotId].onDefinitionChange(definition);
@@ -47596,7 +47691,7 @@ const coreViewsPluginRegistry = new Registry$1()
47596
47691
  .add("pivot_ui", PivotUIPlugin)
47597
47692
  .add("cell_icon", CellIconPlugin);
47598
47693
 
47599
- class RangeAdapter {
47694
+ class RangeAdapterPlugin {
47600
47695
  getters;
47601
47696
  providers = [];
47602
47697
  isAdaptingRanges = false;
@@ -47604,7 +47699,6 @@ class RangeAdapter {
47604
47699
  this.getters = getters;
47605
47700
  }
47606
47701
  static getters = [
47607
- "adaptFormulaStringDependencies",
47608
47702
  "copyFormulaStringForSheet",
47609
47703
  "extendRange",
47610
47704
  "getRangeString",
@@ -47635,8 +47729,8 @@ class RangeAdapter {
47635
47729
  throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
47636
47730
  }
47637
47731
  const rangeAdapter = getRangeAdapter(cmd);
47638
- if (rangeAdapter?.applyChange) {
47639
- this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
47732
+ if (rangeAdapter) {
47733
+ this.executeOnAllRanges(rangeAdapter);
47640
47734
  }
47641
47735
  }
47642
47736
  finalize() { }
@@ -47655,11 +47749,15 @@ class RangeAdapter {
47655
47749
  return result;
47656
47750
  };
47657
47751
  }
47658
- executeOnAllRanges(adaptRange, sheetId, sheetName) {
47752
+ executeOnAllRanges(rangeAdapter) {
47659
47753
  this.isAdaptingRanges = true;
47660
- const func = this.verifyRangeRemoved(adaptRange);
47754
+ const adapterFunctions = {
47755
+ applyChange: this.verifyRangeRemoved(rangeAdapter.applyChange),
47756
+ adaptRangeString: (defaultSheetId, sheetXC) => adaptStringRange(defaultSheetId, sheetXC, rangeAdapter),
47757
+ adaptFormulaString: (defaultSheetId, formula) => adaptFormulaStringRanges(defaultSheetId, formula, rangeAdapter),
47758
+ };
47661
47759
  for (const provider of this.providers) {
47662
- provider(func, sheetId, sheetName);
47760
+ provider(adapterFunctions, rangeAdapter.sheetId, rangeAdapter.sheetName);
47663
47761
  }
47664
47762
  this.isAdaptingRanges = false;
47665
47763
  }
@@ -47827,18 +47925,6 @@ class RangeAdapter {
47827
47925
  const unionOfZones = unionUnboundedZones(...zones);
47828
47926
  return this.getRangeFromZone(ranges[0].sheetId, unionOfZones);
47829
47927
  }
47830
- adaptFormulaStringDependencies(sheetId, formula, applyChange) {
47831
- if (!formula.startsWith("=")) {
47832
- return formula;
47833
- }
47834
- const compiledFormula = compile(formula);
47835
- const updatedDependencies = compiledFormula.dependencies.map((dep) => {
47836
- const range = this.getters.getRangeFromSheetXC(sheetId, dep);
47837
- const changedRange = applyChange(range);
47838
- return changedRange.changeType === "NONE" ? range : changedRange.range;
47839
- });
47840
- return this.getters.getFormulaString(sheetId, compiledFormula.tokens, updatedDependencies);
47841
- }
47842
47928
  /**
47843
47929
  * Copy a formula string to another sheet.
47844
47930
  *
@@ -50280,6 +50366,12 @@ function addStyles(styles) {
50280
50366
  if (style.alignment && style.alignment.wrapText) {
50281
50367
  alignAttrs.push(["wrapText", "1"]);
50282
50368
  }
50369
+ if (style.alignment && style.alignment.textRotation) {
50370
+ alignAttrs.push(["textRotation", style.alignment.textRotation]);
50371
+ }
50372
+ if (style.alignment && style.alignment.shrinkToFit) {
50373
+ alignAttrs.push(["shrinkToFit", "1"]);
50374
+ }
50283
50375
  if (alignAttrs.length > 0) {
50284
50376
  attributes.push(["applyAlignment", "1"]); // for Libre Office
50285
50377
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
@@ -51074,7 +51166,7 @@ class Model extends EventBus {
51074
51166
  this.config = this.setupConfig(config);
51075
51167
  this.session = this.setupSession(workbookData.revisionId);
51076
51168
  this.coreGetters = {};
51077
- this.range = new RangeAdapter(this.coreGetters);
51169
+ this.range = new RangeAdapterPlugin(this.coreGetters);
51078
51170
  this.coreGetters.getRangeString = this.range.getRangeString.bind(this.range);
51079
51171
  this.coreGetters.getRangeFromSheetXC = this.range.getRangeFromSheetXC.bind(this.range);
51080
51172
  this.coreGetters.createAdaptedRanges = this.range.createAdaptedRanges.bind(this.range);
@@ -51088,8 +51180,6 @@ class Model extends EventBus {
51088
51180
  this.coreGetters.extendRange = this.range.extendRange.bind(this.range);
51089
51181
  this.coreGetters.getRangesUnion = this.range.getRangesUnion.bind(this.range);
51090
51182
  this.coreGetters.removeRangesSheetPrefix = this.range.removeRangesSheetPrefix.bind(this.range);
51091
- this.coreGetters.adaptFormulaStringDependencies =
51092
- this.range.adaptFormulaStringDependencies.bind(this.range);
51093
51183
  this.coreGetters.copyFormulaStringForSheet = this.range.copyFormulaStringForSheet.bind(this.range);
51094
51184
  this.getters = {
51095
51185
  isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
@@ -51560,5 +51650,5 @@ export { BadExpressionError, BasePlugin, CellErrorType, CircularDependencyError,
51560
51650
 
51561
51651
 
51562
51652
  __info__.version = "19.1.0-alpha.3";
51563
- __info__.date = "2026-01-07T16:20:59.139Z";
51564
- __info__.hash = "febc3e9";
51653
+ __info__.date = "2026-01-21T11:06:38.842Z";
51654
+ __info__.hash = "ceae12a";