@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
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -3497,6 +3497,7 @@ const invalidateBordersCommands = new Set([
3497
3497
  "AUTOFILL_CELL",
3498
3498
  "SET_BORDER",
3499
3499
  "SET_ZONE_BORDERS",
3500
+ "SET_BORDERS_ON_TARGET",
3500
3501
  ]);
3501
3502
  const readonlyAllowedCommands = new Set([
3502
3503
  "START",
@@ -6442,40 +6443,44 @@ function orderRange(range) {
6442
6443
  };
6443
6444
  }
6444
6445
  function getRangeAdapter(cmd) {
6445
- switch (cmd.type) {
6446
- case "REMOVE_COLUMNS_ROWS":
6447
- return {
6448
- applyChange: getApplyRangeChangeRemoveColRow(cmd),
6449
- sheetId: cmd.sheetId,
6450
- sheetName: cmd.sheetName,
6451
- };
6452
- case "ADD_COLUMNS_ROWS":
6453
- return {
6454
- applyChange: getApplyRangeChangeAddColRow(cmd),
6455
- sheetId: cmd.sheetId,
6456
- sheetName: cmd.sheetName,
6457
- };
6458
- case "DELETE_SHEET":
6459
- return {
6460
- applyChange: getApplyRangeChangeDeleteSheet(cmd),
6461
- sheetId: cmd.sheetId,
6462
- sheetName: cmd.sheetName,
6463
- };
6464
- case "RENAME_SHEET":
6465
- return {
6466
- applyChange: getApplyRangeChangeRenameSheet(cmd),
6467
- sheetId: cmd.sheetId,
6468
- sheetName: cmd.oldName,
6469
- };
6470
- case "MOVE_RANGES":
6471
- return {
6472
- applyChange: getApplyRangeChangeMoveRange(cmd),
6473
- sheetId: cmd.sheetId,
6474
- sheetName: cmd.sheetName,
6475
- };
6446
+ return rangeAdapterRegistry.get(cmd.type)?.(cmd);
6447
+ }
6448
+ class RangeAdapterRegistry extends Registry {
6449
+ add(cmdType, fn) {
6450
+ super.add(cmdType, fn);
6451
+ return this;
6452
+ }
6453
+ get(cmdType) {
6454
+ return this.content[cmdType];
6476
6455
  }
6477
- return undefined;
6478
6456
  }
6457
+ const rangeAdapterRegistry = new RangeAdapterRegistry();
6458
+ rangeAdapterRegistry
6459
+ .add("REMOVE_COLUMNS_ROWS", (cmd) => ({
6460
+ applyChange: getApplyRangeChangeRemoveColRow(cmd),
6461
+ sheetId: cmd.sheetId,
6462
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6463
+ }))
6464
+ .add("ADD_COLUMNS_ROWS", (cmd) => ({
6465
+ applyChange: getApplyRangeChangeAddColRow(cmd),
6466
+ sheetId: cmd.sheetId,
6467
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6468
+ }))
6469
+ .add("DELETE_SHEET", (cmd) => ({
6470
+ applyChange: getApplyRangeChangeDeleteSheet(cmd),
6471
+ sheetId: cmd.sheetId,
6472
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6473
+ }))
6474
+ .add("RENAME_SHEET", (cmd) => ({
6475
+ applyChange: getApplyRangeChangeRenameSheet(cmd),
6476
+ sheetId: cmd.sheetId,
6477
+ sheetName: { old: cmd.oldName, current: cmd.newName },
6478
+ }))
6479
+ .add("MOVE_RANGES", (cmd) => ({
6480
+ applyChange: getApplyRangeChangeMoveRange(cmd),
6481
+ sheetId: cmd.sheetId,
6482
+ sheetName: { old: cmd.sheetName, current: cmd.sheetName },
6483
+ }));
6479
6484
  function getApplyRangeChangeRemoveColRow(cmd) {
6480
6485
  let start = cmd.dimension === "COL" ? "left" : "top";
6481
6486
  let end = cmd.dimension === "COL" ? "right" : "bottom";
@@ -7103,14 +7108,11 @@ function getPasteZones(target, content) {
7103
7108
  const width = content[0].length, height = content.length;
7104
7109
  return target.map((t) => splitZoneForPaste(t, width, height)).flat();
7105
7110
  }
7106
- function parseOSClipboardContent(content, clipboardId) {
7111
+ function parseOSClipboardContent(content) {
7107
7112
  let spreadsheetContent = undefined;
7108
7113
  if (content[ClipboardMIMEType.Html]) {
7109
7114
  const htmlDocument = new DOMParser().parseFromString(content[ClipboardMIMEType.Html], "text/html");
7110
- const oSheetClipboardData = htmlDocument
7111
- .querySelector("div")
7112
- ?.getAttribute("data-osheet-clipboard");
7113
- spreadsheetContent = oSheetClipboardData && JSON.parse(oSheetClipboardData);
7115
+ spreadsheetContent = getOSheetDataFromHTML(htmlDocument);
7114
7116
  }
7115
7117
  const textContent = content[ClipboardMIMEType.PlainText] || "";
7116
7118
  let imageBlob = undefined;
@@ -7129,6 +7131,17 @@ function parseOSClipboardContent(content, clipboardId) {
7129
7131
  };
7130
7132
  return osClipboardContent;
7131
7133
  }
7134
+ function getOSheetDataFromHTML(htmlDocument) {
7135
+ const attributes = [...htmlDocument.documentElement.attributes];
7136
+ // Check if it's a Microsoft Office clipboard data (it will have some namespaces defined in the root element)
7137
+ if (attributes.some((attr) => attr.value.includes("microsoft"))) {
7138
+ return undefined;
7139
+ }
7140
+ const oSheetClipboardData = htmlDocument
7141
+ .querySelector("div")
7142
+ ?.getAttribute("data-osheet-clipboard");
7143
+ return oSheetClipboardData && JSON.parse(oSheetClipboardData);
7144
+ }
7132
7145
  /**
7133
7146
  * Applies each clipboard handler to paste its corresponding data into the target.
7134
7147
  */
@@ -7818,8 +7831,11 @@ function invertMatrix(M) {
7818
7831
  // (a) Swap 2 rows. This multiply the determinant by -1.
7819
7832
  // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
7820
7833
  // (c) Add to a row a multiple of another row. This does not change the determinant.
7834
+ if (M.length < 1 || M[0].length < 1) {
7835
+ throw new Error("invertMatrix: an empty matrix cannot be inverted.");
7836
+ }
7821
7837
  if (M.length !== M[0].length) {
7822
- throw new EvaluationError(_t("Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible"));
7838
+ throw new Error("invertMatrix: only square matrices are invertible");
7823
7839
  }
7824
7840
  let determinant = 1;
7825
7841
  const dim = M.length;
@@ -7888,8 +7904,11 @@ function swapMatrixRows(matrix, row1, row2) {
7888
7904
  * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
7889
7905
  */
7890
7906
  function multiplyMatrices(matrix1, matrix2) {
7907
+ if (matrix1.length < 1 || matrix2.length < 1) {
7908
+ throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
7909
+ }
7891
7910
  if (matrix1.length !== matrix2[0].length) {
7892
- throw new EvaluationError(_t("Cannot multiply matrices : incompatible matrices size."));
7911
+ throw new Error("multiplyMatrices: incompatible matrices size.");
7893
7912
  }
7894
7913
  const rowsM1 = matrix1[0].length;
7895
7914
  const colsM2 = matrix2.length;
@@ -7915,7 +7934,7 @@ function toScalar(arg) {
7915
7934
  return arg;
7916
7935
  }
7917
7936
  if (!isSingleElementMatrix(arg)) {
7918
- throw new EvaluationError(_t("The value should be a scalar or a 1x1 matrix"));
7937
+ throw new Error("The value should be a scalar or a 1x1 matrix");
7919
7938
  }
7920
7939
  return arg[0][0];
7921
7940
  }
@@ -8152,6 +8171,16 @@ function getMovingAverageValues(dataset, labels, windowSize = DEFAULT_WINDOW_SIZ
8152
8171
  }
8153
8172
  return values;
8154
8173
  }
8174
+ function assertNonEmptyMatrix(matrix, argName) {
8175
+ assert(() => matrix.length > 0 && matrix[0].length > 0, _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", {
8176
+ argName,
8177
+ }));
8178
+ }
8179
+ function assertNonEmpty(...data) {
8180
+ if (data.length === 0 || data.some((arg) => arg.length === 0)) {
8181
+ throw new NotAvailableError(_t("[[FUNCTION_NAME]] has no valid input data."));
8182
+ }
8183
+ }
8155
8184
 
8156
8185
  const PREVIOUS_VALUE = "(previous)";
8157
8186
  const NEXT_VALUE = "(next)";
@@ -10975,6 +11004,7 @@ const MMULT = {
10975
11004
  compute: function (matrix1, matrix2) {
10976
11005
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
10977
11006
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
11007
+ assert(() => _matrix1.length > 0 && _matrix2.length > 0, _t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
10978
11008
  assert(() => _matrix1.length === _matrix2[0].length, _t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
10979
11009
  number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
10980
11010
  return multiplyMatrices(_matrix1, _matrix2);
@@ -12770,6 +12800,7 @@ const FORECAST = {
12770
12800
  ],
12771
12801
  compute: function (x, dataY, dataX) {
12772
12802
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
12803
+ assertNonEmpty(flatDataX, flatDataY);
12773
12804
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
12774
12805
  },
12775
12806
  isExported: true,
@@ -12786,6 +12817,7 @@ const GROWTH = {
12786
12817
  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.")),
12787
12818
  ],
12788
12819
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
12820
+ assertNonEmptyMatrix(knownDataY, "known_data_y");
12789
12821
  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)));
12790
12822
  },
12791
12823
  };
@@ -12800,6 +12832,7 @@ const INTERCEPT = {
12800
12832
  ],
12801
12833
  compute: function (dataY, dataX) {
12802
12834
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
12835
+ assertNonEmpty(flatDataX, flatDataY);
12803
12836
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
12804
12837
  return intercept;
12805
12838
  },
@@ -12849,6 +12882,7 @@ const LINEST = {
12849
12882
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
12850
12883
  ],
12851
12884
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12885
+ assertNonEmptyMatrix(dataY, "data_y");
12852
12886
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
12853
12887
  },
12854
12888
  isExported: true,
@@ -12865,6 +12899,7 @@ const LOGEST = {
12865
12899
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
12866
12900
  ],
12867
12901
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12902
+ assertNonEmptyMatrix(dataY, "data_y");
12868
12903
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
12869
12904
  for (let i = 0; i < coeffs.length; i++) {
12870
12905
  coeffs[i][0] = Math.exp(coeffs[i][0]);
@@ -12886,9 +12921,7 @@ const MATTHEWS = {
12886
12921
  const flatX = dataX.flat();
12887
12922
  const flatY = dataY.flat();
12888
12923
  assertSameNumberOfElements(flatX, flatY);
12889
- if (flatX.length === 0) {
12890
- return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
12891
- }
12924
+ assertNonEmpty(flatX, flatY);
12892
12925
  const n = flatX.length;
12893
12926
  let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
12894
12927
  for (let i = 0; i < n; ++i) {
@@ -13052,12 +13085,7 @@ const MINIFS = {
13052
13085
  // -----------------------------------------------------------------------------
13053
13086
  function pearson(dataY, dataX) {
13054
13087
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13055
- if (flatDataX.length === 0) {
13056
- throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
13057
- }
13058
- if (flatDataX.length < 2) {
13059
- throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
13060
- }
13088
+ assertNonEmpty(flatDataX, flatDataY);
13061
13089
  const n = flatDataX.length;
13062
13090
  let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
13063
13091
  for (let i = 0; i < n; i++) {
@@ -13146,6 +13174,7 @@ const POLYFIT_COEFFS = {
13146
13174
  ],
13147
13175
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13148
13176
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13177
+ assertNonEmpty(flatDataX, flatDataY);
13149
13178
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
13150
13179
  },
13151
13180
  isExported: false,
@@ -13165,6 +13194,7 @@ const POLYFIT_FORECAST = {
13165
13194
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13166
13195
  const _order = toNumber(order, this.locale);
13167
13196
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13197
+ assertNonEmpty(flatDataX, flatDataY);
13168
13198
  const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
13169
13199
  return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
13170
13200
  },
@@ -13281,6 +13311,7 @@ const SLOPE = {
13281
13311
  ],
13282
13312
  compute: function (dataY, dataX) {
13283
13313
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13314
+ assertNonEmpty(flatDataX, flatDataY);
13284
13315
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
13285
13316
  return slope;
13286
13317
  },
@@ -13329,6 +13360,7 @@ const SPEARMAN = {
13329
13360
  ],
13330
13361
  compute: function (dataX, dataY) {
13331
13362
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13363
+ assertNonEmpty(flatDataX, flatDataY);
13332
13364
  const n = flatDataX.length;
13333
13365
  const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
13334
13366
  order.sort((a, b) => a[0] - b[0]);
@@ -13439,6 +13471,7 @@ const STEYX = {
13439
13471
  ],
13440
13472
  compute: function (dataY, dataX) {
13441
13473
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13474
+ assertNonEmpty(flatDataX, flatDataY);
13442
13475
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
13443
13476
  return data[1][2];
13444
13477
  },
@@ -13456,6 +13489,7 @@ const TREND = {
13456
13489
  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.")),
13457
13490
  ],
13458
13491
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13492
+ assertNonEmptyMatrix(knownDataY, "known_data_y");
13459
13493
  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));
13460
13494
  },
13461
13495
  };
@@ -20592,7 +20626,7 @@ function adaptFormulaStringRanges(defaultSheetId, formula, applyChange) {
20592
20626
  function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20593
20627
  const sheetName = splitReference(sheetXC).sheetName;
20594
20628
  if (sheetName
20595
- ? !isSheetNameEqual(sheetName, applyChange.sheetName)
20629
+ ? !isSheetNameEqual(sheetName, applyChange.sheetName.old)
20596
20630
  : defaultSheetId !== applyChange.sheetId) {
20597
20631
  return sheetXC;
20598
20632
  }
@@ -20609,7 +20643,7 @@ function adaptStringRange(defaultSheetId, sheetXC, applyChange) {
20609
20643
  }
20610
20644
  function getSheetNameGetter(applyChange) {
20611
20645
  return (sheetId) => {
20612
- return sheetId === applyChange.sheetId ? applyChange.sheetName : "";
20646
+ return sheetId === applyChange.sheetId ? applyChange.sheetName.current : "";
20613
20647
  };
20614
20648
  }
20615
20649
  function defaultGetSheetSize(sheetId) {
@@ -27200,10 +27234,6 @@ class ComboChart extends AbstractChart {
27200
27234
  };
27201
27235
  }
27202
27236
  getDefinitionForExcel() {
27203
- // Excel does not support aggregating labels
27204
- if (this.aggregated) {
27205
- return undefined;
27206
- }
27207
27237
  const dataSets = this.dataSets
27208
27238
  .map((ds) => toExcelDataset(this.getters, ds))
27209
27239
  .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
@@ -27576,9 +27606,13 @@ class GaugeChart extends AbstractChart {
27576
27606
  : undefined,
27577
27607
  };
27578
27608
  }
27579
- updateRanges(applyChange) {
27609
+ updateRanges(applyChange, sheetId, adaptSheetName) {
27580
27610
  const dataRange = adaptChartRange(this.dataRange, applyChange);
27581
- const adaptFormula = (formula) => this.getters.adaptFormulaStringDependencies(this.sheetId, formula, applyChange);
27611
+ const adaptFormula = (formula) => adaptFormulaStringRanges(this.sheetId, formula, {
27612
+ applyChange,
27613
+ sheetId,
27614
+ sheetName: adaptSheetName,
27615
+ });
27582
27616
  const sectionRule = adaptSectionRuleFormulas(this.sectionRule, adaptFormula);
27583
27617
  const definition = this.getDefinitionWithSpecificRanges(dataRange, sectionRule);
27584
27618
  return new GaugeChart(definition, this.sheetId, this.getters);
@@ -28501,10 +28535,6 @@ class ScatterChart extends AbstractChart {
28501
28535
  return new ScatterChart(definition, this.sheetId, this.getters);
28502
28536
  }
28503
28537
  getDefinitionForExcel() {
28504
- // Excel does not support aggregating labels
28505
- if (this.aggregated) {
28506
- return undefined;
28507
- }
28508
28538
  const dataSets = this.dataSets
28509
28539
  .map((ds) => toExcelDataset(this.getters, ds))
28510
28540
  .filter((ds) => ds.range !== "");
@@ -30209,7 +30239,8 @@ const inverseCommandRegistry = new Registry()
30209
30239
  .add("HIDE_COLUMNS_ROWS", inverseHideColumnsRows)
30210
30240
  .add("UNHIDE_COLUMNS_ROWS", inverseUnhideColumnsRows)
30211
30241
  .add("CREATE_TABLE_STYLE", inverseCreateTableStyle)
30212
- .add("ADD_PIVOT", inverseAddPivot);
30242
+ .add("ADD_PIVOT", inverseAddPivot)
30243
+ .add("RENAME_SHEET", inverseRenameSheet);
30213
30244
  for (const cmd of coreTypes.values()) {
30214
30245
  if (!inverseCommandRegistry.contains(cmd)) {
30215
30246
  inverseCommandRegistry.add(cmd, identity);
@@ -30307,6 +30338,16 @@ function inverseUnhideColumnsRows(cmd) {
30307
30338
  function inverseCreateTableStyle(cmd) {
30308
30339
  return [{ type: "REMOVE_TABLE_STYLE", tableStyleId: cmd.tableStyleId }];
30309
30340
  }
30341
+ function inverseRenameSheet(cmd) {
30342
+ return [
30343
+ {
30344
+ type: "RENAME_SHEET",
30345
+ sheetId: cmd.sheetId,
30346
+ oldName: cmd.newName,
30347
+ newName: cmd.oldName,
30348
+ },
30349
+ ];
30350
+ }
30310
30351
 
30311
30352
  /**
30312
30353
  * The class Registry is extended in order to add the function addChild
@@ -31556,9 +31597,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
31556
31597
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
31557
31598
  continue;
31558
31599
  operator = convertCFCellIsOperator(rule.operator);
31559
- values.push(rule.formula[0]);
31600
+ values.push(prefixFormula(rule.formula[0]));
31560
31601
  if (rule.formula.length === 2) {
31561
- values.push(rule.formula[1]);
31602
+ values.push(prefixFormula(rule.formula[1]));
31562
31603
  }
31563
31604
  break;
31564
31605
  }
@@ -31716,6 +31757,11 @@ function convertIcons(xlsxIconSet, index) {
31716
31757
  ? ICON_SETS[iconSet].neutral
31717
31758
  : ICON_SETS[iconSet].good;
31718
31759
  }
31760
+ /** Prefix the string by "=" if the string looks like a formula */
31761
+ function prefixFormula(formula) {
31762
+ const tokens = tokenize(formula);
31763
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
31764
+ }
31719
31765
  // ---------------------------------------------------------------------------
31720
31766
  // Warnings
31721
31767
  // ---------------------------------------------------------------------------
@@ -31978,7 +32024,7 @@ function getColPosition(colIndex, sheetData) {
31978
32024
  function getRowPosition(rowIndex, sheetData) {
31979
32025
  let position = 0;
31980
32026
  for (let i = 0; i < rowIndex; i++) {
31981
- const rowAtIndex = sheetData.rows[i];
32027
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
31982
32028
  if (rowAtIndex?.height) {
31983
32029
  position += rowAtIndex.height;
31984
32030
  }
@@ -32118,8 +32164,8 @@ function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
32118
32164
  }
32119
32165
  function convertAnchor(XLSXanchor) {
32120
32166
  const offset = {
32121
- x: convertEMUToDotValue(XLSXanchor.colOffset),
32122
- y: convertEMUToDotValue(XLSXanchor.rowOffset),
32167
+ x: convertEMUToDotValue(XLSXanchor.colOffset) - FIGURE_BORDER_WIDTH,
32168
+ y: convertEMUToDotValue(XLSXanchor.rowOffset) - FIGURE_BORDER_WIDTH,
32123
32169
  };
32124
32170
  return { col: XLSXanchor.col, row: XLSXanchor.row, offset };
32125
32171
  }
@@ -32502,8 +32548,12 @@ function getSheetDims(sheet) {
32502
32548
  dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
32503
32549
  dims[1] = Math.max(dims[1], row.index);
32504
32550
  }
32505
- dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
32506
- dims[1] = Math.max(dims[1], EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
32551
+ for (const fig of sheet.figures) {
32552
+ dims[0] = Math.max(dims[0], fig.anchors[fig.anchors.length - 1]?.col ?? 0);
32553
+ dims[1] = Math.max(dims[1], fig.anchors[fig.anchors.length - 1]?.row ?? 0);
32554
+ }
32555
+ dims[0] = Math.max(dims[0] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
32556
+ dims[1] = Math.max(dims[1] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
32507
32557
  return dims;
32508
32558
  }
32509
32559
  /**
@@ -34508,7 +34558,7 @@ function getRelationFile(file, xmls) {
34508
34558
  return relsFile;
34509
34559
  }
34510
34560
 
34511
- const EXCEL_IMPORT_VERSION = "18.3";
34561
+ const EXCEL_IMPORT_VERSION = "18.3.1";
34512
34562
  class XlsxReader {
34513
34563
  warningManager;
34514
34564
  xmls;
@@ -38512,7 +38562,7 @@ const splitToColumns = {
38512
38562
  const reinsertDynamicPivotMenu = {
38513
38563
  id: "reinsert_dynamic_pivot",
38514
38564
  name: _t("Re-insert dynamic pivot"),
38515
- sequence: 1020,
38565
+ sequence: 60,
38516
38566
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
38517
38567
  children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
38518
38568
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -38520,7 +38570,7 @@ const reinsertDynamicPivotMenu = {
38520
38570
  const reinsertStaticPivotMenu = {
38521
38571
  id: "reinsert_static_pivot",
38522
38572
  name: _t("Re-insert static pivot"),
38523
- sequence: 1020,
38573
+ sequence: 70,
38524
38574
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
38525
38575
  children: [REINSERT_STATIC_PIVOT_CHILDREN],
38526
38576
  isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
@@ -40189,8 +40239,9 @@ topbarMenuRegistry
40189
40239
  sequence: 40,
40190
40240
  separator: true,
40191
40241
  })
40192
- .addChild("data_sources_data", ["data"], (env) => {
40242
+ .addChild("pivot_data_sources", ["data"], (env) => {
40193
40243
  const sequence = 50;
40244
+ const numberOfPivots = env.model.getters.getPivotIds().length;
40194
40245
  return env.model.getters.getPivotIds().map((pivotId, index) => {
40195
40246
  const highlightProvider = {
40196
40247
  get highlights() {
@@ -40200,7 +40251,7 @@ topbarMenuRegistry
40200
40251
  return {
40201
40252
  id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
40202
40253
  name: env.model.getters.getPivotDisplayName(pivotId),
40203
- sequence: sequence + index,
40254
+ sequence: sequence + index / numberOfPivots,
40204
40255
  isReadonlyAllowed: true,
40205
40256
  execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
40206
40257
  onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
@@ -43758,6 +43809,9 @@ class Composer extends Component {
43758
43809
  this.contentHelper.removeSelection();
43759
43810
  }
43760
43811
  onMouseup() {
43812
+ if (this.env.model.getters.isReadonly()) {
43813
+ return;
43814
+ }
43761
43815
  const selection = this.contentHelper.getCurrentSelection();
43762
43816
  if (selection.start !== selection.end) {
43763
43817
  this.props.composerStore.hoverToken(undefined);
@@ -57195,7 +57249,8 @@ class CorePlugin extends BasePlugin {
57195
57249
  * the type of change that occurred.
57196
57250
  *
57197
57251
  * @param applyChange a function that, when called, will adapt the range according to the change on the grid
57198
- * @param sheetId an optional sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
57252
+ * @param sheetId an sheetId to adapt either range of that sheet specifically, or ranges pointing to that sheet
57253
+ * @param sheetName couple of old and new sheet names to adapt ranges pointing to that sheet
57199
57254
  */
57200
57255
  adaptRanges(applyChange, sheetId, sheetName) { }
57201
57256
  /**
@@ -57798,9 +57853,7 @@ class CellPlugin extends CorePlugin {
57798
57853
  for (const cell of Object.values(this.cells[sheet] || {})) {
57799
57854
  if (cell.isFormula) {
57800
57855
  for (const range of cell.compiledFormula.dependencies) {
57801
- if (!sheetId ||
57802
- range.sheetId === sheetId ||
57803
- (sheetName && range.invalidSheetName === sheetName)) {
57856
+ if (range.sheetId === sheetId || range.invalidSheetName === sheetName.old) {
57804
57857
  const change = applyChange(range);
57805
57858
  if (change.changeType !== "NONE") {
57806
57859
  this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
@@ -58416,9 +58469,9 @@ class ChartPlugin extends CorePlugin {
58416
58469
  charts = {};
58417
58470
  createChart = chartFactory(this.getters);
58418
58471
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
58419
- adaptRanges(applyChange) {
58472
+ adaptRanges(applyChange, sheetId, adaptSheetName) {
58420
58473
  for (const [chartId, chart] of Object.entries(this.charts)) {
58421
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
58474
+ this.history.update("charts", chartId, chart?.updateRanges(applyChange, sheetId, adaptSheetName));
58422
58475
  }
58423
58476
  }
58424
58477
  // ---------------------------------------------------------------------------
@@ -58681,7 +58734,7 @@ class ConditionalFormatPlugin extends CorePlugin {
58681
58734
  }
58682
58735
  }
58683
58736
  }
58684
- adaptRanges(applyChange, sheetId, sheetName) {
58737
+ adaptRanges(applyChange, sheetId) {
58685
58738
  const sheetIds = sheetId ? [sheetId] : Object.keys(this.cfRules);
58686
58739
  for (const sheetId of sheetIds) {
58687
58740
  this.adaptCFRanges(sheetId, applyChange);
@@ -59077,11 +59130,8 @@ class DataValidationPlugin extends CorePlugin {
59077
59130
  "getValidationRuleForCell",
59078
59131
  ];
59079
59132
  rules = {};
59080
- adaptRanges(applyChange, sheetId, sheetName) {
59081
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.rules);
59082
- for (const sheetId of sheetIds) {
59083
- this.adaptDVRanges(sheetId, applyChange);
59084
- }
59133
+ adaptRanges(applyChange, sheetId) {
59134
+ this.adaptDVRanges(sheetId, applyChange);
59085
59135
  this.adaptDVFormulas(applyChange);
59086
59136
  }
59087
59137
  adaptDVFormulas(applyChange) {
@@ -59371,9 +59421,6 @@ class FigurePlugin extends CorePlugin {
59371
59421
  // Command Handling
59372
59422
  // ---------------------------------------------------------------------------
59373
59423
  adaptRanges(applyChange, sheetId) {
59374
- if (!sheetId) {
59375
- return;
59376
- }
59377
59424
  for (const figure of this.getFigures(sheetId)) {
59378
59425
  const change = applyChange(this.getters.getRangeFromZone(sheetId, {
59379
59426
  left: figure.col,
@@ -60181,11 +60228,8 @@ class MergePlugin extends CorePlugin {
60181
60228
  break;
60182
60229
  }
60183
60230
  }
60184
- adaptRanges(applyChange, sheetId, sheetName) {
60185
- const sheetIds = sheetId ? [sheetId] : Object.keys(this.merges);
60186
- for (const sheetId of sheetIds) {
60187
- this.applyRangeChangeOnSheet(sheetId, applyChange);
60188
- }
60231
+ adaptRanges(applyChange, sheetId) {
60232
+ this.applyRangeChangeOnSheet(sheetId, applyChange);
60189
60233
  }
60190
60234
  // ---------------------------------------------------------------------------
60191
60235
  // Getters
@@ -61693,12 +61737,9 @@ class TablePlugin extends CorePlugin {
61693
61737
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
61694
61738
  tables = {};
61695
61739
  nextTableId = 1;
61696
- adaptRanges(applyChange, sheetId, sheetName) {
61697
- const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
61698
- for (const sheetId of sheetIds) {
61699
- for (const table of this.getCoreTables(sheetId)) {
61700
- this.applyRangeChangeOnTable(sheetId, table, applyChange);
61701
- }
61740
+ adaptRanges(applyChange, sheetId) {
61741
+ for (const table of this.getCoreTables(sheetId)) {
61742
+ this.applyRangeChangeOnTable(sheetId, table, applyChange);
61702
61743
  }
61703
61744
  }
61704
61745
  allowDispatch(cmd) {
@@ -62661,7 +62702,7 @@ class PivotCorePlugin extends CorePlugin {
62661
62702
  }
62662
62703
  }
62663
62704
  }
62664
- adaptRanges(applyChange, sheetId, sheetName) {
62705
+ adaptRanges(applyChange) {
62665
62706
  for (const sheetId in this.compiledMeasureFormulas) {
62666
62707
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
62667
62708
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -66822,7 +66863,7 @@ class PivotUIPlugin extends CoreViewPlugin {
66822
66863
  if (!result) {
66823
66864
  return EMPTY_PIVOT_CELL;
66824
66865
  }
66825
- const { functionName, args } = result;
66866
+ let { functionName, args } = result;
66826
66867
  const formulaId = args[0];
66827
66868
  if (!formulaId) {
66828
66869
  return EMPTY_PIVOT_CELL;
@@ -66852,6 +66893,9 @@ class PivotUIPlugin extends CoreViewPlugin {
66852
66893
  return pivotCells[pivotCol][pivotRow];
66853
66894
  }
66854
66895
  try {
66896
+ const offsetRow = position.row - mainPosition.row;
66897
+ const offsetCol = position.col - mainPosition.col;
66898
+ args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
66855
66899
  if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
66856
66900
  const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
66857
66901
  return {
@@ -68050,7 +68094,8 @@ function transformAll(toTransform, executed) {
68050
68094
  // If the executed command is not in the registry, we skip it
68051
68095
  // because we know there won't be any transformation impacting the
68052
68096
  // commands to transform.
68053
- if (possibleTransformations.has(executedCommand.type)) {
68097
+ if (possibleTransformations.has(executedCommand.type) ||
68098
+ rangeAdapterRegistry.contains(executedCommand.type)) {
68054
68099
  transformedCommands = transformedCommands.reduce((acc, cmd) => {
68055
68100
  const transformed = transform(cmd, executedCommand);
68056
68101
  if (transformed) {
@@ -79211,7 +79256,7 @@ function figureCoordinates(headers, anchor, offset) {
79211
79256
  for (const [headerIndex, header] of headers.slice(anchor).entries()) {
79212
79257
  if (currentPosition <= offset && offset < currentPosition + header.size) {
79213
79258
  return {
79214
- index: headerIndex,
79259
+ index: anchor + headerIndex,
79215
79260
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
79216
79261
  };
79217
79262
  }
@@ -80207,7 +80252,7 @@ class Model extends EventBus {
80207
80252
  handlers = [];
80208
80253
  uiHandlers = [];
80209
80254
  coreHandlers = [];
80210
- constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
80255
+ constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
80211
80256
  const start = performance.now();
80212
80257
  console.debug("##### Model creation #####");
80213
80258
  super();
@@ -80904,6 +80949,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
80904
80949
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, 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 };
80905
80950
 
80906
80951
 
80907
- __info__.version = "18.3.17";
80908
- __info__.date = "2025-08-21T06:40:44.469Z";
80909
- __info__.hash = "ab02b0c";
80952
+ __info__.version = "18.3.19";
80953
+ __info__.date = "2025-09-05T07:38:30.661Z";
80954
+ __info__.hash = "77fd307";