@odoo/o-spreadsheet 18.4.8 → 18.4.9

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.
@@ -2,9 +2,9 @@
2
2
  /**
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
- * @version 18.4.8
6
- * @date 2025-08-26T10:14:08.954Z
7
- * @hash 746217a
5
+ * @version 18.4.9
6
+ * @date 2025-09-05T07:38:32.126Z
7
+ * @hash a261873
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -2643,6 +2643,7 @@ const invalidateBordersCommands = new Set([
2643
2643
  "AUTOFILL_CELL",
2644
2644
  "SET_BORDER",
2645
2645
  "SET_ZONE_BORDERS",
2646
+ "SET_BORDERS_ON_TARGET",
2646
2647
  ]);
2647
2648
  const readonlyAllowedCommands = new Set([
2648
2649
  "START",
@@ -3989,6 +3990,10 @@ function isDataNonEmpty(data) {
3989
3990
  }
3990
3991
  return true;
3991
3992
  }
3993
+ const noValidInputErrorMessage = _t("[[FUNCTION_NAME]] has no valid input data.");
3994
+ function emptyDataErrorMessage(argName) {
3995
+ return _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", { argName });
3996
+ }
3992
3997
 
3993
3998
  function tokenizeFormat(str) {
3994
3999
  const chars = new TokenizingChars(str);
@@ -6590,40 +6595,44 @@ function orderRange(range) {
6590
6595
  };
6591
6596
  }
6592
6597
  function getRangeAdapter(cmd) {
6593
- switch (cmd.type) {
6594
- case "REMOVE_COLUMNS_ROWS":
6595
- return {
6596
- applyChange: getApplyRangeChangeRemoveColRow(cmd),
6597
- sheetId: cmd.sheetId,
6598
- sheetName: cmd.sheetName,
6599
- };
6600
- case "ADD_COLUMNS_ROWS":
6601
- return {
6602
- applyChange: getApplyRangeChangeAddColRow(cmd),
6603
- sheetId: cmd.sheetId,
6604
- sheetName: cmd.sheetName,
6605
- };
6606
- case "DELETE_SHEET":
6607
- return {
6608
- applyChange: getApplyRangeChangeDeleteSheet(cmd),
6609
- sheetId: cmd.sheetId,
6610
- sheetName: cmd.sheetName,
6611
- };
6612
- case "RENAME_SHEET":
6613
- return {
6614
- applyChange: getApplyRangeChangeRenameSheet(cmd),
6615
- sheetId: cmd.sheetId,
6616
- sheetName: cmd.oldName,
6617
- };
6618
- case "MOVE_RANGES":
6619
- return {
6620
- applyChange: getApplyRangeChangeMoveRange(cmd),
6621
- sheetId: cmd.sheetId,
6622
- sheetName: cmd.sheetName,
6623
- };
6598
+ return rangeAdapterRegistry.get(cmd.type)?.(cmd);
6599
+ }
6600
+ class RangeAdapterRegistry extends Registry {
6601
+ add(cmdType, fn) {
6602
+ super.add(cmdType, fn);
6603
+ return this;
6604
+ }
6605
+ get(cmdType) {
6606
+ return this.content[cmdType];
6624
6607
  }
6625
- return undefined;
6626
6608
  }
6609
+ const rangeAdapterRegistry = new RangeAdapterRegistry();
6610
+ rangeAdapterRegistry
6611
+ .add("REMOVE_COLUMNS_ROWS", (cmd) => ({
6612
+ applyChange: getApplyRangeChangeRemoveColRow(cmd),
6613
+ sheetId: cmd.sheetId,
6614
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6615
+ }))
6616
+ .add("ADD_COLUMNS_ROWS", (cmd) => ({
6617
+ applyChange: getApplyRangeChangeAddColRow(cmd),
6618
+ sheetId: cmd.sheetId,
6619
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6620
+ }))
6621
+ .add("DELETE_SHEET", (cmd) => ({
6622
+ applyChange: getApplyRangeChangeDeleteSheet(cmd),
6623
+ sheetId: cmd.sheetId,
6624
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6625
+ }))
6626
+ .add("RENAME_SHEET", (cmd) => ({
6627
+ applyChange: getApplyRangeChangeRenameSheet(cmd),
6628
+ sheetId: cmd.sheetId,
6629
+ sheetName: { old: cmd.oldName, current: cmd.newName },
6630
+ }))
6631
+ .add("MOVE_RANGES", (cmd) => ({
6632
+ applyChange: getApplyRangeChangeMoveRange(cmd),
6633
+ sheetId: cmd.sheetId,
6634
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6635
+ }));
6627
6636
  function getApplyRangeChangeRemoveColRow(cmd) {
6628
6637
  const start = cmd.dimension === "COL" ? "left" : "top";
6629
6638
  const end = cmd.dimension === "COL" ? "right" : "bottom";
@@ -8000,8 +8009,11 @@ function invertMatrix(M) {
8000
8009
  // (a) Swap 2 rows. This multiply the determinant by -1.
8001
8010
  // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
8002
8011
  // (c) Add to a row a multiple of another row. This does not change the determinant.
8012
+ if (M.length < 1 || M[0].length < 1) {
8013
+ throw new Error("invertMatrix: an empty matrix cannot be inverted.");
8014
+ }
8003
8015
  if (M.length !== M[0].length) {
8004
- throw new EvaluationError(_t("Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible"));
8016
+ throw new Error("invertMatrix: only square matrices are invertible");
8005
8017
  }
8006
8018
  let determinant = 1;
8007
8019
  const dim = M.length;
@@ -8070,8 +8082,11 @@ function swapMatrixRows(matrix, row1, row2) {
8070
8082
  * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
8071
8083
  */
8072
8084
  function multiplyMatrices(matrix1, matrix2) {
8085
+ if (matrix1.length < 1 || matrix2.length < 1) {
8086
+ throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
8087
+ }
8073
8088
  if (matrix1.length !== matrix2[0].length) {
8074
- throw new EvaluationError(_t("Cannot multiply matrices : incompatible matrices size."));
8089
+ throw new Error("multiplyMatrices: incompatible matrices size.");
8075
8090
  }
8076
8091
  const rowsM1 = matrix1[0].length;
8077
8092
  const colsM2 = matrix2.length;
@@ -8097,7 +8112,7 @@ function toScalar(arg) {
8097
8112
  return arg;
8098
8113
  }
8099
8114
  if (!isSingleElementMatrix(arg)) {
8100
- throw new EvaluationError(_t("The value should be a scalar or a 1x1 matrix"));
8115
+ throw new Error("The value should be a scalar or a 1x1 matrix");
8101
8116
  }
8102
8117
  return arg[0][0];
8103
8118
  }
@@ -11236,6 +11251,9 @@ const MMULT = {
11236
11251
  compute: function (matrix1, matrix2) {
11237
11252
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
11238
11253
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
11254
+ if (_matrix1.length === 0 || _matrix2.length === 0) {
11255
+ return new EvaluationError(_t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
11256
+ }
11239
11257
  if (_matrix1.length !== _matrix2[0].length) {
11240
11258
  return new EvaluationError(_t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
11241
11259
  number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
@@ -12848,7 +12866,7 @@ function centile(data, percent, isInclusive, locale) {
12848
12866
  count++;
12849
12867
  }
12850
12868
  });
12851
- assert(count !== 0, _t("[[FUNCTION_NAME]] has no valid input data."));
12869
+ assert(count !== 0, noValidInputErrorMessage);
12852
12870
  if (!isInclusive) {
12853
12871
  // 2nd argument must be between 1/(n+1) and n/(n+1) with n the number of data
12854
12872
  assert(1 / (count + 1) <= _percent && _percent <= count / (count + 1), _t("Function [[FUNCTION_NAME]] parameter 2 value is out of range."));
@@ -13123,6 +13141,9 @@ const FORECAST = {
13123
13141
  ],
13124
13142
  compute: function (x, dataY, dataX) {
13125
13143
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13144
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13145
+ return new NotAvailableError(noValidInputErrorMessage);
13146
+ }
13126
13147
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
13127
13148
  },
13128
13149
  isExported: true,
@@ -13139,6 +13160,9 @@ const GROWTH = {
13139
13160
  arg("b (boolean, default=TRUE)", _t("Given a general exponential form of y = b*m^x for a curve fit, calculates b if TRUE or forces b to be 1 and only calculates the m values if FALSE.")),
13140
13161
  ],
13141
13162
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13163
+ if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13164
+ return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13165
+ }
13142
13166
  return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "the first argument (known_data_y)")), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b)));
13143
13167
  },
13144
13168
  };
@@ -13153,6 +13177,9 @@ const INTERCEPT = {
13153
13177
  ],
13154
13178
  compute: function (dataY, dataX) {
13155
13179
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13180
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13181
+ return new NotAvailableError(noValidInputErrorMessage);
13182
+ }
13156
13183
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
13157
13184
  return intercept;
13158
13185
  },
@@ -13185,7 +13212,7 @@ const LARGE = {
13185
13212
  });
13186
13213
  const result = largests.shift();
13187
13214
  if (result === undefined) {
13188
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
13215
+ return new EvaluationError(noValidInputErrorMessage);
13189
13216
  }
13190
13217
  if (count < _n) {
13191
13218
  return new EvaluationError(_t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
@@ -13206,6 +13233,9 @@ const LINEST = {
13206
13233
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13207
13234
  ],
13208
13235
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13236
+ if (dataY.length === 0 || dataY[0].length === 0) {
13237
+ return new EvaluationError(emptyDataErrorMessage("data_y"));
13238
+ }
13209
13239
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
13210
13240
  },
13211
13241
  isExported: true,
@@ -13222,6 +13252,9 @@ const LOGEST = {
13222
13252
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13223
13253
  ],
13224
13254
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13255
+ if (dataY.length === 0 || dataY[0].length === 0) {
13256
+ return new EvaluationError(emptyDataErrorMessage("data_y"));
13257
+ }
13225
13258
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
13226
13259
  for (let i = 0; i < coeffs.length; i++) {
13227
13260
  coeffs[i][0] = Math.exp(coeffs[i][0]);
@@ -13243,8 +13276,8 @@ const MATTHEWS = {
13243
13276
  const flatX = dataX.flat();
13244
13277
  const flatY = dataY.flat();
13245
13278
  assertSameNumberOfElements(flatX, flatY);
13246
- if (flatX.length === 0) {
13247
- return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13279
+ if (flatX.length === 0 || flatY.length === 0) {
13280
+ return new NotAvailableError(noValidInputErrorMessage);
13248
13281
  }
13249
13282
  const n = flatX.length;
13250
13283
  let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
@@ -13409,11 +13442,8 @@ const MINIFS = {
13409
13442
  // -----------------------------------------------------------------------------
13410
13443
  function pearson(dataY, dataX) {
13411
13444
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13412
- if (flatDataX.length === 0) {
13413
- throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13414
- }
13415
- if (flatDataX.length < 2) {
13416
- throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
13445
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13446
+ return new NotAvailableError(noValidInputErrorMessage);
13417
13447
  }
13418
13448
  const n = flatDataX.length;
13419
13449
  let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
@@ -13503,6 +13533,9 @@ const POLYFIT_COEFFS = {
13503
13533
  ],
13504
13534
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13505
13535
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13536
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13537
+ return new NotAvailableError(noValidInputErrorMessage);
13538
+ }
13506
13539
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
13507
13540
  },
13508
13541
  isExported: false,
@@ -13522,6 +13555,9 @@ const POLYFIT_FORECAST = {
13522
13555
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13523
13556
  const _order = toNumber(order, this.locale);
13524
13557
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13558
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13559
+ return new NotAvailableError(noValidInputErrorMessage);
13560
+ }
13525
13561
  const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
13526
13562
  return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
13527
13563
  },
@@ -13623,7 +13659,11 @@ const RSQ = {
13623
13659
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13624
13660
  ],
13625
13661
  compute: function (dataY, dataX) {
13626
- return Math.pow(pearson(dataX, dataY), 2.0);
13662
+ const value = pearson(dataY, dataX);
13663
+ if (value instanceof Error) {
13664
+ throw value;
13665
+ }
13666
+ return Math.pow(value, 2.0);
13627
13667
  },
13628
13668
  isExported: true,
13629
13669
  };
@@ -13638,6 +13678,9 @@ const SLOPE = {
13638
13678
  ],
13639
13679
  compute: function (dataY, dataX) {
13640
13680
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13681
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13682
+ return new NotAvailableError(noValidInputErrorMessage);
13683
+ }
13641
13684
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
13642
13685
  return slope;
13643
13686
  },
@@ -13670,7 +13713,7 @@ const SMALL = {
13670
13713
  });
13671
13714
  const result = largests.pop();
13672
13715
  if (result === undefined) {
13673
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
13716
+ return new EvaluationError(noValidInputErrorMessage);
13674
13717
  }
13675
13718
  if (count < _n) {
13676
13719
  return new EvaluationError(_t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
@@ -13690,6 +13733,9 @@ const SPEARMAN = {
13690
13733
  ],
13691
13734
  compute: function (dataX, dataY) {
13692
13735
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13736
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13737
+ return new NotAvailableError(noValidInputErrorMessage);
13738
+ }
13693
13739
  const n = flatDataX.length;
13694
13740
  const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
13695
13741
  order.sort((a, b) => a[0] - b[0]);
@@ -13800,6 +13846,9 @@ const STEYX = {
13800
13846
  ],
13801
13847
  compute: function (dataY, dataX) {
13802
13848
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13849
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13850
+ return new NotAvailableError(noValidInputErrorMessage);
13851
+ }
13803
13852
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
13804
13853
  return data[1][2];
13805
13854
  },
@@ -13817,6 +13866,9 @@ const TREND = {
13817
13866
  arg("b (boolean, optional, default=TRUE)", _t("Given a general linear form of y = m*x+b for a curve fit, calculates b if TRUE or forces b to be 0 and only calculates the m values if FALSE, i.e. forces the curve fit to pass through the origin.")),
13818
13867
  ],
13819
13868
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13869
+ if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13870
+ return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13871
+ }
13820
13872
  return predictLinearValues(toNumberMatrix(knownDataY, "the first argument (known_data_y)"), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b));
13821
13873
  },
13822
13874
  };
@@ -18732,7 +18784,7 @@ const AND = {
18732
18784
  compute: function (...logicalExpressions) {
18733
18785
  const { result, foundBoolean } = boolAnd(logicalExpressions);
18734
18786
  if (!foundBoolean) {
18735
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18787
+ return new EvaluationError(noValidInputErrorMessage);
18736
18788
  }
18737
18789
  return result;
18738
18790
  },
@@ -18858,7 +18910,7 @@ const OR = {
18858
18910
  compute: function (...logicalExpressions) {
18859
18911
  const { result, foundBoolean } = boolOr(logicalExpressions);
18860
18912
  if (!foundBoolean) {
18861
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18913
+ return new EvaluationError(noValidInputErrorMessage);
18862
18914
  }
18863
18915
  return result;
18864
18916
  },
@@ -18921,7 +18973,7 @@ const XOR = {
18921
18973
  return true; // no stop condition
18922
18974
  });
18923
18975
  if (!foundBoolean) {
18924
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18976
+ return new EvaluationError(noValidInputErrorMessage);
18925
18977
  }
18926
18978
  return acc;
18927
18979
  },
@@ -21385,7 +21437,7 @@ function adaptFormulaStringRanges(defaultSheetId, formula, applyChange) {
21385
21437
  function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
21386
21438
  const sheetName = splitReference(sheetXC).sheetName;
21387
21439
  if (sheetName
21388
- ? !isSheetNameEqual(sheetName, applyChange.sheetName)
21440
+ ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
21389
21441
  : defaultSheetId !== applyChange.sheetId) {
21390
21442
  return sheetXC;
21391
21443
  }
@@ -21402,7 +21454,7 @@ function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
21402
21454
  }
21403
21455
  function getSheetNameGetter(applyChange) {
21404
21456
  return (sheetId) => {
21405
- return sheetId === applyChange.sheetId ? applyChange.sheetName : "";
21457
+ return sheetId === applyChange.sheetId ? applyChange.sheetName.current : "";
21406
21458
  };
21407
21459
  }
21408
21460
  function defaultGetSheetSize(sheetId) {
@@ -27393,9 +27445,13 @@ class GaugeChart extends AbstractChart {
27393
27445
  : undefined,
27394
27446
  };
27395
27447
  }
27396
- updateRanges(applyChange) {
27448
+ updateRanges(applyChange, sheetId, adaptSheetName) {
27397
27449
  const dataRange = adaptChartRange(this.dataRange, applyChange);
27398
- const adaptFormula = (formula) => this.getters.adaptFormulaStringDependencies(this.sheetId, formula, applyChange);
27450
+ const adaptFormula = (formula) => adaptFormulaStringRanges(this.sheetId, formula, {
27451
+ applyChange,
27452
+ sheetId,
27453
+ sheetName: adaptSheetName,
27454
+ });
27399
27455
  const sectionRule = adaptSectionRuleFormulas(this.sectionRule, adaptFormula);
27400
27456
  const definition = this.getDefinitionWithSpecificRanges(dataRange, sectionRule);
27401
27457
  return new GaugeChart(definition, this.sheetId, this.getters);
@@ -33718,6 +33774,9 @@ class Composer extends Component {
33718
33774
  this.contentHelper.removeSelection();
33719
33775
  }
33720
33776
  onMouseup() {
33777
+ if (this.env.model.getters.isReadonly()) {
33778
+ return;
33779
+ }
33721
33780
  const selection = this.contentHelper.getCurrentSelection();
33722
33781
  if (selection.start !== selection.end) {
33723
33782
  this.props.composerStore.hoverToken(undefined);
@@ -38181,9 +38240,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
38181
38240
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
38182
38241
  continue;
38183
38242
  operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
38184
- values.push(rule.formula[0]);
38243
+ values.push(prefixFormula(rule.formula[0]));
38185
38244
  if (rule.formula.length === 2) {
38186
- values.push(rule.formula[1]);
38245
+ values.push(prefixFormula(rule.formula[1]));
38187
38246
  }
38188
38247
  break;
38189
38248
  }
@@ -38341,6 +38400,11 @@ function convertIcons(xlsxIconSet, index) {
38341
38400
  ? ICON_SETS[iconSet].neutral
38342
38401
  : ICON_SETS[iconSet].good;
38343
38402
  }
38403
+ /** Prefix the string by "=" if the string looks like a formula */
38404
+ function prefixFormula(formula) {
38405
+ const tokens = tokenize(formula);
38406
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
38407
+ }
38344
38408
  // ---------------------------------------------------------------------------
38345
38409
  // Warnings
38346
38410
  // ---------------------------------------------------------------------------
@@ -38623,7 +38687,7 @@ function getColPosition(colIndex, sheetData) {
38623
38687
  function getRowPosition(rowIndex, sheetData) {
38624
38688
  let position = 0;
38625
38689
  for (let i = 0; i < rowIndex; i++) {
38626
- const rowAtIndex = sheetData.rows[i];
38690
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
38627
38691
  if (rowAtIndex?.height) {
38628
38692
  position += rowAtIndex.height;
38629
38693
  }
@@ -38778,8 +38842,8 @@ function convertExcelTrendline(trend) {
38778
38842
  }
38779
38843
  function convertAnchor(XLSXanchor) {
38780
38844
  const offset = {
38781
- x: convertEMUToDotValue(XLSXanchor.colOffset),
38782
- y: convertEMUToDotValue(XLSXanchor.rowOffset),
38845
+ x: convertEMUToDotValue(XLSXanchor.colOffset) - FIGURE_BORDER_WIDTH,
38846
+ y: convertEMUToDotValue(XLSXanchor.rowOffset) - FIGURE_BORDER_WIDTH,
38783
38847
  };
38784
38848
  return { col: XLSXanchor.col, row: XLSXanchor.row, offset };
38785
38849
  }
@@ -39162,8 +39226,12 @@ function getSheetDims(sheet) {
39162
39226
  dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
39163
39227
  dims[1] = Math.max(dims[1], row.index);
39164
39228
  }
39165
- dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
39166
- dims[1] = Math.max(dims[1], EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
39229
+ for (const fig of sheet.figures) {
39230
+ dims[0] = Math.max(dims[0], fig.anchors[fig.anchors.length - 1]?.col ?? 0);
39231
+ dims[1] = Math.max(dims[1], fig.anchors[fig.anchors.length - 1]?.row ?? 0);
39232
+ }
39233
+ dims[0] = Math.max(dims[0] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
39234
+ dims[1] = Math.max(dims[1] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
39167
39235
  return dims;
39168
39236
  }
39169
39237
  /**
@@ -40866,7 +40934,7 @@ function getRelationFile(file, xmls) {
40866
40934
  return relsFile;
40867
40935
  }
40868
40936
 
40869
- const EXCEL_IMPORT_VERSION = "18.4.1";
40937
+ const EXCEL_IMPORT_VERSION = "18.4.2";
40870
40938
  class XlsxReader {
40871
40939
  warningManager;
40872
40940
  xmls;
@@ -44411,7 +44479,7 @@ const splitToColumns = {
44411
44479
  const reinsertDynamicPivotMenu = {
44412
44480
  id: "reinsert_dynamic_pivot",
44413
44481
  name: _t("Re-insert dynamic pivot"),
44414
- sequence: 1020,
44482
+ sequence: 60,
44415
44483
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
44416
44484
  children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
44417
44485
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -44419,7 +44487,7 @@ const reinsertDynamicPivotMenu = {
44419
44487
  const reinsertStaticPivotMenu = {
44420
44488
  id: "reinsert_static_pivot",
44421
44489
  name: _t("Re-insert static pivot"),
44422
- sequence: 1020,
44490
+ sequence: 70,
44423
44491
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
44424
44492
  children: [REINSERT_STATIC_PIVOT_CHILDREN],
44425
44493
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -58690,7 +58758,8 @@ class CorePlugin extends BasePlugin {
58690
58758
  * the type of change that occurred.
58691
58759
  *
58692
58760
  * @param applyChange a function that, when called, will adapt the range according to the change on the grid
58693
- * @param sheetId an optional sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
58761
+ * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
58762
+ * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
58694
58763
  */
58695
58764
  adaptRanges(applyChange, sheetId, sheetName) { }
58696
58765
  /**
@@ -59293,9 +59362,7 @@ class CellPlugin extends CorePlugin {
59293
59362
  for (const cell of Object.values(this.cells[sheet] || {})) {
59294
59363
  if (cell.isFormula) {
59295
59364
  for (const range of cell.compiledFormula.dependencies) {
59296
- if (!sheetId ||
59297
- range.sheetId === sheetId ||
59298
- (sheetName && range.invalidSheetName === sheetName)) {
59365
+ if (range.sheetId === sheetId || range.invalidSheetName === sheetName.old) {
59299
59366
  const change = applyChange(range);
59300
59367
  if (change.changeType !== "NONE") {
59301
59368
  this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
@@ -59911,9 +59978,9 @@ class ChartPlugin extends CorePlugin {
59911
59978
  charts = {};
59912
59979
  createChart = chartFactory(this.getters);
59913
59980
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
59914
- adaptRanges(applyChange) {
59981
+ adaptRanges(applyChange, sheetId, adaptSheetName) {
59915
59982
  for (const [chartId, chart] of Object.entries(this.charts)) {
59916
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
59983
+ this.history.update("charts", chartId, chart?.updateRanges(applyChange, sheetId, adaptSheetName));
59917
59984
  }
59918
59985
  }
59919
59986
  // ---------------------------------------------------------------------------
@@ -60176,7 +60243,7 @@ class ConditionalFormatPlugin extends CorePlugin {
60176
60243
  }
60177
60244
  }
60178
60245
  }
60179
- adaptRanges(applyChange, sheetId, sheetName) {
60246
+ adaptRanges(applyChange, sheetId) {
60180
60247
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
60181
60248
  for (const sheetId of sheetIds) {
60182
60249
  this.adaptCFRanges(sheetId, applyChange);
@@ -60558,11 +60625,8 @@ class DataValidationPlugin extends CorePlugin {
60558
60625
  "getValidationRuleForCell",
60559
60626
  ];
60560
60627
  rules = {};
60561
- adaptRanges(applyChange, sheetId, sheetName) {
60562
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.rules);
60563
- for (const sheetId of sheetIds) {
60564
- this.adaptDVRanges(sheetId, applyChange);
60565
- }
60628
+ adaptRanges(applyChange, sheetId) {
60629
+ this.adaptDVRanges(sheetId, applyChange);
60566
60630
  this.adaptDVFormulas(applyChange);
60567
60631
  }
60568
60632
  adaptDVFormulas(applyChange) {
@@ -60852,9 +60916,6 @@ class FigurePlugin extends CorePlugin {
60852
60916
  // Command Handling
60853
60917
  // ---------------------------------------------------------------------------
60854
60918
  adaptRanges(applyChange, sheetId) {
60855
- if (!sheetId) {
60856
- return;
60857
- }
60858
60919
  for (const figure of this.getFigures(sheetId)) {
60859
60920
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
60860
60921
  left: figure.col,
@@ -61663,11 +61724,8 @@ class MergePlugin extends CorePlugin {
61663
61724
  break;
61664
61725
  }
61665
61726
  }
61666
- adaptRanges(applyChange, sheetId, sheetName) {
61667
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.merges);
61668
- for (const sheetId of sheetIds) {
61669
- this.applyRangeChangeOnSheet(sheetId, applyChange);
61670
- }
61727
+ adaptRanges(applyChange, sheetId) {
61728
+ this.applyRangeChangeOnSheet(sheetId, applyChange);
61671
61729
  }
61672
61730
  // ---------------------------------------------------------------------------
61673
61731
  // Getters
@@ -63172,12 +63230,9 @@ class TablePlugin extends CorePlugin {
63172
63230
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
63173
63231
  tables = {};
63174
63232
  nextTableId = 1;
63175
- adaptRanges(applyChange, sheetId, sheetName) {
63176
- const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
63177
- for (const sheetId of sheetIds) {
63178
- for (const table of this.getCoreTables(sheetId)) {
63179
- this.applyRangeChangeOnTable(sheetId, table, applyChange);
63180
- }
63233
+ adaptRanges(applyChange, sheetId) {
63234
+ for (const table of this.getCoreTables(sheetId)) {
63235
+ this.applyRangeChangeOnTable(sheetId, table, applyChange);
63181
63236
  }
63182
63237
  }
63183
63238
  allowDispatch(cmd) {
@@ -64140,7 +64195,7 @@ class PivotCorePlugin extends CorePlugin {
64140
64195
  }
64141
64196
  }
64142
64197
  }
64143
- adaptRanges(applyChange, sheetId, sheetName) {
64198
+ adaptRanges(applyChange) {
64144
64199
  for (const sheetId in this.compiledMeasureFormulas) {
64145
64200
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64146
64201
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -68541,7 +68596,7 @@ class PivotUIPlugin extends CoreViewPlugin {
68541
68596
  if (!result) {
68542
68597
  return EMPTY_PIVOT_CELL;
68543
68598
  }
68544
- const { functionName, args } = result;
68599
+ let { functionName, args } = result;
68545
68600
  const formulaId = args[0];
68546
68601
  if (!formulaId) {
68547
68602
  return EMPTY_PIVOT_CELL;
@@ -68576,6 +68631,9 @@ class PivotUIPlugin extends CoreViewPlugin {
68576
68631
  return pivotCells[pivotCol][pivotRow];
68577
68632
  }
68578
68633
  try {
68634
+ const offsetRow = position.row - mainPosition.row;
68635
+ const offsetCol = position.col - mainPosition.col;
68636
+ args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
68579
68637
  if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
68580
68638
  const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
68581
68639
  return {
@@ -70184,7 +70242,8 @@ function transformAll(toTransform, executed) {
70184
70242
  // If the executed command is not in the registry, we skip it
70185
70243
  // because we know there won't be any transformation impacting the
70186
70244
  // commands to transform.
70187
- if (possibleTransformations.has(executedCommand.type)) {
70245
+ if (possibleTransformations.has(executedCommand.type) ||
70246
+ rangeAdapterRegistry.contains(executedCommand.type)) {
70188
70247
  transformedCommands = transformedCommands.reduce((acc, cmd) => {
70189
70248
  const transformed = transform(cmd, executedCommand);
70190
70249
  if (transformed) {
@@ -76176,7 +76235,8 @@ const inverseCommandRegistry = new Registry()
76176
76235
  .add("HIDE_COLUMNS_ROWS", inverseHideColumnsRows)
76177
76236
  .add("UNHIDE_COLUMNS_ROWS", inverseUnhideColumnsRows)
76178
76237
  .add("CREATE_TABLE_STYLE", inverseCreateTableStyle)
76179
- .add("ADD_PIVOT", inverseAddPivot);
76238
+ .add("ADD_PIVOT", inverseAddPivot)
76239
+ .add("RENAME_SHEET", inverseRenameSheet);
76180
76240
  for (const cmd of coreTypes.values()) {
76181
76241
  if (!inverseCommandRegistry.contains(cmd)) {
76182
76242
  inverseCommandRegistry.add(cmd, identity);
@@ -76274,6 +76334,16 @@ function inverseUnhideColumnsRows(cmd) {
76274
76334
  function inverseCreateTableStyle(cmd) {
76275
76335
  return [{ type: "REMOVE_TABLE_STYLE", tableStyleId: cmd.tableStyleId }];
76276
76336
  }
76337
+ function inverseRenameSheet(cmd) {
76338
+ return [
76339
+ {
76340
+ type: "RENAME_SHEET",
76341
+ sheetId: cmd.sheetId,
76342
+ oldName: cmd.newName,
76343
+ newName: cmd.oldName,
76344
+ },
76345
+ ];
76346
+ }
76277
76347
 
76278
76348
  const numberFormatMenuRegistry = new Registry();
76279
76349
  numberFormatMenuRegistry
@@ -76872,8 +76942,9 @@ topbarMenuRegistry
76872
76942
  sequence: 40,
76873
76943
  separator: true,
76874
76944
  })
76875
- .addChild("data_sources_data", ["data"], (env) => {
76945
+ .addChild("pivot_data_sources", ["data"], (env) => {
76876
76946
  const sequence = 50;
76947
+ const numberOfPivots = env.model.getters.getPivotIds().length;
76877
76948
  return env.model.getters.getPivotIds().map((pivotId, index) => {
76878
76949
  const highlightProvider = {
76879
76950
  get highlights() {
@@ -76883,7 +76954,7 @@ topbarMenuRegistry
76883
76954
  return {
76884
76955
  id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
76885
76956
  name: env.model.getters.getPivotDisplayName(pivotId),
76886
- sequence: sequence + index,
76957
+ sequence: sequence + index / numberOfPivots,
76887
76958
  isReadonlyAllowed: true,
76888
76959
  execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
76889
76960
  isEnabled: (env) => !env.isSmall,
@@ -83003,7 +83074,7 @@ function figureCoordinates(headers, anchor, offset) {
83003
83074
  for (const [headerIndex, header] of headers.slice(anchor).entries()) {
83004
83075
  if (currentPosition <= offset && offset < currentPosition + header.size) {
83005
83076
  return {
83006
- index: headerIndex,
83077
+ index: anchor + headerIndex,
83007
83078
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
83008
83079
  };
83009
83080
  }
@@ -83999,7 +84070,7 @@ class Model extends EventBus {
83999
84070
  handlers = [];
84000
84071
  uiHandlers = [];
84001
84072
  coreHandlers = [];
84002
- constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
84073
+ constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
84003
84074
  const start = performance.now();
84004
84075
  console.debug("##### Model creation #####");
84005
84076
  super();
@@ -84701,6 +84772,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
84701
84772
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
84702
84773
 
84703
84774
 
84704
- __info__.version = "18.4.8";
84705
- __info__.date = "2025-08-26T10:14:08.954Z";
84706
- __info__.hash = "746217a";
84775
+ __info__.version = "18.4.9";
84776
+ __info__.date = "2025-09-05T07:38:32.126Z";
84777
+ __info__.hash = "a261873";