@odoo/o-spreadsheet 18.3.18 → 18.3.20

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.3.18
6
- * @date 2025-08-26T10:14:21.408Z
7
- * @hash ec2777d
5
+ * @version 18.3.20
6
+ * @date 2025-09-11T08:45:37.934Z
7
+ * @hash ef829f4
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -3498,6 +3498,7 @@
3498
3498
  "AUTOFILL_CELL",
3499
3499
  "SET_BORDER",
3500
3500
  "SET_ZONE_BORDERS",
3501
+ "SET_BORDERS_ON_TARGET",
3501
3502
  ]);
3502
3503
  const readonlyAllowedCommands = new Set([
3503
3504
  "START",
@@ -6443,40 +6444,44 @@
6443
6444
  };
6444
6445
  }
6445
6446
  function getRangeAdapter(cmd) {
6446
- switch (cmd.type) {
6447
- case "REMOVE_COLUMNS_ROWS":
6448
- return {
6449
- applyChange: getApplyRangeChangeRemoveColRow(cmd),
6450
- sheetId: cmd.sheetId,
6451
- sheetName: cmd.sheetName,
6452
- };
6453
- case "ADD_COLUMNS_ROWS":
6454
- return {
6455
- applyChange: getApplyRangeChangeAddColRow(cmd),
6456
- sheetId: cmd.sheetId,
6457
- sheetName: cmd.sheetName,
6458
- };
6459
- case "DELETE_SHEET":
6460
- return {
6461
- applyChange: getApplyRangeChangeDeleteSheet(cmd),
6462
- sheetId: cmd.sheetId,
6463
- sheetName: cmd.sheetName,
6464
- };
6465
- case "RENAME_SHEET":
6466
- return {
6467
- applyChange: getApplyRangeChangeRenameSheet(cmd),
6468
- sheetId: cmd.sheetId,
6469
- sheetName: cmd.oldName,
6470
- };
6471
- case "MOVE_RANGES":
6472
- return {
6473
- applyChange: getApplyRangeChangeMoveRange(cmd),
6474
- sheetId: cmd.sheetId,
6475
- sheetName: cmd.sheetName,
6476
- };
6447
+ return rangeAdapterRegistry.get(cmd.type)?.(cmd);
6448
+ }
6449
+ class RangeAdapterRegistry extends Registry {
6450
+ add(cmdType, fn) {
6451
+ super.add(cmdType, fn);
6452
+ return this;
6453
+ }
6454
+ get(cmdType) {
6455
+ return this.content[cmdType];
6477
6456
  }
6478
- return undefined;
6479
6457
  }
6458
+ const rangeAdapterRegistry = new RangeAdapterRegistry();
6459
+ rangeAdapterRegistry
6460
+ .add("REMOVE_COLUMNS_ROWS", (cmd) => ({
6461
+ applyChange: getApplyRangeChangeRemoveColRow(cmd),
6462
+ sheetId: cmd.sheetId,
6463
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6464
+ }))
6465
+ .add("ADD_COLUMNS_ROWS", (cmd) => ({
6466
+ applyChange: getApplyRangeChangeAddColRow(cmd),
6467
+ sheetId: cmd.sheetId,
6468
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6469
+ }))
6470
+ .add("DELETE_SHEET", (cmd) => ({
6471
+ applyChange: getApplyRangeChangeDeleteSheet(cmd),
6472
+ sheetId: cmd.sheetId,
6473
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6474
+ }))
6475
+ .add("RENAME_SHEET", (cmd) => ({
6476
+ applyChange: getApplyRangeChangeRenameSheet(cmd),
6477
+ sheetId: cmd.sheetId,
6478
+ sheetName: { old: cmd.oldName, current: cmd.newName },
6479
+ }))
6480
+ .add("MOVE_RANGES", (cmd) => ({
6481
+ applyChange: getApplyRangeChangeMoveRange(cmd),
6482
+ sheetId: cmd.sheetId,
6483
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6484
+ }));
6480
6485
  function getApplyRangeChangeRemoveColRow(cmd) {
6481
6486
  let start = cmd.dimension === "COL" ? "left" : "top";
6482
6487
  let end = cmd.dimension === "COL" ? "right" : "bottom";
@@ -7203,7 +7208,7 @@
7203
7208
  this.getters = getters;
7204
7209
  this.dispatch = dispatch;
7205
7210
  }
7206
- copy(data, isCutOperation) {
7211
+ copy(data, isCutOperation, mode = "copyPaste") {
7207
7212
  return;
7208
7213
  }
7209
7214
  paste(target, clippedContent, options) { }
@@ -7222,7 +7227,7 @@
7222
7227
  }
7223
7228
 
7224
7229
  class AbstractCellClipboardHandler extends ClipboardHandler {
7225
- copy(data) {
7230
+ copy(data, isCutOperation, mode = "copyPaste") {
7226
7231
  return;
7227
7232
  }
7228
7233
  pasteFromCopy(sheetId, target, content, options) {
@@ -7827,8 +7832,11 @@
7827
7832
  // (a) Swap 2 rows. This multiply the determinant by -1.
7828
7833
  // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
7829
7834
  // (c) Add to a row a multiple of another row. This does not change the determinant.
7835
+ if (M.length < 1 || M[0].length < 1) {
7836
+ throw new Error("invertMatrix: an empty matrix cannot be inverted.");
7837
+ }
7830
7838
  if (M.length !== M[0].length) {
7831
- throw new EvaluationError(_t("Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible"));
7839
+ throw new Error("invertMatrix: only square matrices are invertible");
7832
7840
  }
7833
7841
  let determinant = 1;
7834
7842
  const dim = M.length;
@@ -7897,8 +7905,11 @@
7897
7905
  * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
7898
7906
  */
7899
7907
  function multiplyMatrices(matrix1, matrix2) {
7908
+ if (matrix1.length < 1 || matrix2.length < 1) {
7909
+ throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
7910
+ }
7900
7911
  if (matrix1.length !== matrix2[0].length) {
7901
- throw new EvaluationError(_t("Cannot multiply matrices : incompatible matrices size."));
7912
+ throw new Error("multiplyMatrices: incompatible matrices size.");
7902
7913
  }
7903
7914
  const rowsM1 = matrix1[0].length;
7904
7915
  const colsM2 = matrix2.length;
@@ -7924,7 +7935,7 @@
7924
7935
  return arg;
7925
7936
  }
7926
7937
  if (!isSingleElementMatrix(arg)) {
7927
- throw new EvaluationError(_t("The value should be a scalar or a 1x1 matrix"));
7938
+ throw new Error("The value should be a scalar or a 1x1 matrix");
7928
7939
  }
7929
7940
  return arg[0][0];
7930
7941
  }
@@ -8161,6 +8172,16 @@
8161
8172
  }
8162
8173
  return values;
8163
8174
  }
8175
+ function assertNonEmptyMatrix(matrix, argName) {
8176
+ assert(() => matrix.length > 0 && matrix[0].length > 0, _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", {
8177
+ argName,
8178
+ }));
8179
+ }
8180
+ function assertNonEmpty(...data) {
8181
+ if (data.length === 0 || data.some((arg) => arg.length === 0)) {
8182
+ throw new NotAvailableError(_t("[[FUNCTION_NAME]] has no valid input data."));
8183
+ }
8184
+ }
8164
8185
 
8165
8186
  const PREVIOUS_VALUE = "(previous)";
8166
8187
  const NEXT_VALUE = "(next)";
@@ -8929,7 +8950,7 @@
8929
8950
  }
8930
8951
  return "Success" /* CommandResult.Success */;
8931
8952
  }
8932
- copy(data) {
8953
+ copy(data, isCutOperation, mode = "copyPaste") {
8933
8954
  const sheetId = data.sheetId;
8934
8955
  const { clippedZones, rowsIndexes, columnsIndexes } = data;
8935
8956
  const clippedCells = [];
@@ -8942,7 +8963,7 @@
8942
8963
  const evaluatedCell = this.getters.getEvaluatedCell(position);
8943
8964
  const pivotId = this.getters.getPivotIdFromPosition(position);
8944
8965
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
8945
- if (pivotId && spreader) {
8966
+ if (mode !== "shiftCells" && pivotId && spreader) {
8946
8967
  const pivotZone = this.getters.getSpreadZone(spreader);
8947
8968
  if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
8948
8969
  pivotZone &&
@@ -8960,7 +8981,7 @@
8960
8981
  };
8961
8982
  }
8962
8983
  }
8963
- else {
8984
+ else if (mode !== "shiftCells") {
8964
8985
  if (spreader && !deepEquals(spreader, position)) {
8965
8986
  const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
8966
8987
  const content = isSpreaderCopied
@@ -9660,7 +9681,7 @@
9660
9681
  }
9661
9682
 
9662
9683
  class TableClipboardHandler extends AbstractCellClipboardHandler {
9663
- copy(data, isCutOperation) {
9684
+ copy(data, isCutOperation, mode = "copyPaste") {
9664
9685
  const sheetId = data.sheetId;
9665
9686
  const { rowsIndexes, columnsIndexes, zones } = data;
9666
9687
  const copiedTablesIds = new Set();
@@ -9698,11 +9719,13 @@
9698
9719
  type: coreTable.type,
9699
9720
  };
9700
9721
  }
9701
- tableCellsInRow.push({
9702
- table: copiedTable,
9703
- style: this.getTableStyleToCopy(position),
9704
- isWholeTableCopied: copiedTablesIds.has(table.id),
9705
- });
9722
+ if (mode !== "shiftCells") {
9723
+ tableCellsInRow.push({
9724
+ table: copiedTable,
9725
+ style: this.getTableStyleToCopy(position),
9726
+ isWholeTableCopied: copiedTablesIds.has(table.id),
9727
+ });
9728
+ }
9706
9729
  }
9707
9730
  }
9708
9731
  return {
@@ -10984,6 +11007,7 @@ stores.inject(MyMetaStore, storeInstance);
10984
11007
  compute: function (matrix1, matrix2) {
10985
11008
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
10986
11009
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
11010
+ assert(() => _matrix1.length > 0 && _matrix2.length > 0, _t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
10987
11011
  assert(() => _matrix1.length === _matrix2[0].length, _t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
10988
11012
  number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
10989
11013
  return multiplyMatrices(_matrix1, _matrix2);
@@ -12779,6 +12803,7 @@ stores.inject(MyMetaStore, storeInstance);
12779
12803
  ],
12780
12804
  compute: function (x, dataY, dataX) {
12781
12805
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
12806
+ assertNonEmpty(flatDataX, flatDataY);
12782
12807
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
12783
12808
  },
12784
12809
  isExported: true,
@@ -12795,6 +12820,7 @@ stores.inject(MyMetaStore, storeInstance);
12795
12820
  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.")),
12796
12821
  ],
12797
12822
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
12823
+ assertNonEmptyMatrix(knownDataY, "known_data_y");
12798
12824
  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)));
12799
12825
  },
12800
12826
  };
@@ -12809,6 +12835,7 @@ stores.inject(MyMetaStore, storeInstance);
12809
12835
  ],
12810
12836
  compute: function (dataY, dataX) {
12811
12837
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
12838
+ assertNonEmpty(flatDataX, flatDataY);
12812
12839
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
12813
12840
  return intercept;
12814
12841
  },
@@ -12858,6 +12885,7 @@ stores.inject(MyMetaStore, storeInstance);
12858
12885
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
12859
12886
  ],
12860
12887
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12888
+ assertNonEmptyMatrix(dataY, "data_y");
12861
12889
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
12862
12890
  },
12863
12891
  isExported: true,
@@ -12874,6 +12902,7 @@ stores.inject(MyMetaStore, storeInstance);
12874
12902
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
12875
12903
  ],
12876
12904
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12905
+ assertNonEmptyMatrix(dataY, "data_y");
12877
12906
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
12878
12907
  for (let i = 0; i < coeffs.length; i++) {
12879
12908
  coeffs[i][0] = Math.exp(coeffs[i][0]);
@@ -12895,9 +12924,7 @@ stores.inject(MyMetaStore, storeInstance);
12895
12924
  const flatX = dataX.flat();
12896
12925
  const flatY = dataY.flat();
12897
12926
  assertSameNumberOfElements(flatX, flatY);
12898
- if (flatX.length === 0) {
12899
- return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
12900
- }
12927
+ assertNonEmpty(flatX, flatY);
12901
12928
  const n = flatX.length;
12902
12929
  let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
12903
12930
  for (let i = 0; i < n; ++i) {
@@ -13061,12 +13088,7 @@ stores.inject(MyMetaStore, storeInstance);
13061
13088
  // -----------------------------------------------------------------------------
13062
13089
  function pearson(dataY, dataX) {
13063
13090
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13064
- if (flatDataX.length === 0) {
13065
- throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13066
- }
13067
- if (flatDataX.length < 2) {
13068
- throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
13069
- }
13091
+ assertNonEmpty(flatDataX, flatDataY);
13070
13092
  const n = flatDataX.length;
13071
13093
  let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
13072
13094
  for (let i = 0; i < n; i++) {
@@ -13155,6 +13177,7 @@ stores.inject(MyMetaStore, storeInstance);
13155
13177
  ],
13156
13178
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13157
13179
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13180
+ assertNonEmpty(flatDataX, flatDataY);
13158
13181
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
13159
13182
  },
13160
13183
  isExported: false,
@@ -13174,6 +13197,7 @@ stores.inject(MyMetaStore, storeInstance);
13174
13197
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13175
13198
  const _order = toNumber(order, this.locale);
13176
13199
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13200
+ assertNonEmpty(flatDataX, flatDataY);
13177
13201
  const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
13178
13202
  return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
13179
13203
  },
@@ -13290,6 +13314,7 @@ stores.inject(MyMetaStore, storeInstance);
13290
13314
  ],
13291
13315
  compute: function (dataY, dataX) {
13292
13316
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13317
+ assertNonEmpty(flatDataX, flatDataY);
13293
13318
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
13294
13319
  return slope;
13295
13320
  },
@@ -13338,6 +13363,7 @@ stores.inject(MyMetaStore, storeInstance);
13338
13363
  ],
13339
13364
  compute: function (dataX, dataY) {
13340
13365
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13366
+ assertNonEmpty(flatDataX, flatDataY);
13341
13367
  const n = flatDataX.length;
13342
13368
  const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
13343
13369
  order.sort((a, b) => a[0] - b[0]);
@@ -13448,6 +13474,7 @@ stores.inject(MyMetaStore, storeInstance);
13448
13474
  ],
13449
13475
  compute: function (dataY, dataX) {
13450
13476
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13477
+ assertNonEmpty(flatDataX, flatDataY);
13451
13478
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
13452
13479
  return data[1][2];
13453
13480
  },
@@ -13465,6 +13492,7 @@ stores.inject(MyMetaStore, storeInstance);
13465
13492
  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.")),
13466
13493
  ],
13467
13494
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13495
+ assertNonEmptyMatrix(knownDataY, "known_data_y");
13468
13496
  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));
13469
13497
  },
13470
13498
  };
@@ -20601,7 +20629,7 @@ stores.inject(MyMetaStore, storeInstance);
20601
20629
  function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20602
20630
  const sheetName = splitReference(sheetXC).sheetName;
20603
20631
  if (sheetName
20604
- ? !isSheetNameEqual(sheetName, applyChange.sheetName)
20632
+ ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
20605
20633
  : defaultSheetId !== applyChange.sheetId) {
20606
20634
  return sheetXC;
20607
20635
  }
@@ -20618,7 +20646,7 @@ stores.inject(MyMetaStore, storeInstance);
20618
20646
  }
20619
20647
  function getSheetNameGetter(applyChange) {
20620
20648
  return (sheetId) => {
20621
- return sheetId === applyChange.sheetId ? applyChange.sheetName : "";
20649
+ return sheetId === applyChange.sheetId ? applyChange.sheetName.current : "";
20622
20650
  };
20623
20651
  }
20624
20652
  function defaultGetSheetSize(sheetId) {
@@ -27581,9 +27609,13 @@ stores.inject(MyMetaStore, storeInstance);
27581
27609
  : undefined,
27582
27610
  };
27583
27611
  }
27584
- updateRanges(applyChange) {
27612
+ updateRanges(applyChange, sheetId, adaptSheetName) {
27585
27613
  const dataRange = adaptChartRange(this.dataRange, applyChange);
27586
- const adaptFormula = (formula) => this.getters.adaptFormulaStringDependencies(this.sheetId, formula, applyChange);
27614
+ const adaptFormula = (formula) => adaptFormulaStringRanges(this.sheetId, formula, {
27615
+ applyChange,
27616
+ sheetId,
27617
+ sheetName: adaptSheetName,
27618
+ });
27587
27619
  const sectionRule = adaptSectionRuleFormulas(this.sectionRule, adaptFormula);
27588
27620
  const definition = this.getDefinitionWithSpecificRanges(dataRange, sectionRule);
27589
27621
  return new GaugeChart(definition, this.sheetId, this.getters);
@@ -30210,7 +30242,8 @@ stores.inject(MyMetaStore, storeInstance);
30210
30242
  .add("HIDE_COLUMNS_ROWS", inverseHideColumnsRows)
30211
30243
  .add("UNHIDE_COLUMNS_ROWS", inverseUnhideColumnsRows)
30212
30244
  .add("CREATE_TABLE_STYLE", inverseCreateTableStyle)
30213
- .add("ADD_PIVOT", inverseAddPivot);
30245
+ .add("ADD_PIVOT", inverseAddPivot)
30246
+ .add("RENAME_SHEET", inverseRenameSheet);
30214
30247
  for (const cmd of coreTypes.values()) {
30215
30248
  if (!inverseCommandRegistry.contains(cmd)) {
30216
30249
  inverseCommandRegistry.add(cmd, identity);
@@ -30308,6 +30341,16 @@ stores.inject(MyMetaStore, storeInstance);
30308
30341
  function inverseCreateTableStyle(cmd) {
30309
30342
  return [{ type: "REMOVE_TABLE_STYLE", tableStyleId: cmd.tableStyleId }];
30310
30343
  }
30344
+ function inverseRenameSheet(cmd) {
30345
+ return [
30346
+ {
30347
+ type: "RENAME_SHEET",
30348
+ sheetId: cmd.sheetId,
30349
+ oldName: cmd.newName,
30350
+ newName: cmd.oldName,
30351
+ },
30352
+ ];
30353
+ }
30311
30354
 
30312
30355
  /**
30313
30356
  * The class Registry is extended in order to add the function addChild
@@ -30844,7 +30887,7 @@ stores.inject(MyMetaStore, storeInstance);
30844
30887
  ];
30845
30888
  const SUPPORTED_VERTICAL_ALIGNMENTS = ["top", "center", "bottom"];
30846
30889
  const SUPPORTED_FONTS = ["Arial"];
30847
- const SUPPORTED_FILL_PATTERNS = ["solid"];
30890
+ const SUPPORTED_FILL_PATTERNS = ["solid", "none"];
30848
30891
  const SUPPORTED_CF_TYPES = [
30849
30892
  "expression",
30850
30893
  "cellIs",
@@ -31029,7 +31072,7 @@ stores.inject(MyMetaStore, storeInstance);
31029
31072
  };
31030
31073
  /** Mapping between Excel format indexes (see XLSX_FORMAT_MAP) and some supported formats */
31031
31074
  const XLSX_FORMATS_CONVERSION_MAP = {
31032
- 0: "",
31075
+ 0: "General",
31033
31076
  1: "0",
31034
31077
  2: "0.00",
31035
31078
  3: "#,#00",
@@ -31355,11 +31398,11 @@ stores.inject(MyMetaStore, storeInstance);
31355
31398
  * Excel format are defined in openXML §18.8.31
31356
31399
  */
31357
31400
  function convertXlsxFormat(numFmtId, formats, warningManager) {
31358
- if (numFmtId === 0) {
31359
- return undefined;
31360
- }
31361
31401
  // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
31362
31402
  let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format;
31403
+ if (format === "General") {
31404
+ return undefined;
31405
+ }
31363
31406
  if (format) {
31364
31407
  try {
31365
31408
  let convertedFormat = format.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
@@ -31557,9 +31600,9 @@ stores.inject(MyMetaStore, storeInstance);
31557
31600
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
31558
31601
  continue;
31559
31602
  operator = convertCFCellIsOperator(rule.operator);
31560
- values.push(rule.formula[0]);
31603
+ values.push(prefixFormula(rule.formula[0]));
31561
31604
  if (rule.formula.length === 2) {
31562
- values.push(rule.formula[1]);
31605
+ values.push(prefixFormula(rule.formula[1]));
31563
31606
  }
31564
31607
  break;
31565
31608
  }
@@ -31717,6 +31760,11 @@ stores.inject(MyMetaStore, storeInstance);
31717
31760
  ? ICON_SETS[iconSet].neutral
31718
31761
  : ICON_SETS[iconSet].good;
31719
31762
  }
31763
+ /** Prefix the string by "=" if the string looks like a formula */
31764
+ function prefixFormula(formula) {
31765
+ const tokens = tokenize(formula);
31766
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
31767
+ }
31720
31768
  // ---------------------------------------------------------------------------
31721
31769
  // Warnings
31722
31770
  // ---------------------------------------------------------------------------
@@ -31979,7 +32027,7 @@ stores.inject(MyMetaStore, storeInstance);
31979
32027
  function getRowPosition(rowIndex, sheetData) {
31980
32028
  let position = 0;
31981
32029
  for (let i = 0; i < rowIndex; i++) {
31982
- const rowAtIndex = sheetData.rows[i];
32030
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
31983
32031
  if (rowAtIndex?.height) {
31984
32032
  position += rowAtIndex.height;
31985
32033
  }
@@ -32119,8 +32167,8 @@ stores.inject(MyMetaStore, storeInstance);
32119
32167
  }
32120
32168
  function convertAnchor(XLSXanchor) {
32121
32169
  const offset = {
32122
- x: convertEMUToDotValue(XLSXanchor.colOffset),
32123
- y: convertEMUToDotValue(XLSXanchor.rowOffset),
32170
+ x: convertEMUToDotValue(XLSXanchor.colOffset) - FIGURE_BORDER_WIDTH,
32171
+ y: convertEMUToDotValue(XLSXanchor.rowOffset) - FIGURE_BORDER_WIDTH,
32124
32172
  };
32125
32173
  return { col: XLSXanchor.col, row: XLSXanchor.row, offset };
32126
32174
  }
@@ -32503,8 +32551,12 @@ stores.inject(MyMetaStore, storeInstance);
32503
32551
  dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
32504
32552
  dims[1] = Math.max(dims[1], row.index);
32505
32553
  }
32506
- dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
32507
- dims[1] = Math.max(dims[1], EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
32554
+ for (const fig of sheet.figures) {
32555
+ dims[0] = Math.max(dims[0], fig.anchors[fig.anchors.length - 1]?.col ?? 0);
32556
+ dims[1] = Math.max(dims[1], fig.anchors[fig.anchors.length - 1]?.row ?? 0);
32557
+ }
32558
+ dims[0] = Math.max(dims[0] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
32559
+ dims[1] = Math.max(dims[1] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
32508
32560
  return dims;
32509
32561
  }
32510
32562
  /**
@@ -34195,10 +34247,11 @@ stores.inject(MyMetaStore, storeInstance);
34195
34247
  });
34196
34248
  }
34197
34249
  extractRows(worksheet) {
34250
+ const spilledCells = new Set();
34198
34251
  return this.mapOnElements({ parent: worksheet, query: "sheetData row" }, (rowElement) => {
34199
34252
  return {
34200
34253
  index: this.extractAttr(rowElement, "r", { required: true })?.asNum(),
34201
- cells: this.extractCells(rowElement),
34254
+ cells: this.extractCells(rowElement, spilledCells),
34202
34255
  height: this.extractAttr(rowElement, "ht")?.asNum(),
34203
34256
  customHeight: this.extractAttr(rowElement, "customHeight")?.asBool(),
34204
34257
  hidden: this.extractAttr(rowElement, "hidden")?.asBool(),
@@ -34208,14 +34261,26 @@ stores.inject(MyMetaStore, storeInstance);
34208
34261
  };
34209
34262
  });
34210
34263
  }
34211
- extractCells(row) {
34264
+ extractCells(row, spilledCells) {
34212
34265
  return this.mapOnElements({ parent: row, query: "c" }, (cellElement) => {
34266
+ const xc = this.extractAttr(cellElement, "r", { required: true })?.asString();
34267
+ const formula = this.extractCellFormula(cellElement);
34268
+ if (formula?.ref && formula.sharedIndex === undefined) {
34269
+ const zone = toZone(formula.ref);
34270
+ for (const { col, row } of positions(zone)) {
34271
+ const followerXc = toXC(col, row);
34272
+ if (followerXc !== xc) {
34273
+ spilledCells.add(followerXc);
34274
+ }
34275
+ }
34276
+ }
34277
+ const isSpilled = spilledCells.has(xc);
34213
34278
  return {
34214
- xc: this.extractAttr(cellElement, "r", { required: true })?.asString(),
34279
+ xc,
34215
34280
  styleIndex: this.extractAttr(cellElement, "s")?.asNum(),
34216
34281
  type: CELL_TYPE_CONVERSION_MAP[this.extractAttr(cellElement, "t", { default: "n" })?.asString()],
34217
- value: this.extractChildTextContent(cellElement, "v"),
34218
- formula: this.extractCellFormula(cellElement),
34282
+ value: isSpilled ? undefined : this.extractChildTextContent(cellElement, "v") ?? undefined,
34283
+ formula: isSpilled ? undefined : formula,
34219
34284
  };
34220
34285
  });
34221
34286
  }
@@ -34223,11 +34288,14 @@ stores.inject(MyMetaStore, storeInstance);
34223
34288
  const formulaElement = this.querySelector(cellElement, "f");
34224
34289
  if (!formulaElement)
34225
34290
  return undefined;
34226
- return {
34227
- content: this.extractTextContent(formulaElement),
34228
- sharedIndex: this.extractAttr(formulaElement, "si")?.asNum(),
34229
- ref: this.extractAttr(formulaElement, "ref")?.asString(),
34230
- };
34291
+ const content = this.extractTextContent(formulaElement);
34292
+ const sharedIndex = this.extractAttr(formulaElement, "si")?.asNum();
34293
+ const ref = this.extractAttr(formulaElement, "ref")?.asString();
34294
+ // This is the case of spilled cells of array formulas where <f> is empty
34295
+ if ((content === undefined || content.trim() === "") && sharedIndex === undefined) {
34296
+ return undefined;
34297
+ }
34298
+ return { content, sharedIndex, ref };
34231
34299
  }
34232
34300
  extractHyperLinks(worksheet) {
34233
34301
  return this.mapOnElements({ parent: worksheet, query: "hyperlink" }, (linkElement) => {
@@ -34509,7 +34577,7 @@ stores.inject(MyMetaStore, storeInstance);
34509
34577
  return relsFile;
34510
34578
  }
34511
34579
 
34512
- const EXCEL_IMPORT_VERSION = "18.3";
34580
+ const EXCEL_IMPORT_VERSION = "18.3.1";
34513
34581
  class XlsxReader {
34514
34582
  warningManager;
34515
34583
  xmls;
@@ -38513,7 +38581,7 @@ stores.inject(MyMetaStore, storeInstance);
38513
38581
  const reinsertDynamicPivotMenu = {
38514
38582
  id: "reinsert_dynamic_pivot",
38515
38583
  name: _t("Re-insert dynamic pivot"),
38516
- sequence: 1020,
38584
+ sequence: 60,
38517
38585
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
38518
38586
  children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
38519
38587
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -38521,7 +38589,7 @@ stores.inject(MyMetaStore, storeInstance);
38521
38589
  const reinsertStaticPivotMenu = {
38522
38590
  id: "reinsert_static_pivot",
38523
38591
  name: _t("Re-insert static pivot"),
38524
- sequence: 1020,
38592
+ sequence: 70,
38525
38593
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
38526
38594
  children: [REINSERT_STATIC_PIVOT_CHILDREN],
38527
38595
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -40190,8 +40258,9 @@ stores.inject(MyMetaStore, storeInstance);
40190
40258
  sequence: 40,
40191
40259
  separator: true,
40192
40260
  })
40193
- .addChild("data_sources_data", ["data"], (env) => {
40261
+ .addChild("pivot_data_sources", ["data"], (env) => {
40194
40262
  const sequence = 50;
40263
+ const numberOfPivots = env.model.getters.getPivotIds().length;
40195
40264
  return env.model.getters.getPivotIds().map((pivotId, index) => {
40196
40265
  const highlightProvider = {
40197
40266
  get highlights() {
@@ -40201,7 +40270,7 @@ stores.inject(MyMetaStore, storeInstance);
40201
40270
  return {
40202
40271
  id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
40203
40272
  name: env.model.getters.getPivotDisplayName(pivotId),
40204
- sequence: sequence + index,
40273
+ sequence: sequence + index / numberOfPivots,
40205
40274
  isReadonlyAllowed: true,
40206
40275
  execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
40207
40276
  onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
@@ -57199,7 +57268,8 @@ stores.inject(MyMetaStore, storeInstance);
57199
57268
  * the type of change that occurred.
57200
57269
  *
57201
57270
  * @param applyChange a function that, when called, will adapt the range according to the change on the grid
57202
- * @param sheetId an optional sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
57271
+ * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
57272
+ * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
57203
57273
  */
57204
57274
  adaptRanges(applyChange, sheetId, sheetName) { }
57205
57275
  /**
@@ -57802,9 +57872,7 @@ stores.inject(MyMetaStore, storeInstance);
57802
57872
  for (const cell of Object.values(this.cells[sheet] || {})) {
57803
57873
  if (cell.isFormula) {
57804
57874
  for (const range of cell.compiledFormula.dependencies) {
57805
- if (!sheetId ||
57806
- range.sheetId === sheetId ||
57807
- (sheetName && range.invalidSheetName === sheetName)) {
57875
+ if (range.sheetId === sheetId || range.invalidSheetName === sheetName.old) {
57808
57876
  const change = applyChange(range);
57809
57877
  if (change.changeType !== "NONE") {
57810
57878
  this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
@@ -58420,9 +58488,9 @@ stores.inject(MyMetaStore, storeInstance);
58420
58488
  charts = {};
58421
58489
  createChart = chartFactory(this.getters);
58422
58490
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
58423
- adaptRanges(applyChange) {
58491
+ adaptRanges(applyChange, sheetId, adaptSheetName) {
58424
58492
  for (const [chartId, chart] of Object.entries(this.charts)) {
58425
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
58493
+ this.history.update("charts", chartId, chart?.updateRanges(applyChange, sheetId, adaptSheetName));
58426
58494
  }
58427
58495
  }
58428
58496
  // ---------------------------------------------------------------------------
@@ -58685,7 +58753,7 @@ stores.inject(MyMetaStore, storeInstance);
58685
58753
  }
58686
58754
  }
58687
58755
  }
58688
- adaptRanges(applyChange, sheetId, sheetName) {
58756
+ adaptRanges(applyChange, sheetId) {
58689
58757
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
58690
58758
  for (const sheetId of sheetIds) {
58691
58759
  this.adaptCFRanges(sheetId, applyChange);
@@ -59081,11 +59149,8 @@ stores.inject(MyMetaStore, storeInstance);
59081
59149
  "getValidationRuleForCell",
59082
59150
  ];
59083
59151
  rules = {};
59084
- adaptRanges(applyChange, sheetId, sheetName) {
59085
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.rules);
59086
- for (const sheetId of sheetIds) {
59087
- this.adaptDVRanges(sheetId, applyChange);
59088
- }
59152
+ adaptRanges(applyChange, sheetId) {
59153
+ this.adaptDVRanges(sheetId, applyChange);
59089
59154
  this.adaptDVFormulas(applyChange);
59090
59155
  }
59091
59156
  adaptDVFormulas(applyChange) {
@@ -59375,9 +59440,6 @@ stores.inject(MyMetaStore, storeInstance);
59375
59440
  // Command Handling
59376
59441
  // ---------------------------------------------------------------------------
59377
59442
  adaptRanges(applyChange, sheetId) {
59378
- if (!sheetId) {
59379
- return;
59380
- }
59381
59443
  for (const figure of this.getFigures(sheetId)) {
59382
59444
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
59383
59445
  left: figure.col,
@@ -60185,11 +60247,8 @@ stores.inject(MyMetaStore, storeInstance);
60185
60247
  break;
60186
60248
  }
60187
60249
  }
60188
- adaptRanges(applyChange, sheetId, sheetName) {
60189
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.merges);
60190
- for (const sheetId of sheetIds) {
60191
- this.applyRangeChangeOnSheet(sheetId, applyChange);
60192
- }
60250
+ adaptRanges(applyChange, sheetId) {
60251
+ this.applyRangeChangeOnSheet(sheetId, applyChange);
60193
60252
  }
60194
60253
  // ---------------------------------------------------------------------------
60195
60254
  // Getters
@@ -61697,12 +61756,9 @@ stores.inject(MyMetaStore, storeInstance);
61697
61756
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
61698
61757
  tables = {};
61699
61758
  nextTableId = 1;
61700
- adaptRanges(applyChange, sheetId, sheetName) {
61701
- const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
61702
- for (const sheetId of sheetIds) {
61703
- for (const table of this.getCoreTables(sheetId)) {
61704
- this.applyRangeChangeOnTable(sheetId, table, applyChange);
61705
- }
61759
+ adaptRanges(applyChange, sheetId) {
61760
+ for (const table of this.getCoreTables(sheetId)) {
61761
+ this.applyRangeChangeOnTable(sheetId, table, applyChange);
61706
61762
  }
61707
61763
  }
61708
61764
  allowDispatch(cmd) {
@@ -62665,7 +62721,7 @@ stores.inject(MyMetaStore, storeInstance);
62665
62721
  }
62666
62722
  }
62667
62723
  }
62668
- adaptRanges(applyChange, sheetId, sheetName) {
62724
+ adaptRanges(applyChange) {
62669
62725
  for (const sheetId in this.compiledMeasureFormulas) {
62670
62726
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
62671
62727
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -66826,7 +66882,7 @@ stores.inject(MyMetaStore, storeInstance);
66826
66882
  if (!result) {
66827
66883
  return EMPTY_PIVOT_CELL;
66828
66884
  }
66829
- const { functionName, args } = result;
66885
+ let { functionName, args } = result;
66830
66886
  const formulaId = args[0];
66831
66887
  if (!formulaId) {
66832
66888
  return EMPTY_PIVOT_CELL;
@@ -66856,6 +66912,9 @@ stores.inject(MyMetaStore, storeInstance);
66856
66912
  return pivotCells[pivotCol][pivotRow];
66857
66913
  }
66858
66914
  try {
66915
+ const offsetRow = position.row - mainPosition.row;
66916
+ const offsetCol = position.col - mainPosition.col;
66917
+ args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
66859
66918
  if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
66860
66919
  const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
66861
66920
  return {
@@ -68054,7 +68113,8 @@ stores.inject(MyMetaStore, storeInstance);
68054
68113
  // If the executed command is not in the registry, we skip it
68055
68114
  // because we know there won't be any transformation impacting the
68056
68115
  // commands to transform.
68057
- if (possibleTransformations.has(executedCommand.type)) {
68116
+ if (possibleTransformations.has(executedCommand.type) ||
68117
+ rangeAdapterRegistry.contains(executedCommand.type)) {
68058
68118
  transformedCommands = transformedCommands.reduce((acc, cmd) => {
68059
68119
  const transformed = transform(cmd, executedCommand);
68060
68120
  if (transformed) {
@@ -68788,7 +68848,7 @@ stores.inject(MyMetaStore, storeInstance);
68788
68848
  bottom: rowIndex,
68789
68849
  }));
68790
68850
  const handler = new CellClipboardHandler(this.getters, this.dispatch);
68791
- const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep));
68851
+ const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep), false);
68792
68852
  if (!data) {
68793
68853
  return;
68794
68854
  }
@@ -70828,12 +70888,12 @@ stores.inject(MyMetaStore, storeInstance);
70828
70888
  }
70829
70889
  case "INSERT_CELL": {
70830
70890
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
70831
- const copiedData = this.copy(cut);
70891
+ const copiedData = this.copy(cut, "shiftCells");
70832
70892
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
70833
70893
  }
70834
70894
  case "DELETE_CELL": {
70835
70895
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
70836
- const copiedData = this.copy(cut);
70896
+ const copiedData = this.copy(cut, "shiftCells");
70837
70897
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
70838
70898
  }
70839
70899
  }
@@ -70944,13 +71004,13 @@ stores.inject(MyMetaStore, storeInstance);
70944
71004
  });
70945
71005
  break;
70946
71006
  }
70947
- const copiedData = this.copy(cut);
71007
+ const copiedData = this.copy(cut, "shiftCells");
70948
71008
  this.paste(paste, copiedData, { isCutOperation: true });
70949
71009
  break;
70950
71010
  }
70951
71011
  case "INSERT_CELL": {
70952
71012
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
70953
- const copiedData = this.copy(cut);
71013
+ const copiedData = this.copy(cut, "shiftCells");
70954
71014
  this.paste(paste, copiedData, { isCutOperation: true });
70955
71015
  break;
70956
71016
  }
@@ -71065,11 +71125,11 @@ stores.inject(MyMetaStore, storeInstance);
71065
71125
  }
71066
71126
  return false;
71067
71127
  }
71068
- copy(zones) {
71128
+ copy(zones, mode = "copyPaste") {
71069
71129
  let copiedData = {};
71070
71130
  const clipboardData = this.getClipboardData(zones);
71071
71131
  for (const { handlerName, handler } of this.selectClipboardHandlers(clipboardData)) {
71072
- const data = handler.copy(clipboardData, this._isCutOperation);
71132
+ const data = handler.copy(clipboardData, this._isCutOperation, mode);
71073
71133
  copiedData[handlerName] = data;
71074
71134
  const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
71075
71135
  for (const key of minimalKeys) {
@@ -72020,7 +72080,7 @@ stores.inject(MyMetaStore, storeInstance);
72020
72080
  ];
72021
72081
  for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
72022
72082
  const handler = new Handler(this.getters, this.dispatch);
72023
- const data = handler.copy(getClipboardDataPositions(sheetId, target));
72083
+ const data = handler.copy(getClipboardDataPositions(sheetId, target), false, "shiftCells");
72024
72084
  if (!data) {
72025
72085
  continue;
72026
72086
  }
@@ -79215,7 +79275,7 @@ stores.inject(MyMetaStore, storeInstance);
79215
79275
  for (const [headerIndex, header] of headers.slice(anchor).entries()) {
79216
79276
  if (currentPosition <= offset && offset < currentPosition + header.size) {
79217
79277
  return {
79218
- index: headerIndex,
79278
+ index: anchor + headerIndex,
79219
79279
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
79220
79280
  };
79221
79281
  }
@@ -80954,9 +81014,9 @@ stores.inject(MyMetaStore, storeInstance);
80954
81014
  exports.tokenize = tokenize;
80955
81015
 
80956
81016
 
80957
- __info__.version = "18.3.18";
80958
- __info__.date = "2025-08-26T10:14:21.408Z";
80959
- __info__.hash = "ec2777d";
81017
+ __info__.version = "18.3.20";
81018
+ __info__.date = "2025-09-11T08:45:37.934Z";
81019
+ __info__.hash = "ef829f4";
80960
81020
 
80961
81021
 
80962
81022
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);