@odoo/o-spreadsheet 18.4.7 → 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.7
6
- * @date 2025-08-21T06:42:12.438Z
7
- * @hash d5eb3a6
5
+ * @version 18.4.9
6
+ * @date 2025-09-05T07:38:32.126Z
7
+ * @hash a261873
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -2644,6 +2644,7 @@
2644
2644
  "AUTOFILL_CELL",
2645
2645
  "SET_BORDER",
2646
2646
  "SET_ZONE_BORDERS",
2647
+ "SET_BORDERS_ON_TARGET",
2647
2648
  ]);
2648
2649
  const readonlyAllowedCommands = new Set([
2649
2650
  "START",
@@ -3990,6 +3991,10 @@
3990
3991
  }
3991
3992
  return true;
3992
3993
  }
3994
+ const noValidInputErrorMessage = _t("[[FUNCTION_NAME]] has no valid input data.");
3995
+ function emptyDataErrorMessage(argName) {
3996
+ return _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", { argName });
3997
+ }
3993
3998
 
3994
3999
  function tokenizeFormat(str) {
3995
4000
  const chars = new TokenizingChars(str);
@@ -6591,40 +6596,44 @@
6591
6596
  };
6592
6597
  }
6593
6598
  function getRangeAdapter(cmd) {
6594
- switch (cmd.type) {
6595
- case "REMOVE_COLUMNS_ROWS":
6596
- return {
6597
- applyChange: getApplyRangeChangeRemoveColRow(cmd),
6598
- sheetId: cmd.sheetId,
6599
- sheetName: cmd.sheetName,
6600
- };
6601
- case "ADD_COLUMNS_ROWS":
6602
- return {
6603
- applyChange: getApplyRangeChangeAddColRow(cmd),
6604
- sheetId: cmd.sheetId,
6605
- sheetName: cmd.sheetName,
6606
- };
6607
- case "DELETE_SHEET":
6608
- return {
6609
- applyChange: getApplyRangeChangeDeleteSheet(cmd),
6610
- sheetId: cmd.sheetId,
6611
- sheetName: cmd.sheetName,
6612
- };
6613
- case "RENAME_SHEET":
6614
- return {
6615
- applyChange: getApplyRangeChangeRenameSheet(cmd),
6616
- sheetId: cmd.sheetId,
6617
- sheetName: cmd.oldName,
6618
- };
6619
- case "MOVE_RANGES":
6620
- return {
6621
- applyChange: getApplyRangeChangeMoveRange(cmd),
6622
- sheetId: cmd.sheetId,
6623
- sheetName: cmd.sheetName,
6624
- };
6599
+ return rangeAdapterRegistry.get(cmd.type)?.(cmd);
6600
+ }
6601
+ class RangeAdapterRegistry extends Registry {
6602
+ add(cmdType, fn) {
6603
+ super.add(cmdType, fn);
6604
+ return this;
6605
+ }
6606
+ get(cmdType) {
6607
+ return this.content[cmdType];
6625
6608
  }
6626
- return undefined;
6627
6609
  }
6610
+ const rangeAdapterRegistry = new RangeAdapterRegistry();
6611
+ rangeAdapterRegistry
6612
+ .add("REMOVE_COLUMNS_ROWS", (cmd) => ({
6613
+ applyChange: getApplyRangeChangeRemoveColRow(cmd),
6614
+ sheetId: cmd.sheetId,
6615
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6616
+ }))
6617
+ .add("ADD_COLUMNS_ROWS", (cmd) => ({
6618
+ applyChange: getApplyRangeChangeAddColRow(cmd),
6619
+ sheetId: cmd.sheetId,
6620
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6621
+ }))
6622
+ .add("DELETE_SHEET", (cmd) => ({
6623
+ applyChange: getApplyRangeChangeDeleteSheet(cmd),
6624
+ sheetId: cmd.sheetId,
6625
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6626
+ }))
6627
+ .add("RENAME_SHEET", (cmd) => ({
6628
+ applyChange: getApplyRangeChangeRenameSheet(cmd),
6629
+ sheetId: cmd.sheetId,
6630
+ sheetName: { old: cmd.oldName, current: cmd.newName },
6631
+ }))
6632
+ .add("MOVE_RANGES", (cmd) => ({
6633
+ applyChange: getApplyRangeChangeMoveRange(cmd),
6634
+ sheetId: cmd.sheetId,
6635
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6636
+ }));
6628
6637
  function getApplyRangeChangeRemoveColRow(cmd) {
6629
6638
  const start = cmd.dimension === "COL" ? "left" : "top";
6630
6639
  const end = cmd.dimension === "COL" ? "right" : "bottom";
@@ -7247,14 +7256,11 @@
7247
7256
  const width = content[0].length, height = content.length;
7248
7257
  return target.map((t) => splitZoneForPaste(t, width, height)).flat();
7249
7258
  }
7250
- function parseOSClipboardContent(content, clipboardId) {
7259
+ function parseOSClipboardContent(content) {
7251
7260
  let spreadsheetContent = undefined;
7252
7261
  if (content[ClipboardMIMEType.Html]) {
7253
7262
  const htmlDocument = new DOMParser().parseFromString(content[ClipboardMIMEType.Html], "text/html");
7254
- const oSheetClipboardData = htmlDocument
7255
- .querySelector("div")
7256
- ?.getAttribute("data-osheet-clipboard");
7257
- spreadsheetContent = oSheetClipboardData && JSON.parse(oSheetClipboardData);
7263
+ spreadsheetContent = getOSheetDataFromHTML(htmlDocument);
7258
7264
  }
7259
7265
  const textContent = content[ClipboardMIMEType.PlainText] || "";
7260
7266
  let imageBlob = undefined;
@@ -7273,6 +7279,17 @@
7273
7279
  };
7274
7280
  return osClipboardContent;
7275
7281
  }
7282
+ function getOSheetDataFromHTML(htmlDocument) {
7283
+ const attributes = [...htmlDocument.documentElement.attributes];
7284
+ // Check if it's a Microsoft Office clipboard data (it will have some namespaces defined in the root element)
7285
+ if (attributes.some((attr) => attr.value.includes("microsoft"))) {
7286
+ return undefined;
7287
+ }
7288
+ const oSheetClipboardData = htmlDocument
7289
+ .querySelector("div")
7290
+ ?.getAttribute("data-osheet-clipboard");
7291
+ return oSheetClipboardData && JSON.parse(oSheetClipboardData);
7292
+ }
7276
7293
  /**
7277
7294
  * Applies each clipboard handler to paste its corresponding data into the target.
7278
7295
  */
@@ -7993,8 +8010,11 @@
7993
8010
  // (a) Swap 2 rows. This multiply the determinant by -1.
7994
8011
  // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
7995
8012
  // (c) Add to a row a multiple of another row. This does not change the determinant.
8013
+ if (M.length < 1 || M[0].length < 1) {
8014
+ throw new Error("invertMatrix: an empty matrix cannot be inverted.");
8015
+ }
7996
8016
  if (M.length !== M[0].length) {
7997
- throw new EvaluationError(_t("Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible"));
8017
+ throw new Error("invertMatrix: only square matrices are invertible");
7998
8018
  }
7999
8019
  let determinant = 1;
8000
8020
  const dim = M.length;
@@ -8063,8 +8083,11 @@
8063
8083
  * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
8064
8084
  */
8065
8085
  function multiplyMatrices(matrix1, matrix2) {
8086
+ if (matrix1.length < 1 || matrix2.length < 1) {
8087
+ throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
8088
+ }
8066
8089
  if (matrix1.length !== matrix2[0].length) {
8067
- throw new EvaluationError(_t("Cannot multiply matrices : incompatible matrices size."));
8090
+ throw new Error("multiplyMatrices: incompatible matrices size.");
8068
8091
  }
8069
8092
  const rowsM1 = matrix1[0].length;
8070
8093
  const colsM2 = matrix2.length;
@@ -8090,7 +8113,7 @@
8090
8113
  return arg;
8091
8114
  }
8092
8115
  if (!isSingleElementMatrix(arg)) {
8093
- throw new EvaluationError(_t("The value should be a scalar or a 1x1 matrix"));
8116
+ throw new Error("The value should be a scalar or a 1x1 matrix");
8094
8117
  }
8095
8118
  return arg[0][0];
8096
8119
  }
@@ -11229,6 +11252,9 @@ stores.inject(MyMetaStore, storeInstance);
11229
11252
  compute: function (matrix1, matrix2) {
11230
11253
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
11231
11254
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
11255
+ if (_matrix1.length === 0 || _matrix2.length === 0) {
11256
+ return new EvaluationError(_t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
11257
+ }
11232
11258
  if (_matrix1.length !== _matrix2[0].length) {
11233
11259
  return new EvaluationError(_t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
11234
11260
  number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
@@ -12841,7 +12867,7 @@ stores.inject(MyMetaStore, storeInstance);
12841
12867
  count++;
12842
12868
  }
12843
12869
  });
12844
- assert(count !== 0, _t("[[FUNCTION_NAME]] has no valid input data."));
12870
+ assert(count !== 0, noValidInputErrorMessage);
12845
12871
  if (!isInclusive) {
12846
12872
  // 2nd argument must be between 1/(n+1) and n/(n+1) with n the number of data
12847
12873
  assert(1 / (count + 1) <= _percent && _percent <= count / (count + 1), _t("Function [[FUNCTION_NAME]] parameter 2 value is out of range."));
@@ -13116,6 +13142,9 @@ stores.inject(MyMetaStore, storeInstance);
13116
13142
  ],
13117
13143
  compute: function (x, dataY, dataX) {
13118
13144
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13145
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13146
+ return new NotAvailableError(noValidInputErrorMessage);
13147
+ }
13119
13148
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
13120
13149
  },
13121
13150
  isExported: true,
@@ -13132,6 +13161,9 @@ stores.inject(MyMetaStore, storeInstance);
13132
13161
  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.")),
13133
13162
  ],
13134
13163
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13164
+ if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13165
+ return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13166
+ }
13135
13167
  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)));
13136
13168
  },
13137
13169
  };
@@ -13146,6 +13178,9 @@ stores.inject(MyMetaStore, storeInstance);
13146
13178
  ],
13147
13179
  compute: function (dataY, dataX) {
13148
13180
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13181
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13182
+ return new NotAvailableError(noValidInputErrorMessage);
13183
+ }
13149
13184
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
13150
13185
  return intercept;
13151
13186
  },
@@ -13178,7 +13213,7 @@ stores.inject(MyMetaStore, storeInstance);
13178
13213
  });
13179
13214
  const result = largests.shift();
13180
13215
  if (result === undefined) {
13181
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
13216
+ return new EvaluationError(noValidInputErrorMessage);
13182
13217
  }
13183
13218
  if (count < _n) {
13184
13219
  return new EvaluationError(_t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
@@ -13199,6 +13234,9 @@ stores.inject(MyMetaStore, storeInstance);
13199
13234
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13200
13235
  ],
13201
13236
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13237
+ if (dataY.length === 0 || dataY[0].length === 0) {
13238
+ return new EvaluationError(emptyDataErrorMessage("data_y"));
13239
+ }
13202
13240
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
13203
13241
  },
13204
13242
  isExported: true,
@@ -13215,6 +13253,9 @@ stores.inject(MyMetaStore, storeInstance);
13215
13253
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13216
13254
  ],
13217
13255
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13256
+ if (dataY.length === 0 || dataY[0].length === 0) {
13257
+ return new EvaluationError(emptyDataErrorMessage("data_y"));
13258
+ }
13218
13259
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
13219
13260
  for (let i = 0; i < coeffs.length; i++) {
13220
13261
  coeffs[i][0] = Math.exp(coeffs[i][0]);
@@ -13236,8 +13277,8 @@ stores.inject(MyMetaStore, storeInstance);
13236
13277
  const flatX = dataX.flat();
13237
13278
  const flatY = dataY.flat();
13238
13279
  assertSameNumberOfElements(flatX, flatY);
13239
- if (flatX.length === 0) {
13240
- return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13280
+ if (flatX.length === 0 || flatY.length === 0) {
13281
+ return new NotAvailableError(noValidInputErrorMessage);
13241
13282
  }
13242
13283
  const n = flatX.length;
13243
13284
  let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
@@ -13402,11 +13443,8 @@ stores.inject(MyMetaStore, storeInstance);
13402
13443
  // -----------------------------------------------------------------------------
13403
13444
  function pearson(dataY, dataX) {
13404
13445
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13405
- if (flatDataX.length === 0) {
13406
- throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13407
- }
13408
- if (flatDataX.length < 2) {
13409
- throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
13446
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13447
+ return new NotAvailableError(noValidInputErrorMessage);
13410
13448
  }
13411
13449
  const n = flatDataX.length;
13412
13450
  let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
@@ -13496,6 +13534,9 @@ stores.inject(MyMetaStore, storeInstance);
13496
13534
  ],
13497
13535
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13498
13536
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13537
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13538
+ return new NotAvailableError(noValidInputErrorMessage);
13539
+ }
13499
13540
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
13500
13541
  },
13501
13542
  isExported: false,
@@ -13515,6 +13556,9 @@ stores.inject(MyMetaStore, storeInstance);
13515
13556
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13516
13557
  const _order = toNumber(order, this.locale);
13517
13558
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13559
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13560
+ return new NotAvailableError(noValidInputErrorMessage);
13561
+ }
13518
13562
  const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
13519
13563
  return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
13520
13564
  },
@@ -13616,7 +13660,11 @@ stores.inject(MyMetaStore, storeInstance);
13616
13660
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13617
13661
  ],
13618
13662
  compute: function (dataY, dataX) {
13619
- return Math.pow(pearson(dataX, dataY), 2.0);
13663
+ const value = pearson(dataY, dataX);
13664
+ if (value instanceof Error) {
13665
+ throw value;
13666
+ }
13667
+ return Math.pow(value, 2.0);
13620
13668
  },
13621
13669
  isExported: true,
13622
13670
  };
@@ -13631,6 +13679,9 @@ stores.inject(MyMetaStore, storeInstance);
13631
13679
  ],
13632
13680
  compute: function (dataY, dataX) {
13633
13681
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13682
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13683
+ return new NotAvailableError(noValidInputErrorMessage);
13684
+ }
13634
13685
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
13635
13686
  return slope;
13636
13687
  },
@@ -13663,7 +13714,7 @@ stores.inject(MyMetaStore, storeInstance);
13663
13714
  });
13664
13715
  const result = largests.pop();
13665
13716
  if (result === undefined) {
13666
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
13717
+ return new EvaluationError(noValidInputErrorMessage);
13667
13718
  }
13668
13719
  if (count < _n) {
13669
13720
  return new EvaluationError(_t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
@@ -13683,6 +13734,9 @@ stores.inject(MyMetaStore, storeInstance);
13683
13734
  ],
13684
13735
  compute: function (dataX, dataY) {
13685
13736
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13737
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13738
+ return new NotAvailableError(noValidInputErrorMessage);
13739
+ }
13686
13740
  const n = flatDataX.length;
13687
13741
  const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
13688
13742
  order.sort((a, b) => a[0] - b[0]);
@@ -13793,6 +13847,9 @@ stores.inject(MyMetaStore, storeInstance);
13793
13847
  ],
13794
13848
  compute: function (dataY, dataX) {
13795
13849
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13850
+ if (flatDataX.length === 0 || flatDataY.length === 0) {
13851
+ return new NotAvailableError(noValidInputErrorMessage);
13852
+ }
13796
13853
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
13797
13854
  return data[1][2];
13798
13855
  },
@@ -13810,6 +13867,9 @@ stores.inject(MyMetaStore, storeInstance);
13810
13867
  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.")),
13811
13868
  ],
13812
13869
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13870
+ if (knownDataY.length === 0 || knownDataY[0].length === 0) {
13871
+ return new EvaluationError(emptyDataErrorMessage("known_data_y"));
13872
+ }
13813
13873
  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));
13814
13874
  },
13815
13875
  };
@@ -18725,7 +18785,7 @@ stores.inject(MyMetaStore, storeInstance);
18725
18785
  compute: function (...logicalExpressions) {
18726
18786
  const { result, foundBoolean } = boolAnd(logicalExpressions);
18727
18787
  if (!foundBoolean) {
18728
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18788
+ return new EvaluationError(noValidInputErrorMessage);
18729
18789
  }
18730
18790
  return result;
18731
18791
  },
@@ -18851,7 +18911,7 @@ stores.inject(MyMetaStore, storeInstance);
18851
18911
  compute: function (...logicalExpressions) {
18852
18912
  const { result, foundBoolean } = boolOr(logicalExpressions);
18853
18913
  if (!foundBoolean) {
18854
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18914
+ return new EvaluationError(noValidInputErrorMessage);
18855
18915
  }
18856
18916
  return result;
18857
18917
  },
@@ -18914,7 +18974,7 @@ stores.inject(MyMetaStore, storeInstance);
18914
18974
  return true; // no stop condition
18915
18975
  });
18916
18976
  if (!foundBoolean) {
18917
- return new EvaluationError(_t("[[FUNCTION_NAME]] has no valid input data."));
18977
+ return new EvaluationError(noValidInputErrorMessage);
18918
18978
  }
18919
18979
  return acc;
18920
18980
  },
@@ -21378,7 +21438,7 @@ stores.inject(MyMetaStore, storeInstance);
21378
21438
  function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
21379
21439
  const sheetName = splitReference(sheetXC).sheetName;
21380
21440
  if (sheetName
21381
- ? !isSheetNameEqual(sheetName, applyChange.sheetName)
21441
+ ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
21382
21442
  : defaultSheetId !== applyChange.sheetId) {
21383
21443
  return sheetXC;
21384
21444
  }
@@ -21395,7 +21455,7 @@ stores.inject(MyMetaStore, storeInstance);
21395
21455
  }
21396
21456
  function getSheetNameGetter(applyChange) {
21397
21457
  return (sheetId) => {
21398
- return sheetId === applyChange.sheetId ? applyChange.sheetName : "";
21458
+ return sheetId === applyChange.sheetId ? applyChange.sheetName.current : "";
21399
21459
  };
21400
21460
  }
21401
21461
  function defaultGetSheetSize(sheetId) {
@@ -27013,10 +27073,6 @@ stores.inject(MyMetaStore, storeInstance);
27013
27073
  };
27014
27074
  }
27015
27075
  getDefinitionForExcel() {
27016
- // Excel does not support aggregating labels
27017
- if (this.aggregated) {
27018
- return undefined;
27019
- }
27020
27076
  const dataSets = this.dataSets
27021
27077
  .map((ds) => toExcelDataset(this.getters, ds))
27022
27078
  .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
@@ -27390,9 +27446,13 @@ stores.inject(MyMetaStore, storeInstance);
27390
27446
  : undefined,
27391
27447
  };
27392
27448
  }
27393
- updateRanges(applyChange) {
27449
+ updateRanges(applyChange, sheetId, adaptSheetName) {
27394
27450
  const dataRange = adaptChartRange(this.dataRange, applyChange);
27395
- const adaptFormula = (formula) => this.getters.adaptFormulaStringDependencies(this.sheetId, formula, applyChange);
27451
+ const adaptFormula = (formula) => adaptFormulaStringRanges(this.sheetId, formula, {
27452
+ applyChange,
27453
+ sheetId,
27454
+ sheetName: adaptSheetName,
27455
+ });
27396
27456
  const sectionRule = adaptSectionRuleFormulas(this.sectionRule, adaptFormula);
27397
27457
  const definition = this.getDefinitionWithSpecificRanges(dataRange, sectionRule);
27398
27458
  return new GaugeChart(definition, this.sheetId, this.getters);
@@ -28331,10 +28391,6 @@ stores.inject(MyMetaStore, storeInstance);
28331
28391
  return new ScatterChart(definition, this.sheetId, this.getters);
28332
28392
  }
28333
28393
  getDefinitionForExcel() {
28334
- // Excel does not support aggregating labels
28335
- if (this.aggregated) {
28336
- return undefined;
28337
- }
28338
28394
  const dataSets = this.dataSets
28339
28395
  .map((ds) => toExcelDataset(this.getters, ds))
28340
28396
  .filter((ds) => ds.range !== "");
@@ -33719,6 +33775,9 @@ stores.inject(MyMetaStore, storeInstance);
33719
33775
  this.contentHelper.removeSelection();
33720
33776
  }
33721
33777
  onMouseup() {
33778
+ if (this.env.model.getters.isReadonly()) {
33779
+ return;
33780
+ }
33722
33781
  const selection = this.contentHelper.getCurrentSelection();
33723
33782
  if (selection.start !== selection.end) {
33724
33783
  this.props.composerStore.hoverToken(undefined);
@@ -38182,9 +38241,9 @@ stores.inject(MyMetaStore, storeInstance);
38182
38241
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
38183
38242
  continue;
38184
38243
  operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.operator];
38185
- values.push(rule.formula[0]);
38244
+ values.push(prefixFormula(rule.formula[0]));
38186
38245
  if (rule.formula.length === 2) {
38187
- values.push(rule.formula[1]);
38246
+ values.push(prefixFormula(rule.formula[1]));
38188
38247
  }
38189
38248
  break;
38190
38249
  }
@@ -38342,6 +38401,11 @@ stores.inject(MyMetaStore, storeInstance);
38342
38401
  ? ICON_SETS[iconSet].neutral
38343
38402
  : ICON_SETS[iconSet].good;
38344
38403
  }
38404
+ /** Prefix the string by "=" if the string looks like a formula */
38405
+ function prefixFormula(formula) {
38406
+ const tokens = tokenize(formula);
38407
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
38408
+ }
38345
38409
  // ---------------------------------------------------------------------------
38346
38410
  // Warnings
38347
38411
  // ---------------------------------------------------------------------------
@@ -38624,7 +38688,7 @@ stores.inject(MyMetaStore, storeInstance);
38624
38688
  function getRowPosition(rowIndex, sheetData) {
38625
38689
  let position = 0;
38626
38690
  for (let i = 0; i < rowIndex; i++) {
38627
- const rowAtIndex = sheetData.rows[i];
38691
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
38628
38692
  if (rowAtIndex?.height) {
38629
38693
  position += rowAtIndex.height;
38630
38694
  }
@@ -38779,8 +38843,8 @@ stores.inject(MyMetaStore, storeInstance);
38779
38843
  }
38780
38844
  function convertAnchor(XLSXanchor) {
38781
38845
  const offset = {
38782
- x: convertEMUToDotValue(XLSXanchor.colOffset),
38783
- y: convertEMUToDotValue(XLSXanchor.rowOffset),
38846
+ x: convertEMUToDotValue(XLSXanchor.colOffset) - FIGURE_BORDER_WIDTH,
38847
+ y: convertEMUToDotValue(XLSXanchor.rowOffset) - FIGURE_BORDER_WIDTH,
38784
38848
  };
38785
38849
  return { col: XLSXanchor.col, row: XLSXanchor.row, offset };
38786
38850
  }
@@ -39163,8 +39227,12 @@ stores.inject(MyMetaStore, storeInstance);
39163
39227
  dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
39164
39228
  dims[1] = Math.max(dims[1], row.index);
39165
39229
  }
39166
- dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
39167
- dims[1] = Math.max(dims[1], EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
39230
+ for (const fig of sheet.figures) {
39231
+ dims[0] = Math.max(dims[0], fig.anchors[fig.anchors.length - 1]?.col ?? 0);
39232
+ dims[1] = Math.max(dims[1], fig.anchors[fig.anchors.length - 1]?.row ?? 0);
39233
+ }
39234
+ dims[0] = Math.max(dims[0] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
39235
+ dims[1] = Math.max(dims[1] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
39168
39236
  return dims;
39169
39237
  }
39170
39238
  /**
@@ -40867,7 +40935,7 @@ stores.inject(MyMetaStore, storeInstance);
40867
40935
  return relsFile;
40868
40936
  }
40869
40937
 
40870
- const EXCEL_IMPORT_VERSION = "18.4.1";
40938
+ const EXCEL_IMPORT_VERSION = "18.4.2";
40871
40939
  class XlsxReader {
40872
40940
  warningManager;
40873
40941
  xmls;
@@ -44412,7 +44480,7 @@ stores.inject(MyMetaStore, storeInstance);
44412
44480
  const reinsertDynamicPivotMenu = {
44413
44481
  id: "reinsert_dynamic_pivot",
44414
44482
  name: _t("Re-insert dynamic pivot"),
44415
- sequence: 1020,
44483
+ sequence: 60,
44416
44484
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
44417
44485
  children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
44418
44486
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -44420,7 +44488,7 @@ stores.inject(MyMetaStore, storeInstance);
44420
44488
  const reinsertStaticPivotMenu = {
44421
44489
  id: "reinsert_static_pivot",
44422
44490
  name: _t("Re-insert static pivot"),
44423
- sequence: 1020,
44491
+ sequence: 70,
44424
44492
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
44425
44493
  children: [REINSERT_STATIC_PIVOT_CHILDREN],
44426
44494
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -58691,7 +58759,8 @@ stores.inject(MyMetaStore, storeInstance);
58691
58759
  * the type of change that occurred.
58692
58760
  *
58693
58761
  * @param applyChange a function that, when called, will adapt the range according to the change on the grid
58694
- * @param sheetId an optional sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
58762
+ * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
58763
+ * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
58695
58764
  */
58696
58765
  adaptRanges(applyChange, sheetId, sheetName) { }
58697
58766
  /**
@@ -59294,9 +59363,7 @@ stores.inject(MyMetaStore, storeInstance);
59294
59363
  for (const cell of Object.values(this.cells[sheet] || {})) {
59295
59364
  if (cell.isFormula) {
59296
59365
  for (const range of cell.compiledFormula.dependencies) {
59297
- if (!sheetId ||
59298
- range.sheetId === sheetId ||
59299
- (sheetName && range.invalidSheetName === sheetName)) {
59366
+ if (range.sheetId === sheetId || range.invalidSheetName === sheetName.old) {
59300
59367
  const change = applyChange(range);
59301
59368
  if (change.changeType !== "NONE") {
59302
59369
  this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
@@ -59912,9 +59979,9 @@ stores.inject(MyMetaStore, storeInstance);
59912
59979
  charts = {};
59913
59980
  createChart = chartFactory(this.getters);
59914
59981
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
59915
- adaptRanges(applyChange) {
59982
+ adaptRanges(applyChange, sheetId, adaptSheetName) {
59916
59983
  for (const [chartId, chart] of Object.entries(this.charts)) {
59917
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
59984
+ this.history.update("charts", chartId, chart?.updateRanges(applyChange, sheetId, adaptSheetName));
59918
59985
  }
59919
59986
  }
59920
59987
  // ---------------------------------------------------------------------------
@@ -60177,7 +60244,7 @@ stores.inject(MyMetaStore, storeInstance);
60177
60244
  }
60178
60245
  }
60179
60246
  }
60180
- adaptRanges(applyChange, sheetId, sheetName) {
60247
+ adaptRanges(applyChange, sheetId) {
60181
60248
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
60182
60249
  for (const sheetId of sheetIds) {
60183
60250
  this.adaptCFRanges(sheetId, applyChange);
@@ -60559,11 +60626,8 @@ stores.inject(MyMetaStore, storeInstance);
60559
60626
  "getValidationRuleForCell",
60560
60627
  ];
60561
60628
  rules = {};
60562
- adaptRanges(applyChange, sheetId, sheetName) {
60563
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.rules);
60564
- for (const sheetId of sheetIds) {
60565
- this.adaptDVRanges(sheetId, applyChange);
60566
- }
60629
+ adaptRanges(applyChange, sheetId) {
60630
+ this.adaptDVRanges(sheetId, applyChange);
60567
60631
  this.adaptDVFormulas(applyChange);
60568
60632
  }
60569
60633
  adaptDVFormulas(applyChange) {
@@ -60853,9 +60917,6 @@ stores.inject(MyMetaStore, storeInstance);
60853
60917
  // Command Handling
60854
60918
  // ---------------------------------------------------------------------------
60855
60919
  adaptRanges(applyChange, sheetId) {
60856
- if (!sheetId) {
60857
- return;
60858
- }
60859
60920
  for (const figure of this.getFigures(sheetId)) {
60860
60921
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
60861
60922
  left: figure.col,
@@ -61664,11 +61725,8 @@ stores.inject(MyMetaStore, storeInstance);
61664
61725
  break;
61665
61726
  }
61666
61727
  }
61667
- adaptRanges(applyChange, sheetId, sheetName) {
61668
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.merges);
61669
- for (const sheetId of sheetIds) {
61670
- this.applyRangeChangeOnSheet(sheetId, applyChange);
61671
- }
61728
+ adaptRanges(applyChange, sheetId) {
61729
+ this.applyRangeChangeOnSheet(sheetId, applyChange);
61672
61730
  }
61673
61731
  // ---------------------------------------------------------------------------
61674
61732
  // Getters
@@ -63173,12 +63231,9 @@ stores.inject(MyMetaStore, storeInstance);
63173
63231
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
63174
63232
  tables = {};
63175
63233
  nextTableId = 1;
63176
- adaptRanges(applyChange, sheetId, sheetName) {
63177
- const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
63178
- for (const sheetId of sheetIds) {
63179
- for (const table of this.getCoreTables(sheetId)) {
63180
- this.applyRangeChangeOnTable(sheetId, table, applyChange);
63181
- }
63234
+ adaptRanges(applyChange, sheetId) {
63235
+ for (const table of this.getCoreTables(sheetId)) {
63236
+ this.applyRangeChangeOnTable(sheetId, table, applyChange);
63182
63237
  }
63183
63238
  }
63184
63239
  allowDispatch(cmd) {
@@ -64141,7 +64196,7 @@ stores.inject(MyMetaStore, storeInstance);
64141
64196
  }
64142
64197
  }
64143
64198
  }
64144
- adaptRanges(applyChange, sheetId, sheetName) {
64199
+ adaptRanges(applyChange) {
64145
64200
  for (const sheetId in this.compiledMeasureFormulas) {
64146
64201
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64147
64202
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -68542,7 +68597,7 @@ stores.inject(MyMetaStore, storeInstance);
68542
68597
  if (!result) {
68543
68598
  return EMPTY_PIVOT_CELL;
68544
68599
  }
68545
- const { functionName, args } = result;
68600
+ let { functionName, args } = result;
68546
68601
  const formulaId = args[0];
68547
68602
  if (!formulaId) {
68548
68603
  return EMPTY_PIVOT_CELL;
@@ -68577,6 +68632,9 @@ stores.inject(MyMetaStore, storeInstance);
68577
68632
  return pivotCells[pivotCol][pivotRow];
68578
68633
  }
68579
68634
  try {
68635
+ const offsetRow = position.row - mainPosition.row;
68636
+ const offsetCol = position.col - mainPosition.col;
68637
+ args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
68580
68638
  if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
68581
68639
  const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
68582
68640
  return {
@@ -70185,7 +70243,8 @@ stores.inject(MyMetaStore, storeInstance);
70185
70243
  // If the executed command is not in the registry, we skip it
70186
70244
  // because we know there won't be any transformation impacting the
70187
70245
  // commands to transform.
70188
- if (possibleTransformations.has(executedCommand.type)) {
70246
+ if (possibleTransformations.has(executedCommand.type) ||
70247
+ rangeAdapterRegistry.contains(executedCommand.type)) {
70189
70248
  transformedCommands = transformedCommands.reduce((acc, cmd) => {
70190
70249
  const transformed = transform(cmd, executedCommand);
70191
70250
  if (transformed) {
@@ -76177,7 +76236,8 @@ stores.inject(MyMetaStore, storeInstance);
76177
76236
  .add("HIDE_COLUMNS_ROWS", inverseHideColumnsRows)
76178
76237
  .add("UNHIDE_COLUMNS_ROWS", inverseUnhideColumnsRows)
76179
76238
  .add("CREATE_TABLE_STYLE", inverseCreateTableStyle)
76180
- .add("ADD_PIVOT", inverseAddPivot);
76239
+ .add("ADD_PIVOT", inverseAddPivot)
76240
+ .add("RENAME_SHEET", inverseRenameSheet);
76181
76241
  for (const cmd of coreTypes.values()) {
76182
76242
  if (!inverseCommandRegistry.contains(cmd)) {
76183
76243
  inverseCommandRegistry.add(cmd, identity);
@@ -76275,6 +76335,16 @@ stores.inject(MyMetaStore, storeInstance);
76275
76335
  function inverseCreateTableStyle(cmd) {
76276
76336
  return [{ type: "REMOVE_TABLE_STYLE", tableStyleId: cmd.tableStyleId }];
76277
76337
  }
76338
+ function inverseRenameSheet(cmd) {
76339
+ return [
76340
+ {
76341
+ type: "RENAME_SHEET",
76342
+ sheetId: cmd.sheetId,
76343
+ oldName: cmd.newName,
76344
+ newName: cmd.oldName,
76345
+ },
76346
+ ];
76347
+ }
76278
76348
 
76279
76349
  const numberFormatMenuRegistry = new Registry();
76280
76350
  numberFormatMenuRegistry
@@ -76873,8 +76943,9 @@ stores.inject(MyMetaStore, storeInstance);
76873
76943
  sequence: 40,
76874
76944
  separator: true,
76875
76945
  })
76876
- .addChild("data_sources_data", ["data"], (env) => {
76946
+ .addChild("pivot_data_sources", ["data"], (env) => {
76877
76947
  const sequence = 50;
76948
+ const numberOfPivots = env.model.getters.getPivotIds().length;
76878
76949
  return env.model.getters.getPivotIds().map((pivotId, index) => {
76879
76950
  const highlightProvider = {
76880
76951
  get highlights() {
@@ -76884,7 +76955,7 @@ stores.inject(MyMetaStore, storeInstance);
76884
76955
  return {
76885
76956
  id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
76886
76957
  name: env.model.getters.getPivotDisplayName(pivotId),
76887
- sequence: sequence + index,
76958
+ sequence: sequence + index / numberOfPivots,
76888
76959
  isReadonlyAllowed: true,
76889
76960
  execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
76890
76961
  isEnabled: (env) => !env.isSmall,
@@ -83004,7 +83075,7 @@ stores.inject(MyMetaStore, storeInstance);
83004
83075
  for (const [headerIndex, header] of headers.slice(anchor).entries()) {
83005
83076
  if (currentPosition <= offset && offset < currentPosition + header.size) {
83006
83077
  return {
83007
- index: headerIndex,
83078
+ index: anchor + headerIndex,
83008
83079
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
83009
83080
  };
83010
83081
  }
@@ -84000,7 +84071,7 @@ stores.inject(MyMetaStore, storeInstance);
84000
84071
  handlers = [];
84001
84072
  uiHandlers = [];
84002
84073
  coreHandlers = [];
84003
- constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
84074
+ constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
84004
84075
  const start = performance.now();
84005
84076
  console.debug("##### Model creation #####");
84006
84077
  super();
@@ -84750,9 +84821,9 @@ stores.inject(MyMetaStore, storeInstance);
84750
84821
  exports.tokenize = tokenize;
84751
84822
 
84752
84823
 
84753
- __info__.version = "18.4.7";
84754
- __info__.date = "2025-08-21T06:42:12.438Z";
84755
- __info__.hash = "d5eb3a6";
84824
+ __info__.version = "18.4.9";
84825
+ __info__.date = "2025-09-05T07:38:32.126Z";
84826
+ __info__.hash = "a261873";
84756
84827
 
84757
84828
 
84758
84829
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);