@odoo/o-spreadsheet 18.4.8 → 18.4.10

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.10
6
+ * @date 2025-09-11T08:45:39.178Z
7
+ * @hash 15a11a4
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";
@@ -7345,7 +7354,7 @@ class ClipboardHandler {
7345
7354
  this.getters = getters;
7346
7355
  this.dispatch = dispatch;
7347
7356
  }
7348
- copy(data, isCutOperation) {
7357
+ copy(data, isCutOperation, mode = "copyPaste") {
7349
7358
  return;
7350
7359
  }
7351
7360
  paste(target, clippedContent, options) { }
@@ -7364,7 +7373,7 @@ class ClipboardHandler {
7364
7373
  }
7365
7374
 
7366
7375
  class AbstractCellClipboardHandler extends ClipboardHandler {
7367
- copy(data) {
7376
+ copy(data, isCutOperation, mode = "copyPaste") {
7368
7377
  return;
7369
7378
  }
7370
7379
  pasteFromCopy(sheetId, target, content, options) {
@@ -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
  }
@@ -8888,7 +8903,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8888
8903
  }
8889
8904
  return "Success" /* CommandResult.Success */;
8890
8905
  }
8891
- copy(data) {
8906
+ copy(data, isCutOperation, mode = "copyPaste") {
8892
8907
  const sheetId = data.sheetId;
8893
8908
  const { clippedZones, rowsIndexes, columnsIndexes } = data;
8894
8909
  const clippedCells = [];
@@ -8901,7 +8916,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8901
8916
  const evaluatedCell = this.getters.getEvaluatedCell(position);
8902
8917
  const pivotId = this.getters.getPivotIdFromPosition(position);
8903
8918
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
8904
- if (pivotId && spreader) {
8919
+ if (mode !== "shiftCells" && pivotId && spreader) {
8905
8920
  const pivotZone = this.getters.getSpreadZone(spreader);
8906
8921
  if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
8907
8922
  pivotZone &&
@@ -8919,7 +8934,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8919
8934
  };
8920
8935
  }
8921
8936
  }
8922
- else {
8937
+ else if (mode !== "shiftCells") {
8923
8938
  if (spreader && !deepEquals(spreader, position)) {
8924
8939
  const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
8925
8940
  const content = isSpreaderCopied
@@ -9617,7 +9632,7 @@ class SheetClipboardHandler extends AbstractCellClipboardHandler {
9617
9632
  }
9618
9633
 
9619
9634
  class TableClipboardHandler extends AbstractCellClipboardHandler {
9620
- copy(data, isCutOperation) {
9635
+ copy(data, isCutOperation, mode = "copyPaste") {
9621
9636
  const sheetId = data.sheetId;
9622
9637
  const { rowsIndexes, columnsIndexes, zones } = data;
9623
9638
  const copiedTablesIds = new Set();
@@ -9655,11 +9670,13 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
9655
9670
  type: coreTable.type,
9656
9671
  };
9657
9672
  }
9658
- tableCellsInRow.push({
9659
- table: copiedTable,
9660
- style: this.getTableStyleToCopy(position),
9661
- isWholeTableCopied: copiedTablesIds.has(table.id),
9662
- });
9673
+ if (mode !== "shiftCells") {
9674
+ tableCellsInRow.push({
9675
+ table: copiedTable,
9676
+ style: this.getTableStyleToCopy(position),
9677
+ isWholeTableCopied: copiedTablesIds.has(table.id),
9678
+ });
9679
+ }
9663
9680
  }
9664
9681
  }
9665
9682
  return {
@@ -11236,6 +11253,9 @@ const MMULT = {
11236
11253
  compute: function (matrix1, matrix2) {
11237
11254
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
11238
11255
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
11256
+ if (_matrix1.length === 0 || _matrix2.length === 0) {
11257
+ return new EvaluationError(_t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
11258
+ }
11239
11259
  if (_matrix1.length !== _matrix2[0].length) {
11240
11260
  return new EvaluationError(_t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
11241
11261
  number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
@@ -12848,7 +12868,7 @@ function centile(data, percent, isInclusive, locale) {
12848
12868
  count++;
12849
12869
  }
12850
12870
  });
12851
- assert(count !== 0, _t("[[FUNCTION_NAME]] has no valid input data."));
12871
+ assert(count !== 0, noValidInputErrorMessage);
12852
12872
  if (!isInclusive) {
12853
12873
  // 2nd argument must be between 1/(n+1) and n/(n+1) with n the number of data
12854
12874
  assert(1 / (count + 1) <= _percent && _percent <= count / (count + 1), _t("Function [[FUNCTION_NAME]] parameter 2 value is out of range."));
@@ -13123,6 +13143,9 @@ const FORECAST = {
13123
13143
  ],
13124
13144
  compute: function (x, dataY, dataX) {
13125
13145
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13146
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13147
+ return new NotAvailableError(noValidInputErrorMessage);
13148
+ }
13126
13149
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
13127
13150
  },
13128
13151
  isExported: true,
@@ -13139,6 +13162,9 @@ const GROWTH = {
13139
13162
  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
13163
  ],
13141
13164
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13165
+ if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13166
+ return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13167
+ }
13142
13168
  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
13169
  },
13144
13170
  };
@@ -13153,6 +13179,9 @@ const INTERCEPT = {
13153
13179
  ],
13154
13180
  compute: function (dataY, dataX) {
13155
13181
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13182
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13183
+ return new NotAvailableError(noValidInputErrorMessage);
13184
+ }
13156
13185
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
13157
13186
  return intercept;
13158
13187
  },
@@ -13185,7 +13214,7 @@ const LARGE = {
13185
13214
  });
13186
13215
  const result = largests.shift();
13187
13216
  if (result === undefined) {
13188
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
13217
+ return new EvaluationError(noValidInputErrorMessage);
13189
13218
  }
13190
13219
  if (count < _n) {
13191
13220
  return new EvaluationError(_t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
@@ -13206,6 +13235,9 @@ const LINEST = {
13206
13235
  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
13236
  ],
13208
13237
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13238
+ if (dataY.length === 0 || dataY[0].length === 0) {
13239
+ return new EvaluationError(emptyDataErrorMessage("data_y"));
13240
+ }
13209
13241
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
13210
13242
  },
13211
13243
  isExported: true,
@@ -13222,6 +13254,9 @@ const LOGEST = {
13222
13254
  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
13255
  ],
13224
13256
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13257
+ if (dataY.length === 0 || dataY[0].length === 0) {
13258
+ return new EvaluationError(emptyDataErrorMessage("data_y"));
13259
+ }
13225
13260
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
13226
13261
  for (let i = 0; i < coeffs.length; i++) {
13227
13262
  coeffs[i][0] = Math.exp(coeffs[i][0]);
@@ -13243,8 +13278,8 @@ const MATTHEWS = {
13243
13278
  const flatX = dataX.flat();
13244
13279
  const flatY = dataY.flat();
13245
13280
  assertSameNumberOfElements(flatX, flatY);
13246
- if (flatX.length === 0) {
13247
- return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13281
+ if (flatX.length === 0 || flatY.length === 0) {
13282
+ return new NotAvailableError(noValidInputErrorMessage);
13248
13283
  }
13249
13284
  const n = flatX.length;
13250
13285
  let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
@@ -13409,11 +13444,8 @@ const MINIFS = {
13409
13444
  // -----------------------------------------------------------------------------
13410
13445
  function pearson(dataY, dataX) {
13411
13446
  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."));
13447
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13448
+ return new NotAvailableError(noValidInputErrorMessage);
13417
13449
  }
13418
13450
  const n = flatDataX.length;
13419
13451
  let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
@@ -13503,6 +13535,9 @@ const POLYFIT_COEFFS = {
13503
13535
  ],
13504
13536
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13505
13537
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13538
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13539
+ return new NotAvailableError(noValidInputErrorMessage);
13540
+ }
13506
13541
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
13507
13542
  },
13508
13543
  isExported: false,
@@ -13522,6 +13557,9 @@ const POLYFIT_FORECAST = {
13522
13557
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13523
13558
  const _order = toNumber(order, this.locale);
13524
13559
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13560
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13561
+ return new NotAvailableError(noValidInputErrorMessage);
13562
+ }
13525
13563
  const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
13526
13564
  return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
13527
13565
  },
@@ -13623,7 +13661,11 @@ const RSQ = {
13623
13661
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13624
13662
  ],
13625
13663
  compute: function (dataY, dataX) {
13626
- return Math.pow(pearson(dataX, dataY), 2.0);
13664
+ const value = pearson(dataY, dataX);
13665
+ if (value instanceof Error) {
13666
+ throw value;
13667
+ }
13668
+ return Math.pow(value, 2.0);
13627
13669
  },
13628
13670
  isExported: true,
13629
13671
  };
@@ -13638,6 +13680,9 @@ const SLOPE = {
13638
13680
  ],
13639
13681
  compute: function (dataY, dataX) {
13640
13682
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13683
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13684
+ return new NotAvailableError(noValidInputErrorMessage);
13685
+ }
13641
13686
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
13642
13687
  return slope;
13643
13688
  },
@@ -13670,7 +13715,7 @@ const SMALL = {
13670
13715
  });
13671
13716
  const result = largests.pop();
13672
13717
  if (result === undefined) {
13673
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
13718
+ return new EvaluationError(noValidInputErrorMessage);
13674
13719
  }
13675
13720
  if (count < _n) {
13676
13721
  return new EvaluationError(_t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
@@ -13690,6 +13735,9 @@ const SPEARMAN = {
13690
13735
  ],
13691
13736
  compute: function (dataX, dataY) {
13692
13737
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13738
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13739
+ return new NotAvailableError(noValidInputErrorMessage);
13740
+ }
13693
13741
  const n = flatDataX.length;
13694
13742
  const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
13695
13743
  order.sort((a, b) => a[0] - b[0]);
@@ -13800,6 +13848,9 @@ const STEYX = {
13800
13848
  ],
13801
13849
  compute: function (dataY, dataX) {
13802
13850
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13851
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13852
+ return new NotAvailableError(noValidInputErrorMessage);
13853
+ }
13803
13854
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
13804
13855
  return data[1][2];
13805
13856
  },
@@ -13817,6 +13868,9 @@ const TREND = {
13817
13868
  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
13869
  ],
13819
13870
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13871
+ if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13872
+ return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13873
+ }
13820
13874
  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
13875
  },
13822
13876
  };
@@ -18732,7 +18786,7 @@ const AND = {
18732
18786
  compute: function (...logicalExpressions) {
18733
18787
  const { result, foundBoolean } = boolAnd(logicalExpressions);
18734
18788
  if (!foundBoolean) {
18735
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18789
+ return new EvaluationError(noValidInputErrorMessage);
18736
18790
  }
18737
18791
  return result;
18738
18792
  },
@@ -18858,7 +18912,7 @@ const OR = {
18858
18912
  compute: function (...logicalExpressions) {
18859
18913
  const { result, foundBoolean } = boolOr(logicalExpressions);
18860
18914
  if (!foundBoolean) {
18861
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18915
+ return new EvaluationError(noValidInputErrorMessage);
18862
18916
  }
18863
18917
  return result;
18864
18918
  },
@@ -18921,7 +18975,7 @@ const XOR = {
18921
18975
  return true; // no stop condition
18922
18976
  });
18923
18977
  if (!foundBoolean) {
18924
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18978
+ return new EvaluationError(noValidInputErrorMessage);
18925
18979
  }
18926
18980
  return acc;
18927
18981
  },
@@ -21385,7 +21439,7 @@ function adaptFormulaStringRanges(defaultSheetId, formula, applyChange) {
21385
21439
  function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
21386
21440
  const sheetName = splitReference(sheetXC).sheetName;
21387
21441
  if (sheetName
21388
- ? !isSheetNameEqual(sheetName, applyChange.sheetName)
21442
+ ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
21389
21443
  : defaultSheetId !== applyChange.sheetId) {
21390
21444
  return sheetXC;
21391
21445
  }
@@ -21402,7 +21456,7 @@ function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
21402
21456
  }
21403
21457
  function getSheetNameGetter(applyChange) {
21404
21458
  return (sheetId) => {
21405
- return sheetId === applyChange.sheetId ? applyChange.sheetName : "";
21459
+ return sheetId === applyChange.sheetId ? applyChange.sheetName.current : "";
21406
21460
  };
21407
21461
  }
21408
21462
  function defaultGetSheetSize(sheetId) {
@@ -27393,9 +27447,13 @@ class GaugeChart extends AbstractChart {
27393
27447
  : undefined,
27394
27448
  };
27395
27449
  }
27396
- updateRanges(applyChange) {
27450
+ updateRanges(applyChange, sheetId, adaptSheetName) {
27397
27451
  const dataRange = adaptChartRange(this.dataRange, applyChange);
27398
- const adaptFormula = (formula) => this.getters.adaptFormulaStringDependencies(this.sheetId, formula, applyChange);
27452
+ const adaptFormula = (formula) => adaptFormulaStringRanges(this.sheetId, formula, {
27453
+ applyChange,
27454
+ sheetId,
27455
+ sheetName: adaptSheetName,
27456
+ });
27399
27457
  const sectionRule = adaptSectionRuleFormulas(this.sectionRule, adaptFormula);
27400
27458
  const definition = this.getDefinitionWithSpecificRanges(dataRange, sectionRule);
27401
27459
  return new GaugeChart(definition, this.sheetId, this.getters);
@@ -33718,6 +33776,9 @@ class Composer extends Component {
33718
33776
  this.contentHelper.removeSelection();
33719
33777
  }
33720
33778
  onMouseup() {
33779
+ if (this.env.model.getters.isReadonly()) {
33780
+ return;
33781
+ }
33721
33782
  const selection = this.contentHelper.getCurrentSelection();
33722
33783
  if (selection.start !== selection.end) {
33723
33784
  this.props.composerStore.hoverToken(undefined);
@@ -37453,7 +37514,7 @@ const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
37453
37514
  ];
37454
37515
  const SUPPORTED_VERTICAL_ALIGNMENTS = ["top", "center", "bottom"];
37455
37516
  const SUPPORTED_FONTS = ["Arial"];
37456
- const SUPPORTED_FILL_PATTERNS = ["solid"];
37517
+ const SUPPORTED_FILL_PATTERNS = ["solid", "none"];
37457
37518
  const SUPPORTED_CF_TYPES = [
37458
37519
  "expression",
37459
37520
  "cellIs",
@@ -37653,7 +37714,7 @@ const SUBTOTAL_FUNCTION_CONVERSION_MAP = {
37653
37714
  };
37654
37715
  /** Mapping between Excel format indexes (see XLSX_FORMAT_MAP) and some supported formats */
37655
37716
  const XLSX_FORMATS_CONVERSION_MAP = {
37656
- 0: "",
37717
+ 0: "General",
37657
37718
  1: "0",
37658
37719
  2: "0.00",
37659
37720
  3: "#,#00",
@@ -37979,11 +38040,11 @@ const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/
37979
38040
  * Excel format are defined in openXML §18.8.31
37980
38041
  */
37981
38042
  function convertXlsxFormat(numFmtId, formats, warningManager) {
37982
- if (numFmtId === 0) {
37983
- return undefined;
37984
- }
37985
38043
  // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
37986
38044
  const format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format;
38045
+ if (format === "General") {
38046
+ return undefined;
38047
+ }
37987
38048
  if (format) {
37988
38049
  try {
37989
38050
  let convertedFormat = format.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
@@ -38181,9 +38242,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
38181
38242
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
38182
38243
  continue;
38183
38244
  operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
38184
- values.push(rule.formula[0]);
38245
+ values.push(prefixFormula(rule.formula[0]));
38185
38246
  if (rule.formula.length === 2) {
38186
- values.push(rule.formula[1]);
38247
+ values.push(prefixFormula(rule.formula[1]));
38187
38248
  }
38188
38249
  break;
38189
38250
  }
@@ -38341,6 +38402,11 @@ function convertIcons(xlsxIconSet, index) {
38341
38402
  ? ICON_SETS[iconSet].neutral
38342
38403
  : ICON_SETS[iconSet].good;
38343
38404
  }
38405
+ /** Prefix the string by "=" if the string looks like a formula */
38406
+ function prefixFormula(formula) {
38407
+ const tokens = tokenize(formula);
38408
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
38409
+ }
38344
38410
  // ---------------------------------------------------------------------------
38345
38411
  // Warnings
38346
38412
  // ---------------------------------------------------------------------------
@@ -38623,7 +38689,7 @@ function getColPosition(colIndex, sheetData) {
38623
38689
  function getRowPosition(rowIndex, sheetData) {
38624
38690
  let position = 0;
38625
38691
  for (let i = 0; i < rowIndex; i++) {
38626
- const rowAtIndex = sheetData.rows[i];
38692
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
38627
38693
  if (rowAtIndex?.height) {
38628
38694
  position += rowAtIndex.height;
38629
38695
  }
@@ -38778,8 +38844,8 @@ function convertExcelTrendline(trend) {
38778
38844
  }
38779
38845
  function convertAnchor(XLSXanchor) {
38780
38846
  const offset = {
38781
- x: convertEMUToDotValue(XLSXanchor.colOffset),
38782
- y: convertEMUToDotValue(XLSXanchor.rowOffset),
38847
+ x: convertEMUToDotValue(XLSXanchor.colOffset) - FIGURE_BORDER_WIDTH,
38848
+ y: convertEMUToDotValue(XLSXanchor.rowOffset) - FIGURE_BORDER_WIDTH,
38783
38849
  };
38784
38850
  return { col: XLSXanchor.col, row: XLSXanchor.row, offset };
38785
38851
  }
@@ -39162,8 +39228,12 @@ function getSheetDims(sheet) {
39162
39228
  dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
39163
39229
  dims[1] = Math.max(dims[1], row.index);
39164
39230
  }
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);
39231
+ for (const fig of sheet.figures) {
39232
+ dims[0] = Math.max(dims[0], fig.anchors[fig.anchors.length - 1]?.col ?? 0);
39233
+ dims[1] = Math.max(dims[1], fig.anchors[fig.anchors.length - 1]?.row ?? 0);
39234
+ }
39235
+ dims[0] = Math.max(dims[0] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
39236
+ dims[1] = Math.max(dims[1] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
39167
39237
  return dims;
39168
39238
  }
39169
39239
  /**
@@ -40552,10 +40622,11 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
40552
40622
  });
40553
40623
  }
40554
40624
  extractRows(worksheet) {
40625
+ const spilledCells = new Set();
40555
40626
  return this.mapOnElements({ parent: worksheet, query: "sheetData row" }, (rowElement) => {
40556
40627
  return {
40557
40628
  index: this.extractAttr(rowElement, "r", { required: true })?.asNum(),
40558
- cells: this.extractCells(rowElement),
40629
+ cells: this.extractCells(rowElement, spilledCells),
40559
40630
  height: this.extractAttr(rowElement, "ht")?.asNum(),
40560
40631
  customHeight: this.extractAttr(rowElement, "customHeight")?.asBool(),
40561
40632
  hidden: this.extractAttr(rowElement, "hidden")?.asBool(),
@@ -40565,14 +40636,26 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
40565
40636
  };
40566
40637
  });
40567
40638
  }
40568
- extractCells(row) {
40639
+ extractCells(row, spilledCells) {
40569
40640
  return this.mapOnElements({ parent: row, query: "c" }, (cellElement) => {
40641
+ const xc = this.extractAttr(cellElement, "r", { required: true })?.asString();
40642
+ const formula = this.extractCellFormula(cellElement);
40643
+ if (formula?.ref && formula.sharedIndex === undefined) {
40644
+ const zone = toZone(formula.ref);
40645
+ for (const { col, row } of positions(zone)) {
40646
+ const followerXc = toXC(col, row);
40647
+ if (followerXc !== xc) {
40648
+ spilledCells.add(followerXc);
40649
+ }
40650
+ }
40651
+ }
40652
+ const isSpilled = spilledCells.has(xc);
40570
40653
  return {
40571
- xc: this.extractAttr(cellElement, "r", { required: true })?.asString(),
40654
+ xc,
40572
40655
  styleIndex: this.extractAttr(cellElement, "s")?.asNum(),
40573
40656
  type: CELL_TYPE_CONVERSION_MAP[this.extractAttr(cellElement, "t", { default: "n" })?.asString()],
40574
- value: this.extractChildTextContent(cellElement, "v"),
40575
- formula: this.extractCellFormula(cellElement),
40657
+ value: isSpilled ? undefined : this.extractChildTextContent(cellElement, "v") ?? undefined,
40658
+ formula: isSpilled ? undefined : formula,
40576
40659
  };
40577
40660
  });
40578
40661
  }
@@ -40580,11 +40663,14 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
40580
40663
  const formulaElement = this.querySelector(cellElement, "f");
40581
40664
  if (!formulaElement)
40582
40665
  return undefined;
40583
- return {
40584
- content: this.extractTextContent(formulaElement),
40585
- sharedIndex: this.extractAttr(formulaElement, "si")?.asNum(),
40586
- ref: this.extractAttr(formulaElement, "ref")?.asString(),
40587
- };
40666
+ const content = this.extractTextContent(formulaElement);
40667
+ const sharedIndex = this.extractAttr(formulaElement, "si")?.asNum();
40668
+ const ref = this.extractAttr(formulaElement, "ref")?.asString();
40669
+ // This is the case of spilled cells of array formulas where <f> is empty
40670
+ if ((content === undefined || content.trim() === "") && sharedIndex === undefined) {
40671
+ return undefined;
40672
+ }
40673
+ return { content, sharedIndex, ref };
40588
40674
  }
40589
40675
  extractHyperLinks(worksheet) {
40590
40676
  return this.mapOnElements({ parent: worksheet, query: "hyperlink" }, (linkElement) => {
@@ -40866,7 +40952,7 @@ function getRelationFile(file, xmls) {
40866
40952
  return relsFile;
40867
40953
  }
40868
40954
 
40869
- const EXCEL_IMPORT_VERSION = "18.4.1";
40955
+ const EXCEL_IMPORT_VERSION = "18.4.2";
40870
40956
  class XlsxReader {
40871
40957
  warningManager;
40872
40958
  xmls;
@@ -44411,7 +44497,7 @@ const splitToColumns = {
44411
44497
  const reinsertDynamicPivotMenu = {
44412
44498
  id: "reinsert_dynamic_pivot",
44413
44499
  name: _t("Re-insert dynamic pivot"),
44414
- sequence: 1020,
44500
+ sequence: 60,
44415
44501
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
44416
44502
  children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
44417
44503
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -44419,7 +44505,7 @@ const reinsertDynamicPivotMenu = {
44419
44505
  const reinsertStaticPivotMenu = {
44420
44506
  id: "reinsert_static_pivot",
44421
44507
  name: _t("Re-insert static pivot"),
44422
- sequence: 1020,
44508
+ sequence: 70,
44423
44509
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
44424
44510
  children: [REINSERT_STATIC_PIVOT_CHILDREN],
44425
44511
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -58690,7 +58776,8 @@ class CorePlugin extends BasePlugin {
58690
58776
  * the type of change that occurred.
58691
58777
  *
58692
58778
  * @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
58779
+ * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
58780
+ * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
58694
58781
  */
58695
58782
  adaptRanges(applyChange, sheetId, sheetName) { }
58696
58783
  /**
@@ -59293,9 +59380,7 @@ class CellPlugin extends CorePlugin {
59293
59380
  for (const cell of Object.values(this.cells[sheet] || {})) {
59294
59381
  if (cell.isFormula) {
59295
59382
  for (const range of cell.compiledFormula.dependencies) {
59296
- if (!sheetId ||
59297
- range.sheetId === sheetId ||
59298
- (sheetName && range.invalidSheetName === sheetName)) {
59383
+ if (range.sheetId === sheetId || range.invalidSheetName === sheetName.old) {
59299
59384
  const change = applyChange(range);
59300
59385
  if (change.changeType !== "NONE") {
59301
59386
  this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
@@ -59911,9 +59996,9 @@ class ChartPlugin extends CorePlugin {
59911
59996
  charts = {};
59912
59997
  createChart = chartFactory(this.getters);
59913
59998
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
59914
- adaptRanges(applyChange) {
59999
+ adaptRanges(applyChange, sheetId, adaptSheetName) {
59915
60000
  for (const [chartId, chart] of Object.entries(this.charts)) {
59916
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
60001
+ this.history.update("charts", chartId, chart?.updateRanges(applyChange, sheetId, adaptSheetName));
59917
60002
  }
59918
60003
  }
59919
60004
  // ---------------------------------------------------------------------------
@@ -60176,7 +60261,7 @@ class ConditionalFormatPlugin extends CorePlugin {
60176
60261
  }
60177
60262
  }
60178
60263
  }
60179
- adaptRanges(applyChange, sheetId, sheetName) {
60264
+ adaptRanges(applyChange, sheetId) {
60180
60265
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
60181
60266
  for (const sheetId of sheetIds) {
60182
60267
  this.adaptCFRanges(sheetId, applyChange);
@@ -60558,11 +60643,8 @@ class DataValidationPlugin extends CorePlugin {
60558
60643
  "getValidationRuleForCell",
60559
60644
  ];
60560
60645
  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
- }
60646
+ adaptRanges(applyChange, sheetId) {
60647
+ this.adaptDVRanges(sheetId, applyChange);
60566
60648
  this.adaptDVFormulas(applyChange);
60567
60649
  }
60568
60650
  adaptDVFormulas(applyChange) {
@@ -60852,9 +60934,6 @@ class FigurePlugin extends CorePlugin {
60852
60934
  // Command Handling
60853
60935
  // ---------------------------------------------------------------------------
60854
60936
  adaptRanges(applyChange, sheetId) {
60855
- if (!sheetId) {
60856
- return;
60857
- }
60858
60937
  for (const figure of this.getFigures(sheetId)) {
60859
60938
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
60860
60939
  left: figure.col,
@@ -61663,11 +61742,8 @@ class MergePlugin extends CorePlugin {
61663
61742
  break;
61664
61743
  }
61665
61744
  }
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
- }
61745
+ adaptRanges(applyChange, sheetId) {
61746
+ this.applyRangeChangeOnSheet(sheetId, applyChange);
61671
61747
  }
61672
61748
  // ---------------------------------------------------------------------------
61673
61749
  // Getters
@@ -63172,12 +63248,9 @@ class TablePlugin extends CorePlugin {
63172
63248
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
63173
63249
  tables = {};
63174
63250
  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
- }
63251
+ adaptRanges(applyChange, sheetId) {
63252
+ for (const table of this.getCoreTables(sheetId)) {
63253
+ this.applyRangeChangeOnTable(sheetId, table, applyChange);
63181
63254
  }
63182
63255
  }
63183
63256
  allowDispatch(cmd) {
@@ -64140,7 +64213,7 @@ class PivotCorePlugin extends CorePlugin {
64140
64213
  }
64141
64214
  }
64142
64215
  }
64143
- adaptRanges(applyChange, sheetId, sheetName) {
64216
+ adaptRanges(applyChange) {
64144
64217
  for (const sheetId in this.compiledMeasureFormulas) {
64145
64218
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64146
64219
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -68541,7 +68614,7 @@ class PivotUIPlugin extends CoreViewPlugin {
68541
68614
  if (!result) {
68542
68615
  return EMPTY_PIVOT_CELL;
68543
68616
  }
68544
- const { functionName, args } = result;
68617
+ let { functionName, args } = result;
68545
68618
  const formulaId = args[0];
68546
68619
  if (!formulaId) {
68547
68620
  return EMPTY_PIVOT_CELL;
@@ -68576,6 +68649,9 @@ class PivotUIPlugin extends CoreViewPlugin {
68576
68649
  return pivotCells[pivotCol][pivotRow];
68577
68650
  }
68578
68651
  try {
68652
+ const offsetRow = position.row - mainPosition.row;
68653
+ const offsetCol = position.col - mainPosition.col;
68654
+ args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
68579
68655
  if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
68580
68656
  const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
68581
68657
  return {
@@ -70184,7 +70260,8 @@ function transformAll(toTransform, executed) {
70184
70260
  // If the executed command is not in the registry, we skip it
70185
70261
  // because we know there won't be any transformation impacting the
70186
70262
  // commands to transform.
70187
- if (possibleTransformations.has(executedCommand.type)) {
70263
+ if (possibleTransformations.has(executedCommand.type) ||
70264
+ rangeAdapterRegistry.contains(executedCommand.type)) {
70188
70265
  transformedCommands = transformedCommands.reduce((acc, cmd) => {
70189
70266
  const transformed = transform(cmd, executedCommand);
70190
70267
  if (transformed) {
@@ -70931,7 +71008,7 @@ class DataCleanupPlugin extends UIPlugin {
70931
71008
  bottom: rowIndex,
70932
71009
  }));
70933
71010
  const handler = new CellClipboardHandler(this.getters, this.dispatch);
70934
- const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep));
71011
+ const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep), false);
70935
71012
  if (!data) {
70936
71013
  return;
70937
71014
  }
@@ -73016,12 +73093,12 @@ class ClipboardPlugin extends UIPlugin {
73016
73093
  }
73017
73094
  case "INSERT_CELL": {
73018
73095
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
73019
- const copiedData = this.copy(cut);
73096
+ const copiedData = this.copy(cut, "shiftCells");
73020
73097
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
73021
73098
  }
73022
73099
  case "DELETE_CELL": {
73023
73100
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
73024
- const copiedData = this.copy(cut);
73101
+ const copiedData = this.copy(cut, "shiftCells");
73025
73102
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
73026
73103
  }
73027
73104
  }
@@ -73132,13 +73209,13 @@ class ClipboardPlugin extends UIPlugin {
73132
73209
  });
73133
73210
  break;
73134
73211
  }
73135
- const copiedData = this.copy(cut);
73212
+ const copiedData = this.copy(cut, "shiftCells");
73136
73213
  this.paste(paste, copiedData, { isCutOperation: true });
73137
73214
  break;
73138
73215
  }
73139
73216
  case "INSERT_CELL": {
73140
73217
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
73141
- const copiedData = this.copy(cut);
73218
+ const copiedData = this.copy(cut, "shiftCells");
73142
73219
  this.paste(paste, copiedData, { isCutOperation: true });
73143
73220
  break;
73144
73221
  }
@@ -73253,11 +73330,11 @@ class ClipboardPlugin extends UIPlugin {
73253
73330
  }
73254
73331
  return false;
73255
73332
  }
73256
- copy(zones) {
73333
+ copy(zones, mode = "copyPaste") {
73257
73334
  const copiedData = {};
73258
73335
  const clipboardData = this.getClipboardData(zones);
73259
73336
  for (const { handlerName, handler } of this.selectClipboardHandlers(clipboardData)) {
73260
- const data = handler.copy(clipboardData, this._isCutOperation);
73337
+ const data = handler.copy(clipboardData, this._isCutOperation, mode);
73261
73338
  copiedData[handlerName] = data;
73262
73339
  const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
73263
73340
  for (const key of minimalKeys) {
@@ -74271,7 +74348,7 @@ class GridSelectionPlugin extends UIPlugin {
74271
74348
  ];
74272
74349
  for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
74273
74350
  const handler = new Handler(this.getters, this.dispatch);
74274
- const data = handler.copy(getClipboardDataPositions(sheetId, target));
74351
+ const data = handler.copy(getClipboardDataPositions(sheetId, target), false, "shiftCells");
74275
74352
  if (!data) {
74276
74353
  continue;
74277
74354
  }
@@ -76176,7 +76253,8 @@ const inverseCommandRegistry = new Registry()
76176
76253
  .add("HIDE_COLUMNS_ROWS", inverseHideColumnsRows)
76177
76254
  .add("UNHIDE_COLUMNS_ROWS", inverseUnhideColumnsRows)
76178
76255
  .add("CREATE_TABLE_STYLE", inverseCreateTableStyle)
76179
- .add("ADD_PIVOT", inverseAddPivot);
76256
+ .add("ADD_PIVOT", inverseAddPivot)
76257
+ .add("RENAME_SHEET", inverseRenameSheet);
76180
76258
  for (const cmd of coreTypes.values()) {
76181
76259
  if (!inverseCommandRegistry.contains(cmd)) {
76182
76260
  inverseCommandRegistry.add(cmd, identity);
@@ -76274,6 +76352,16 @@ function inverseUnhideColumnsRows(cmd) {
76274
76352
  function inverseCreateTableStyle(cmd) {
76275
76353
  return [{ type: "REMOVE_TABLE_STYLE", tableStyleId: cmd.tableStyleId }];
76276
76354
  }
76355
+ function inverseRenameSheet(cmd) {
76356
+ return [
76357
+ {
76358
+ type: "RENAME_SHEET",
76359
+ sheetId: cmd.sheetId,
76360
+ oldName: cmd.newName,
76361
+ newName: cmd.oldName,
76362
+ },
76363
+ ];
76364
+ }
76277
76365
 
76278
76366
  const numberFormatMenuRegistry = new Registry();
76279
76367
  numberFormatMenuRegistry
@@ -76872,8 +76960,9 @@ topbarMenuRegistry
76872
76960
  sequence: 40,
76873
76961
  separator: true,
76874
76962
  })
76875
- .addChild("data_sources_data", ["data"], (env) => {
76963
+ .addChild("pivot_data_sources", ["data"], (env) => {
76876
76964
  const sequence = 50;
76965
+ const numberOfPivots = env.model.getters.getPivotIds().length;
76877
76966
  return env.model.getters.getPivotIds().map((pivotId, index) => {
76878
76967
  const highlightProvider = {
76879
76968
  get highlights() {
@@ -76883,7 +76972,7 @@ topbarMenuRegistry
76883
76972
  return {
76884
76973
  id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
76885
76974
  name: env.model.getters.getPivotDisplayName(pivotId),
76886
- sequence: sequence + index,
76975
+ sequence: sequence + index / numberOfPivots,
76887
76976
  isReadonlyAllowed: true,
76888
76977
  execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
76889
76978
  isEnabled: (env) => !env.isSmall,
@@ -83003,7 +83092,7 @@ function figureCoordinates(headers, anchor, offset) {
83003
83092
  for (const [headerIndex, header] of headers.slice(anchor).entries()) {
83004
83093
  if (currentPosition <= offset && offset < currentPosition + header.size) {
83005
83094
  return {
83006
- index: headerIndex,
83095
+ index: anchor + headerIndex,
83007
83096
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
83008
83097
  };
83009
83098
  }
@@ -84701,6 +84790,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
84701
84790
  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
84791
 
84703
84792
 
84704
- __info__.version = "18.4.8";
84705
- __info__.date = "2025-08-26T10:14:08.954Z";
84706
- __info__.hash = "746217a";
84793
+ __info__.version = "18.4.10";
84794
+ __info__.date = "2025-09-11T08:45:39.178Z";
84795
+ __info__.hash = "15a11a4";