@odoo/o-spreadsheet 18.3.17 → 18.3.19

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.17
6
- * @date 2025-08-21T06:40:44.469Z
7
- * @hash ab02b0c
5
+ * @version 18.3.19
6
+ * @date 2025-09-05T07:38:30.661Z
7
+ * @hash 77fd307
8
8
  */
9
9
 
10
10
  'use strict';
@@ -3499,6 +3499,7 @@ const invalidateBordersCommands = new Set([
3499
3499
  "AUTOFILL_CELL",
3500
3500
  "SET_BORDER",
3501
3501
  "SET_ZONE_BORDERS",
3502
+ "SET_BORDERS_ON_TARGET",
3502
3503
  ]);
3503
3504
  const readonlyAllowedCommands = new Set([
3504
3505
  "START",
@@ -6444,40 +6445,44 @@ function orderRange(range) {
6444
6445
  };
6445
6446
  }
6446
6447
  function getRangeAdapter(cmd) {
6447
- switch (cmd.type) {
6448
- case "REMOVE_COLUMNS_ROWS":
6449
- return {
6450
- applyChange: getApplyRangeChangeRemoveColRow(cmd),
6451
- sheetId: cmd.sheetId,
6452
- sheetName: cmd.sheetName,
6453
- };
6454
- case "ADD_COLUMNS_ROWS":
6455
- return {
6456
- applyChange: getApplyRangeChangeAddColRow(cmd),
6457
- sheetId: cmd.sheetId,
6458
- sheetName: cmd.sheetName,
6459
- };
6460
- case "DELETE_SHEET":
6461
- return {
6462
- applyChange: getApplyRangeChangeDeleteSheet(cmd),
6463
- sheetId: cmd.sheetId,
6464
- sheetName: cmd.sheetName,
6465
- };
6466
- case "RENAME_SHEET":
6467
- return {
6468
- applyChange: getApplyRangeChangeRenameSheet(cmd),
6469
- sheetId: cmd.sheetId,
6470
- sheetName: cmd.oldName,
6471
- };
6472
- case "MOVE_RANGES":
6473
- return {
6474
- applyChange: getApplyRangeChangeMoveRange(cmd),
6475
- sheetId: cmd.sheetId,
6476
- sheetName: cmd.sheetName,
6477
- };
6448
+ return rangeAdapterRegistry.get(cmd.type)?.(cmd);
6449
+ }
6450
+ class RangeAdapterRegistry extends Registry {
6451
+ add(cmdType, fn) {
6452
+ super.add(cmdType, fn);
6453
+ return this;
6454
+ }
6455
+ get(cmdType) {
6456
+ return this.content[cmdType];
6478
6457
  }
6479
- return undefined;
6480
6458
  }
6459
+ const rangeAdapterRegistry = new RangeAdapterRegistry();
6460
+ rangeAdapterRegistry
6461
+ .add("REMOVE_COLUMNS_ROWS", (cmd) => ({
6462
+ applyChange: getApplyRangeChangeRemoveColRow(cmd),
6463
+ sheetId: cmd.sheetId,
6464
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6465
+ }))
6466
+ .add("ADD_COLUMNS_ROWS", (cmd) => ({
6467
+ applyChange: getApplyRangeChangeAddColRow(cmd),
6468
+ sheetId: cmd.sheetId,
6469
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6470
+ }))
6471
+ .add("DELETE_SHEET", (cmd) => ({
6472
+ applyChange: getApplyRangeChangeDeleteSheet(cmd),
6473
+ sheetId: cmd.sheetId,
6474
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6475
+ }))
6476
+ .add("RENAME_SHEET", (cmd) => ({
6477
+ applyChange: getApplyRangeChangeRenameSheet(cmd),
6478
+ sheetId: cmd.sheetId,
6479
+ sheetName: { old: cmd.oldName, current: cmd.newName },
6480
+ }))
6481
+ .add("MOVE_RANGES", (cmd) => ({
6482
+ applyChange: getApplyRangeChangeMoveRange(cmd),
6483
+ sheetId: cmd.sheetId,
6484
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6485
+ }));
6481
6486
  function getApplyRangeChangeRemoveColRow(cmd) {
6482
6487
  let start = cmd.dimension === "COL" ? "left" : "top";
6483
6488
  let end = cmd.dimension === "COL" ? "right" : "bottom";
@@ -7105,14 +7110,11 @@ function getPasteZones(target, content) {
7105
7110
  const width = content[0].length, height = content.length;
7106
7111
  return target.map((t) => splitZoneForPaste(t, width, height)).flat();
7107
7112
  }
7108
- function parseOSClipboardContent(content, clipboardId) {
7113
+ function parseOSClipboardContent(content) {
7109
7114
  let spreadsheetContent = undefined;
7110
7115
  if (content[ClipboardMIMEType.Html]) {
7111
7116
  const htmlDocument = new DOMParser().parseFromString(content[ClipboardMIMEType.Html], "text/html");
7112
- const oSheetClipboardData = htmlDocument
7113
- .querySelector("div")
7114
- ?.getAttribute("data-osheet-clipboard");
7115
- spreadsheetContent = oSheetClipboardData && JSON.parse(oSheetClipboardData);
7117
+ spreadsheetContent = getOSheetDataFromHTML(htmlDocument);
7116
7118
  }
7117
7119
  const textContent = content[ClipboardMIMEType.PlainText] || "";
7118
7120
  let imageBlob = undefined;
@@ -7131,6 +7133,17 @@ function parseOSClipboardContent(content, clipboardId) {
7131
7133
  };
7132
7134
  return osClipboardContent;
7133
7135
  }
7136
+ function getOSheetDataFromHTML(htmlDocument) {
7137
+ const attributes = [...htmlDocument.documentElement.attributes];
7138
+ // Check if it's a Microsoft Office clipboard data (it will have some namespaces defined in the root element)
7139
+ if (attributes.some((attr) => attr.value.includes("microsoft"))) {
7140
+ return undefined;
7141
+ }
7142
+ const oSheetClipboardData = htmlDocument
7143
+ .querySelector("div")
7144
+ ?.getAttribute("data-osheet-clipboard");
7145
+ return oSheetClipboardData && JSON.parse(oSheetClipboardData);
7146
+ }
7134
7147
  /**
7135
7148
  * Applies each clipboard handler to paste its corresponding data into the target.
7136
7149
  */
@@ -7820,8 +7833,11 @@ function invertMatrix(M) {
7820
7833
  // (a) Swap 2 rows. This multiply the determinant by -1.
7821
7834
  // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
7822
7835
  // (c) Add to a row a multiple of another row. This does not change the determinant.
7836
+ if (M.length < 1 || M[0].length < 1) {
7837
+ throw new Error("invertMatrix: an empty matrix cannot be inverted.");
7838
+ }
7823
7839
  if (M.length !== M[0].length) {
7824
- throw new EvaluationError(_t("Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible"));
7840
+ throw new Error("invertMatrix: only square matrices are invertible");
7825
7841
  }
7826
7842
  let determinant = 1;
7827
7843
  const dim = M.length;
@@ -7890,8 +7906,11 @@ function swapMatrixRows(matrix, row1, row2) {
7890
7906
  * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
7891
7907
  */
7892
7908
  function multiplyMatrices(matrix1, matrix2) {
7909
+ if (matrix1.length < 1 || matrix2.length < 1) {
7910
+ throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
7911
+ }
7893
7912
  if (matrix1.length !== matrix2[0].length) {
7894
- throw new EvaluationError(_t("Cannot multiply matrices : incompatible matrices size."));
7913
+ throw new Error("multiplyMatrices: incompatible matrices size.");
7895
7914
  }
7896
7915
  const rowsM1 = matrix1[0].length;
7897
7916
  const colsM2 = matrix2.length;
@@ -7917,7 +7936,7 @@ function toScalar(arg) {
7917
7936
  return arg;
7918
7937
  }
7919
7938
  if (!isSingleElementMatrix(arg)) {
7920
- throw new EvaluationError(_t("The value should be a scalar or a 1x1 matrix"));
7939
+ throw new Error("The value should be a scalar or a 1x1 matrix");
7921
7940
  }
7922
7941
  return arg[0][0];
7923
7942
  }
@@ -8154,6 +8173,16 @@ function getMovingAverageValues(dataset, labels, windowSize = DEFAULT_WINDOW_SIZ
8154
8173
  }
8155
8174
  return values;
8156
8175
  }
8176
+ function assertNonEmptyMatrix(matrix, argName) {
8177
+ assert(() => matrix.length > 0 && matrix[0].length > 0, _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", {
8178
+ argName,
8179
+ }));
8180
+ }
8181
+ function assertNonEmpty(...data) {
8182
+ if (data.length === 0 || data.some((arg) => arg.length === 0)) {
8183
+ throw new NotAvailableError(_t("[[FUNCTION_NAME]] has no valid input data."));
8184
+ }
8185
+ }
8157
8186
 
8158
8187
  const PREVIOUS_VALUE = "(previous)";
8159
8188
  const NEXT_VALUE = "(next)";
@@ -10977,6 +11006,7 @@ const MMULT = {
10977
11006
  compute: function (matrix1, matrix2) {
10978
11007
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
10979
11008
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
11009
+ assert(() => _matrix1.length > 0 && _matrix2.length > 0, _t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
10980
11010
  assert(() => _matrix1.length === _matrix2[0].length, _t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
10981
11011
  number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
10982
11012
  return multiplyMatrices(_matrix1, _matrix2);
@@ -12772,6 +12802,7 @@ const FORECAST = {
12772
12802
  ],
12773
12803
  compute: function (x, dataY, dataX) {
12774
12804
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
12805
+ assertNonEmpty(flatDataX, flatDataY);
12775
12806
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
12776
12807
  },
12777
12808
  isExported: true,
@@ -12788,6 +12819,7 @@ const GROWTH = {
12788
12819
  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.")),
12789
12820
  ],
12790
12821
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
12822
+ assertNonEmptyMatrix(knownDataY, "known_data_y");
12791
12823
  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)));
12792
12824
  },
12793
12825
  };
@@ -12802,6 +12834,7 @@ const INTERCEPT = {
12802
12834
  ],
12803
12835
  compute: function (dataY, dataX) {
12804
12836
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
12837
+ assertNonEmpty(flatDataX, flatDataY);
12805
12838
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
12806
12839
  return intercept;
12807
12840
  },
@@ -12851,6 +12884,7 @@ const LINEST = {
12851
12884
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
12852
12885
  ],
12853
12886
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12887
+ assertNonEmptyMatrix(dataY, "data_y");
12854
12888
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
12855
12889
  },
12856
12890
  isExported: true,
@@ -12867,6 +12901,7 @@ const LOGEST = {
12867
12901
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
12868
12902
  ],
12869
12903
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12904
+ assertNonEmptyMatrix(dataY, "data_y");
12870
12905
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
12871
12906
  for (let i = 0; i < coeffs.length; i++) {
12872
12907
  coeffs[i][0] = Math.exp(coeffs[i][0]);
@@ -12888,9 +12923,7 @@ const MATTHEWS = {
12888
12923
  const flatX = dataX.flat();
12889
12924
  const flatY = dataY.flat();
12890
12925
  assertSameNumberOfElements(flatX, flatY);
12891
- if (flatX.length === 0) {
12892
- return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
12893
- }
12926
+ assertNonEmpty(flatX, flatY);
12894
12927
  const n = flatX.length;
12895
12928
  let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
12896
12929
  for (let i = 0; i < n; ++i) {
@@ -13054,12 +13087,7 @@ const MINIFS = {
13054
13087
  // -----------------------------------------------------------------------------
13055
13088
  function pearson(dataY, dataX) {
13056
13089
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13057
- if (flatDataX.length === 0) {
13058
- throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13059
- }
13060
- if (flatDataX.length < 2) {
13061
- throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
13062
- }
13090
+ assertNonEmpty(flatDataX, flatDataY);
13063
13091
  const n = flatDataX.length;
13064
13092
  let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
13065
13093
  for (let i = 0; i < n; i++) {
@@ -13148,6 +13176,7 @@ const POLYFIT_COEFFS = {
13148
13176
  ],
13149
13177
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13150
13178
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13179
+ assertNonEmpty(flatDataX, flatDataY);
13151
13180
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
13152
13181
  },
13153
13182
  isExported: false,
@@ -13167,6 +13196,7 @@ const POLYFIT_FORECAST = {
13167
13196
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13168
13197
  const _order = toNumber(order, this.locale);
13169
13198
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13199
+ assertNonEmpty(flatDataX, flatDataY);
13170
13200
  const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
13171
13201
  return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
13172
13202
  },
@@ -13283,6 +13313,7 @@ const SLOPE = {
13283
13313
  ],
13284
13314
  compute: function (dataY, dataX) {
13285
13315
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13316
+ assertNonEmpty(flatDataX, flatDataY);
13286
13317
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
13287
13318
  return slope;
13288
13319
  },
@@ -13331,6 +13362,7 @@ const SPEARMAN = {
13331
13362
  ],
13332
13363
  compute: function (dataX, dataY) {
13333
13364
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13365
+ assertNonEmpty(flatDataX, flatDataY);
13334
13366
  const n = flatDataX.length;
13335
13367
  const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
13336
13368
  order.sort((a, b) => a[0] - b[0]);
@@ -13441,6 +13473,7 @@ const STEYX = {
13441
13473
  ],
13442
13474
  compute: function (dataY, dataX) {
13443
13475
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13476
+ assertNonEmpty(flatDataX, flatDataY);
13444
13477
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
13445
13478
  return data[1][2];
13446
13479
  },
@@ -13458,6 +13491,7 @@ const TREND = {
13458
13491
  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.")),
13459
13492
  ],
13460
13493
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13494
+ assertNonEmptyMatrix(knownDataY, "known_data_y");
13461
13495
  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));
13462
13496
  },
13463
13497
  };
@@ -20594,7 +20628,7 @@ function adaptFormulaStringRanges(defaultSheetId, formula, applyChange) {
20594
20628
  function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20595
20629
  const sheetName = splitReference(sheetXC).sheetName;
20596
20630
  if (sheetName
20597
- ? !isSheetNameEqual(sheetName, applyChange.sheetName)
20631
+ ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
20598
20632
  : defaultSheetId !== applyChange.sheetId) {
20599
20633
  return sheetXC;
20600
20634
  }
@@ -20611,7 +20645,7 @@ function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20611
20645
  }
20612
20646
  function getSheetNameGetter(applyChange) {
20613
20647
  return (sheetId) => {
20614
- return sheetId === applyChange.sheetId ? applyChange.sheetName : "";
20648
+ return sheetId === applyChange.sheetId ? applyChange.sheetName.current : "";
20615
20649
  };
20616
20650
  }
20617
20651
  function defaultGetSheetSize(sheetId) {
@@ -27202,10 +27236,6 @@ class ComboChart extends AbstractChart {
27202
27236
  };
27203
27237
  }
27204
27238
  getDefinitionForExcel() {
27205
- // Excel does not support aggregating labels
27206
- if (this.aggregated) {
27207
- return undefined;
27208
- }
27209
27239
  const dataSets = this.dataSets
27210
27240
  .map((ds) => toExcelDataset(this.getters, ds))
27211
27241
  .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
@@ -27578,9 +27608,13 @@ class GaugeChart extends AbstractChart {
27578
27608
  : undefined,
27579
27609
  };
27580
27610
  }
27581
- updateRanges(applyChange) {
27611
+ updateRanges(applyChange, sheetId, adaptSheetName) {
27582
27612
  const dataRange = adaptChartRange(this.dataRange, applyChange);
27583
- const adaptFormula = (formula) => this.getters.adaptFormulaStringDependencies(this.sheetId, formula, applyChange);
27613
+ const adaptFormula = (formula) => adaptFormulaStringRanges(this.sheetId, formula, {
27614
+ applyChange,
27615
+ sheetId,
27616
+ sheetName: adaptSheetName,
27617
+ });
27584
27618
  const sectionRule = adaptSectionRuleFormulas(this.sectionRule, adaptFormula);
27585
27619
  const definition = this.getDefinitionWithSpecificRanges(dataRange, sectionRule);
27586
27620
  return new GaugeChart(definition, this.sheetId, this.getters);
@@ -28503,10 +28537,6 @@ class ScatterChart extends AbstractChart {
28503
28537
  return new ScatterChart(definition, this.sheetId, this.getters);
28504
28538
  }
28505
28539
  getDefinitionForExcel() {
28506
- // Excel does not support aggregating labels
28507
- if (this.aggregated) {
28508
- return undefined;
28509
- }
28510
28540
  const dataSets = this.dataSets
28511
28541
  .map((ds) => toExcelDataset(this.getters, ds))
28512
28542
  .filter((ds) => ds.range !== "");
@@ -30211,7 +30241,8 @@ const inverseCommandRegistry = new Registry()
30211
30241
  .add("HIDE_COLUMNS_ROWS", inverseHideColumnsRows)
30212
30242
  .add("UNHIDE_COLUMNS_ROWS", inverseUnhideColumnsRows)
30213
30243
  .add("CREATE_TABLE_STYLE", inverseCreateTableStyle)
30214
- .add("ADD_PIVOT", inverseAddPivot);
30244
+ .add("ADD_PIVOT", inverseAddPivot)
30245
+ .add("RENAME_SHEET", inverseRenameSheet);
30215
30246
  for (const cmd of coreTypes.values()) {
30216
30247
  if (!inverseCommandRegistry.contains(cmd)) {
30217
30248
  inverseCommandRegistry.add(cmd, identity);
@@ -30309,6 +30340,16 @@ function inverseUnhideColumnsRows(cmd) {
30309
30340
  function inverseCreateTableStyle(cmd) {
30310
30341
  return [{ type: "REMOVE_TABLE_STYLE", tableStyleId: cmd.tableStyleId }];
30311
30342
  }
30343
+ function inverseRenameSheet(cmd) {
30344
+ return [
30345
+ {
30346
+ type: "RENAME_SHEET",
30347
+ sheetId: cmd.sheetId,
30348
+ oldName: cmd.newName,
30349
+ newName: cmd.oldName,
30350
+ },
30351
+ ];
30352
+ }
30312
30353
 
30313
30354
  /**
30314
30355
  * The class Registry is extended in order to add the function addChild
@@ -31558,9 +31599,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
31558
31599
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
31559
31600
  continue;
31560
31601
  operator = convertCFCellIsOperator(rule.operator);
31561
- values.push(rule.formula[0]);
31602
+ values.push(prefixFormula(rule.formula[0]));
31562
31603
  if (rule.formula.length === 2) {
31563
- values.push(rule.formula[1]);
31604
+ values.push(prefixFormula(rule.formula[1]));
31564
31605
  }
31565
31606
  break;
31566
31607
  }
@@ -31718,6 +31759,11 @@ function convertIcons(xlsxIconSet, index) {
31718
31759
  ? ICON_SETS[iconSet].neutral
31719
31760
  : ICON_SETS[iconSet].good;
31720
31761
  }
31762
+ /** Prefix the string by "=" if the string looks like a formula */
31763
+ function prefixFormula(formula) {
31764
+ const tokens = tokenize(formula);
31765
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
31766
+ }
31721
31767
  // ---------------------------------------------------------------------------
31722
31768
  // Warnings
31723
31769
  // ---------------------------------------------------------------------------
@@ -31980,7 +32026,7 @@ function getColPosition(colIndex, sheetData) {
31980
32026
  function getRowPosition(rowIndex, sheetData) {
31981
32027
  let position = 0;
31982
32028
  for (let i = 0; i < rowIndex; i++) {
31983
- const rowAtIndex = sheetData.rows[i];
32029
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
31984
32030
  if (rowAtIndex?.height) {
31985
32031
  position += rowAtIndex.height;
31986
32032
  }
@@ -32120,8 +32166,8 @@ function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
32120
32166
  }
32121
32167
  function convertAnchor(XLSXanchor) {
32122
32168
  const offset = {
32123
- x: convertEMUToDotValue(XLSXanchor.colOffset),
32124
- y: convertEMUToDotValue(XLSXanchor.rowOffset),
32169
+ x: convertEMUToDotValue(XLSXanchor.colOffset) - FIGURE_BORDER_WIDTH,
32170
+ y: convertEMUToDotValue(XLSXanchor.rowOffset) - FIGURE_BORDER_WIDTH,
32125
32171
  };
32126
32172
  return { col: XLSXanchor.col, row: XLSXanchor.row, offset };
32127
32173
  }
@@ -32504,8 +32550,12 @@ function getSheetDims(sheet) {
32504
32550
  dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
32505
32551
  dims[1] = Math.max(dims[1], row.index);
32506
32552
  }
32507
- dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
32508
- dims[1] = Math.max(dims[1], EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
32553
+ for (const fig of sheet.figures) {
32554
+ dims[0] = Math.max(dims[0], fig.anchors[fig.anchors.length - 1]?.col ?? 0);
32555
+ dims[1] = Math.max(dims[1], fig.anchors[fig.anchors.length - 1]?.row ?? 0);
32556
+ }
32557
+ dims[0] = Math.max(dims[0] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
32558
+ dims[1] = Math.max(dims[1] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
32509
32559
  return dims;
32510
32560
  }
32511
32561
  /**
@@ -34510,7 +34560,7 @@ function getRelationFile(file, xmls) {
34510
34560
  return relsFile;
34511
34561
  }
34512
34562
 
34513
- const EXCEL_IMPORT_VERSION = "18.3";
34563
+ const EXCEL_IMPORT_VERSION = "18.3.1";
34514
34564
  class XlsxReader {
34515
34565
  warningManager;
34516
34566
  xmls;
@@ -38514,7 +38564,7 @@ const splitToColumns = {
38514
38564
  const reinsertDynamicPivotMenu = {
38515
38565
  id: "reinsert_dynamic_pivot",
38516
38566
  name: _t("Re-insert dynamic pivot"),
38517
- sequence: 1020,
38567
+ sequence: 60,
38518
38568
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
38519
38569
  children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
38520
38570
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -38522,7 +38572,7 @@ const reinsertDynamicPivotMenu = {
38522
38572
  const reinsertStaticPivotMenu = {
38523
38573
  id: "reinsert_static_pivot",
38524
38574
  name: _t("Re-insert static pivot"),
38525
- sequence: 1020,
38575
+ sequence: 70,
38526
38576
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
38527
38577
  children: [REINSERT_STATIC_PIVOT_CHILDREN],
38528
38578
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -40191,8 +40241,9 @@ topbarMenuRegistry
40191
40241
  sequence: 40,
40192
40242
  separator: true,
40193
40243
  })
40194
- .addChild("data_sources_data", ["data"], (env) => {
40244
+ .addChild("pivot_data_sources", ["data"], (env) => {
40195
40245
  const sequence = 50;
40246
+ const numberOfPivots = env.model.getters.getPivotIds().length;
40196
40247
  return env.model.getters.getPivotIds().map((pivotId, index) => {
40197
40248
  const highlightProvider = {
40198
40249
  get highlights() {
@@ -40202,7 +40253,7 @@ topbarMenuRegistry
40202
40253
  return {
40203
40254
  id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
40204
40255
  name: env.model.getters.getPivotDisplayName(pivotId),
40205
- sequence: sequence + index,
40256
+ sequence: sequence + index / numberOfPivots,
40206
40257
  isReadonlyAllowed: true,
40207
40258
  execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
40208
40259
  onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
@@ -43760,6 +43811,9 @@ class Composer extends owl.Component {
43760
43811
  this.contentHelper.removeSelection();
43761
43812
  }
43762
43813
  onMouseup() {
43814
+ if (this.env.model.getters.isReadonly()) {
43815
+ return;
43816
+ }
43763
43817
  const selection = this.contentHelper.getCurrentSelection();
43764
43818
  if (selection.start !== selection.end) {
43765
43819
  this.props.composerStore.hoverToken(undefined);
@@ -57197,7 +57251,8 @@ class CorePlugin extends BasePlugin {
57197
57251
  * the type of change that occurred.
57198
57252
  *
57199
57253
  * @param applyChange a function that, when called, will adapt the range according to the change on the grid
57200
- * @param sheetId an optional sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
57254
+ * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
57255
+ * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
57201
57256
  */
57202
57257
  adaptRanges(applyChange, sheetId, sheetName) { }
57203
57258
  /**
@@ -57800,9 +57855,7 @@ class CellPlugin extends CorePlugin {
57800
57855
  for (const cell of Object.values(this.cells[sheet] || {})) {
57801
57856
  if (cell.isFormula) {
57802
57857
  for (const range of cell.compiledFormula.dependencies) {
57803
- if (!sheetId ||
57804
- range.sheetId === sheetId ||
57805
- (sheetName && range.invalidSheetName === sheetName)) {
57858
+ if (range.sheetId === sheetId || range.invalidSheetName === sheetName.old) {
57806
57859
  const change = applyChange(range);
57807
57860
  if (change.changeType !== "NONE") {
57808
57861
  this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
@@ -58418,9 +58471,9 @@ class ChartPlugin extends CorePlugin {
58418
58471
  charts = {};
58419
58472
  createChart = chartFactory(this.getters);
58420
58473
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
58421
- adaptRanges(applyChange) {
58474
+ adaptRanges(applyChange, sheetId, adaptSheetName) {
58422
58475
  for (const [chartId, chart] of Object.entries(this.charts)) {
58423
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
58476
+ this.history.update("charts", chartId, chart?.updateRanges(applyChange, sheetId, adaptSheetName));
58424
58477
  }
58425
58478
  }
58426
58479
  // ---------------------------------------------------------------------------
@@ -58683,7 +58736,7 @@ class ConditionalFormatPlugin extends CorePlugin {
58683
58736
  }
58684
58737
  }
58685
58738
  }
58686
- adaptRanges(applyChange, sheetId, sheetName) {
58739
+ adaptRanges(applyChange, sheetId) {
58687
58740
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
58688
58741
  for (const sheetId of sheetIds) {
58689
58742
  this.adaptCFRanges(sheetId, applyChange);
@@ -59079,11 +59132,8 @@ class DataValidationPlugin extends CorePlugin {
59079
59132
  "getValidationRuleForCell",
59080
59133
  ];
59081
59134
  rules = {};
59082
- adaptRanges(applyChange, sheetId, sheetName) {
59083
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.rules);
59084
- for (const sheetId of sheetIds) {
59085
- this.adaptDVRanges(sheetId, applyChange);
59086
- }
59135
+ adaptRanges(applyChange, sheetId) {
59136
+ this.adaptDVRanges(sheetId, applyChange);
59087
59137
  this.adaptDVFormulas(applyChange);
59088
59138
  }
59089
59139
  adaptDVFormulas(applyChange) {
@@ -59373,9 +59423,6 @@ class FigurePlugin extends CorePlugin {
59373
59423
  // Command Handling
59374
59424
  // ---------------------------------------------------------------------------
59375
59425
  adaptRanges(applyChange, sheetId) {
59376
- if (!sheetId) {
59377
- return;
59378
- }
59379
59426
  for (const figure of this.getFigures(sheetId)) {
59380
59427
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
59381
59428
  left: figure.col,
@@ -60183,11 +60230,8 @@ class MergePlugin extends CorePlugin {
60183
60230
  break;
60184
60231
  }
60185
60232
  }
60186
- adaptRanges(applyChange, sheetId, sheetName) {
60187
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.merges);
60188
- for (const sheetId of sheetIds) {
60189
- this.applyRangeChangeOnSheet(sheetId, applyChange);
60190
- }
60233
+ adaptRanges(applyChange, sheetId) {
60234
+ this.applyRangeChangeOnSheet(sheetId, applyChange);
60191
60235
  }
60192
60236
  // ---------------------------------------------------------------------------
60193
60237
  // Getters
@@ -61695,12 +61739,9 @@ class TablePlugin extends CorePlugin {
61695
61739
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
61696
61740
  tables = {};
61697
61741
  nextTableId = 1;
61698
- adaptRanges(applyChange, sheetId, sheetName) {
61699
- const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
61700
- for (const sheetId of sheetIds) {
61701
- for (const table of this.getCoreTables(sheetId)) {
61702
- this.applyRangeChangeOnTable(sheetId, table, applyChange);
61703
- }
61742
+ adaptRanges(applyChange, sheetId) {
61743
+ for (const table of this.getCoreTables(sheetId)) {
61744
+ this.applyRangeChangeOnTable(sheetId, table, applyChange);
61704
61745
  }
61705
61746
  }
61706
61747
  allowDispatch(cmd) {
@@ -62663,7 +62704,7 @@ class PivotCorePlugin extends CorePlugin {
62663
62704
  }
62664
62705
  }
62665
62706
  }
62666
- adaptRanges(applyChange, sheetId, sheetName) {
62707
+ adaptRanges(applyChange) {
62667
62708
  for (const sheetId in this.compiledMeasureFormulas) {
62668
62709
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
62669
62710
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -66824,7 +66865,7 @@ class PivotUIPlugin extends CoreViewPlugin {
66824
66865
  if (!result) {
66825
66866
  return EMPTY_PIVOT_CELL;
66826
66867
  }
66827
- const { functionName, args } = result;
66868
+ let { functionName, args } = result;
66828
66869
  const formulaId = args[0];
66829
66870
  if (!formulaId) {
66830
66871
  return EMPTY_PIVOT_CELL;
@@ -66854,6 +66895,9 @@ class PivotUIPlugin extends CoreViewPlugin {
66854
66895
  return pivotCells[pivotCol][pivotRow];
66855
66896
  }
66856
66897
  try {
66898
+ const offsetRow = position.row - mainPosition.row;
66899
+ const offsetCol = position.col - mainPosition.col;
66900
+ args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
66857
66901
  if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
66858
66902
  const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
66859
66903
  return {
@@ -68052,7 +68096,8 @@ function transformAll(toTransform, executed) {
68052
68096
  // If the executed command is not in the registry, we skip it
68053
68097
  // because we know there won't be any transformation impacting the
68054
68098
  // commands to transform.
68055
- if (possibleTransformations.has(executedCommand.type)) {
68099
+ if (possibleTransformations.has(executedCommand.type) ||
68100
+ rangeAdapterRegistry.contains(executedCommand.type)) {
68056
68101
  transformedCommands = transformedCommands.reduce((acc, cmd) => {
68057
68102
  const transformed = transform(cmd, executedCommand);
68058
68103
  if (transformed) {
@@ -79213,7 +79258,7 @@ function figureCoordinates(headers, anchor, offset) {
79213
79258
  for (const [headerIndex, header] of headers.slice(anchor).entries()) {
79214
79259
  if (currentPosition <= offset && offset < currentPosition + header.size) {
79215
79260
  return {
79216
- index: headerIndex,
79261
+ index: anchor + headerIndex,
79217
79262
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
79218
79263
  };
79219
79264
  }
@@ -80209,7 +80254,7 @@ class Model extends EventBus {
80209
80254
  handlers = [];
80210
80255
  uiHandlers = [];
80211
80256
  coreHandlers = [];
80212
- constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
80257
+ constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
80213
80258
  const start = performance.now();
80214
80259
  console.debug("##### Model creation #####");
80215
80260
  super();
@@ -80952,6 +80997,6 @@ exports.tokenColors = tokenColors;
80952
80997
  exports.tokenize = tokenize;
80953
80998
 
80954
80999
 
80955
- __info__.version = "18.3.17";
80956
- __info__.date = "2025-08-21T06:40:44.469Z";
80957
- __info__.hash = "ab02b0c";
81000
+ __info__.version = "18.3.19";
81001
+ __info__.date = "2025-09-05T07:38:30.661Z";
81002
+ __info__.hash = "77fd307";