@odoo/o-spreadsheet 16.1.27 → 16.1.28

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.
@@ -622,13 +622,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
622
622
  }
623
623
 
624
624
  //------------------------------------------------------------------------------
625
- /**
626
- * Stringify an object, like JSON.stringify, except that the first level of keys
627
- * is ordered.
628
- */
629
- function stringify(obj) {
630
- return JSON.stringify(obj, Object.keys(obj).sort());
631
- }
632
625
  /**
633
626
  * Remove quotes from a quoted string
634
627
  * ```js
@@ -924,7 +917,7 @@ function isObjectEmptyRecursive(argument) {
924
917
  */
925
918
  function getItemId(item, itemsDic) {
926
919
  for (let [key, value] of Object.entries(itemsDic)) {
927
- if (stringify(value) === stringify(item)) {
920
+ if (deepEquals(value, item)) {
928
921
  return parseInt(key, 10);
929
922
  }
930
923
  }
@@ -1060,6 +1053,22 @@ function transpose2dArray(matrix) {
1060
1053
  if (!matrix.length)
1061
1054
  return matrix;
1062
1055
  return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1056
+ }
1057
+ /**
1058
+ * Creates a version of the function that's memoized on the value of its first
1059
+ * argument, if any.
1060
+ */
1061
+ function memoize(func) {
1062
+ const cache = new Map();
1063
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1064
+ return {
1065
+ [funcName](...args) {
1066
+ if (!cache.has(args[0])) {
1067
+ cache.set(args[0], func(...args));
1068
+ }
1069
+ return cache.get(args[0]);
1070
+ },
1071
+ }[funcName];
1063
1072
  }
1064
1073
 
1065
1074
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -3656,6 +3665,7 @@ var CommandResult;
3656
3665
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
3657
3666
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
3658
3667
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
3668
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
3659
3669
  })(CommandResult || (CommandResult = {}));
3660
3670
 
3661
3671
  function isMatrix(x) {
@@ -8019,12 +8029,12 @@ function toString(value) {
8019
8029
  }
8020
8030
  }
8021
8031
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
8022
- function normalizeString(str) {
8032
+ const normalizeString = memoize(function normalizeString(str) {
8023
8033
  return str
8024
8034
  .toLowerCase()
8025
8035
  .normalize("NFD")
8026
8036
  .replace(/[\u0300-\u036f]/g, "");
8027
- }
8037
+ });
8028
8038
  /**
8029
8039
  * Normalize a value.
8030
8040
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -27941,6 +27951,14 @@ class BordersPlugin extends CorePlugin {
27941
27951
  // ---------------------------------------------------------------------------
27942
27952
  // Command Handling
27943
27953
  // ---------------------------------------------------------------------------
27954
+ allowDispatch(cmd) {
27955
+ switch (cmd.type) {
27956
+ case "SET_BORDER":
27957
+ return this.checkBordersUnchanged(cmd);
27958
+ default:
27959
+ return 0 /* CommandResult.Success */;
27960
+ }
27961
+ }
27944
27962
  handle(cmd) {
27945
27963
  switch (cmd.type) {
27946
27964
  case "ADD_MERGE":
@@ -28336,6 +28354,15 @@ class BordersPlugin extends CorePlugin {
28336
28354
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
28337
28355
  }
28338
28356
  }
28357
+ checkBordersUnchanged(cmd) {
28358
+ var _a, _b, _c, _d;
28359
+ const currentBorder = this.getCellBorder(cmd);
28360
+ const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
28361
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
28362
+ return 88 /* CommandResult.NoChanges */;
28363
+ }
28364
+ return 0 /* CommandResult.Success */;
28365
+ }
28339
28366
  // ---------------------------------------------------------------------------
28340
28367
  // Import/Export
28341
28368
  // ---------------------------------------------------------------------------
@@ -28371,7 +28398,7 @@ class BordersPlugin extends CorePlugin {
28371
28398
  */
28372
28399
  function getBorderId(border) {
28373
28400
  for (let [key, value] of Object.entries(borders)) {
28374
- if (stringify(value) === stringify(border)) {
28401
+ if (deepEquals(value, border)) {
28375
28402
  return parseInt(key, 10);
28376
28403
  }
28377
28404
  }
@@ -28439,8 +28466,9 @@ class CellPlugin extends CorePlugin {
28439
28466
  allowDispatch(cmd) {
28440
28467
  switch (cmd.type) {
28441
28468
  case "UPDATE_CELL":
28469
+ return this.checkCellOutOfSheet(cmd);
28442
28470
  case "CLEAR_CELL":
28443
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28471
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28444
28472
  default:
28445
28473
  return 0 /* CommandResult.Success */;
28446
28474
  }
@@ -28599,14 +28627,9 @@ class CellPlugin extends CorePlugin {
28599
28627
  */
28600
28628
  getCellById(cellId) {
28601
28629
  // this must be as fast as possible
28602
- for (const sheetId in this.cells) {
28603
- const sheet = this.cells[sheetId];
28604
- const cell = sheet[cellId];
28605
- if (cell) {
28606
- return cell;
28607
- }
28608
- }
28609
- return undefined;
28630
+ const position = this.getters.getCellPosition(cellId);
28631
+ const sheet = this.cells[position.sheetId];
28632
+ return sheet[cellId];
28610
28633
  }
28611
28634
  /*
28612
28635
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28847,13 +28870,23 @@ class CellPlugin extends CorePlugin {
28847
28870
  dependencies: [],
28848
28871
  };
28849
28872
  }
28850
- checkCellOutOfSheet(sheetId, col, row) {
28873
+ checkCellOutOfSheet(cmd) {
28874
+ const { sheetId, col, row } = cmd;
28851
28875
  const sheet = this.getters.tryGetSheet(sheetId);
28852
28876
  if (!sheet)
28853
28877
  return 27 /* CommandResult.InvalidSheetId */;
28854
28878
  const sheetZone = this.getters.getSheetZone(sheetId);
28855
28879
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28856
28880
  }
28881
+ checkUselessClearCell(cmd) {
28882
+ const cell = this.getters.getCell(cmd);
28883
+ if (!cell)
28884
+ return 88 /* CommandResult.NoChanges */;
28885
+ if (!cell.content && !cell.style && !cell.format) {
28886
+ return 88 /* CommandResult.NoChanges */;
28887
+ }
28888
+ return 0 /* CommandResult.Success */;
28889
+ }
28857
28890
  }
28858
28891
  CellPlugin.getters = [
28859
28892
  "zoneToXC",
@@ -31914,10 +31947,13 @@ class SheetPlugin extends CorePlugin {
31914
31947
  // begin with the end.
31915
31948
  rows.sort((a, b) => b - a);
31916
31949
  for (let group of groupConsecutive(rows)) {
31950
+ // indexes are sorted in the descending order
31951
+ const from = group[group.length - 1];
31952
+ const to = group[0];
31917
31953
  // Move the cells.
31918
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31919
- // Effectively delete the element and recompute the left-right/top-bottom.
31920
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
31954
+ this.moveCellOnRowsDeletion(sheet, from, to);
31955
+ // Effectively delete the rows
31956
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31921
31957
  }
31922
31958
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31923
31959
  if (count) {
@@ -31939,8 +31975,6 @@ class SheetPlugin extends CorePlugin {
31939
31975
  this.addEmptyRows(sheet, quantity);
31940
31976
  // Move the cells.
31941
31977
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31942
- // Recompute the left-right/top-bottom.
31943
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31944
31978
  if (index < sheet.panes.ySplit) {
31945
31979
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31946
31980
  }
@@ -32041,35 +32075,20 @@ class SheetPlugin extends CorePlugin {
32041
32075
  }
32042
32076
  }
32043
32077
  }
32044
- updateRowsStructureOnDeletion(index, sheet) {
32078
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
32045
32079
  const rows = [];
32046
- const cellsQueue = sheet.rows.map((row) => row.cells);
32080
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
32047
32081
  for (let i in sheet.rows) {
32048
- if (Number(i) === index) {
32082
+ const row = Number(i);
32083
+ if (row >= deleteFromRow && row <= deleteToRow) {
32049
32084
  continue;
32050
32085
  }
32051
32086
  rows.push({
32052
- cells: cellsQueue.shift(),
32087
+ cells: cellsQueue.pop(),
32053
32088
  });
32054
32089
  }
32055
32090
  this.history.update("sheets", sheet.id, "rows", rows);
32056
32091
  }
32057
- /**
32058
- * Update the rows of the sheet after an addition:
32059
- * - Rename the rows
32060
- *
32061
- * @param sheet Sheet on which the deletion occurs
32062
- * @param addedRow Index of the added row
32063
- * @param rowsToAdd Number of the rows to add
32064
- */
32065
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
32066
- const rows = [];
32067
- const cellsQueue = sheet.rows.map((row) => row.cells);
32068
- sheet.rows.forEach(() => rows.push({
32069
- cells: cellsQueue.shift(),
32070
- }));
32071
- this.history.update("sheets", sheet.id, "rows", rows);
32072
- }
32073
32092
  /**
32074
32093
  * Add empty rows at the end of the rows
32075
32094
  *
@@ -32526,6 +32545,7 @@ class EvaluationPlugin extends UIPlugin {
32526
32545
  }
32527
32546
  return evaluatedCell;
32528
32547
  };
32548
+ const rangeCache = {};
32529
32549
  /**
32530
32550
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32531
32551
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32542,21 +32562,26 @@ class EvaluationPlugin extends UIPlugin {
32542
32562
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32543
32563
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32544
32564
  const sheetZone = getters.getSheetZone(sheetId);
32545
- const result = [];
32546
32565
  const zone = intersection(range.zone, sheetZone);
32547
32566
  if (!zone) {
32548
- result.push([]);
32549
- return result;
32567
+ return [[]];
32568
+ }
32569
+ const { top, left, bottom, right } = zone;
32570
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32571
+ if (cacheKey in rangeCache) {
32572
+ return rangeCache[cacheKey];
32550
32573
  }
32574
+ const result = new Array(right - left + 1);
32551
32575
  // Performance issue: nested loop is faster than a map here
32552
- for (let col = zone.left; col <= zone.right; col++) {
32553
- const rowValues = [];
32554
- for (let row = zone.top; row <= zone.bottom; row++) {
32576
+ for (let col = left; col <= right; col++) {
32577
+ const rowValues = new Array(bottom - top + 1);
32578
+ for (let row = top; row <= bottom; row++) {
32555
32579
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32556
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32580
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32557
32581
  }
32558
- result.push(rowValues);
32582
+ result[col - left] = rowValues;
32559
32583
  }
32584
+ rangeCache[cacheKey] = result;
32560
32585
  return result;
32561
32586
  }
32562
32587
  /**
@@ -41670,9 +41695,9 @@ function revertChanges(revisions) {
41670
41695
  * Apply the changes of the given HistoryChange to the state
41671
41696
  */
41672
41697
  function applyChange(change, target) {
41673
- let val = change.root;
41674
- let key = change.path[change.path.length - 1];
41675
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41698
+ let val = change.path[0];
41699
+ const key = change.path[change.path.length - 1];
41700
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41676
41701
  const p = change.path[pathIndex];
41677
41702
  if (val[p] === undefined) {
41678
41703
  const nextPath = change.path[pathIndex + 1];
@@ -42427,13 +42452,14 @@ class StateObserver {
42427
42452
  }
42428
42453
  addChange(...args) {
42429
42454
  const val = args.pop();
42430
- const [root, ...path] = args;
42455
+ const root = args[0];
42431
42456
  let value = root;
42432
- let key = path[path.length - 1];
42433
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
42434
- const p = path[pathIndex];
42457
+ let key = args[args.length - 1];
42458
+ const pathLength = args.length - 2;
42459
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
42460
+ const p = args[pathIndex];
42435
42461
  if (value[p] === undefined) {
42436
- const nextPath = path[pathIndex + 1];
42462
+ const nextPath = args[pathIndex + 1];
42437
42463
  value[p] = createEmptyStructure(nextPath);
42438
42464
  }
42439
42465
  value = value[p];
@@ -42442,8 +42468,7 @@ class StateObserver {
42442
42468
  return;
42443
42469
  }
42444
42470
  this.changes.push({
42445
- root,
42446
- path,
42471
+ path: args,
42447
42472
  before: value[key],
42448
42473
  after: val,
42449
42474
  });
@@ -44217,7 +44242,10 @@ class Model extends EventBus {
44217
44242
  */
44218
44243
  checkDispatchAllowed(command) {
44219
44244
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
44220
- return new DispatchResult(results.flat());
44245
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
44246
+ return new DispatchResult(results.flat());
44247
+ }
44248
+ return DispatchResult.Success;
44221
44249
  }
44222
44250
  finalize() {
44223
44251
  this.status = 3 /* Status.Finalizing */;
@@ -44417,6 +44445,6 @@ function addFunction(functionName, functionDescription) {
44417
44445
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
44418
44446
 
44419
44447
 
44420
- __info__.version = '16.1.27';
44421
- __info__.date = '2023-11-16T11:57:02.419Z';
44422
- __info__.hash = '81f7214';
44448
+ __info__.version = '16.1.28';
44449
+ __info__.date = '2023-11-24T13:11:01.992Z';
44450
+ __info__.hash = '257f369';
@@ -623,13 +623,6 @@
623
623
  }
624
624
 
625
625
  //------------------------------------------------------------------------------
626
- /**
627
- * Stringify an object, like JSON.stringify, except that the first level of keys
628
- * is ordered.
629
- */
630
- function stringify(obj) {
631
- return JSON.stringify(obj, Object.keys(obj).sort());
632
- }
633
626
  /**
634
627
  * Remove quotes from a quoted string
635
628
  * ```js
@@ -925,7 +918,7 @@
925
918
  */
926
919
  function getItemId(item, itemsDic) {
927
920
  for (let [key, value] of Object.entries(itemsDic)) {
928
- if (stringify(value) === stringify(item)) {
921
+ if (deepEquals(value, item)) {
929
922
  return parseInt(key, 10);
930
923
  }
931
924
  }
@@ -1061,6 +1054,22 @@
1061
1054
  if (!matrix.length)
1062
1055
  return matrix;
1063
1056
  return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1057
+ }
1058
+ /**
1059
+ * Creates a version of the function that's memoized on the value of its first
1060
+ * argument, if any.
1061
+ */
1062
+ function memoize(func) {
1063
+ const cache = new Map();
1064
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1065
+ return {
1066
+ [funcName](...args) {
1067
+ if (!cache.has(args[0])) {
1068
+ cache.set(args[0], func(...args));
1069
+ }
1070
+ return cache.get(args[0]);
1071
+ },
1072
+ }[funcName];
1064
1073
  }
1065
1074
 
1066
1075
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -3657,6 +3666,7 @@
3657
3666
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
3658
3667
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
3659
3668
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
3669
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
3660
3670
  })(exports.CommandResult || (exports.CommandResult = {}));
3661
3671
 
3662
3672
  function isMatrix(x) {
@@ -8020,12 +8030,12 @@
8020
8030
  }
8021
8031
  }
8022
8032
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
8023
- function normalizeString(str) {
8033
+ const normalizeString = memoize(function normalizeString(str) {
8024
8034
  return str
8025
8035
  .toLowerCase()
8026
8036
  .normalize("NFD")
8027
8037
  .replace(/[\u0300-\u036f]/g, "");
8028
- }
8038
+ });
8029
8039
  /**
8030
8040
  * Normalize a value.
8031
8041
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -27942,6 +27952,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
27942
27952
  // ---------------------------------------------------------------------------
27943
27953
  // Command Handling
27944
27954
  // ---------------------------------------------------------------------------
27955
+ allowDispatch(cmd) {
27956
+ switch (cmd.type) {
27957
+ case "SET_BORDER":
27958
+ return this.checkBordersUnchanged(cmd);
27959
+ default:
27960
+ return 0 /* CommandResult.Success */;
27961
+ }
27962
+ }
27945
27963
  handle(cmd) {
27946
27964
  switch (cmd.type) {
27947
27965
  case "ADD_MERGE":
@@ -28337,6 +28355,15 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28337
28355
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
28338
28356
  }
28339
28357
  }
28358
+ checkBordersUnchanged(cmd) {
28359
+ var _a, _b, _c, _d;
28360
+ const currentBorder = this.getCellBorder(cmd);
28361
+ const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
28362
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
28363
+ return 88 /* CommandResult.NoChanges */;
28364
+ }
28365
+ return 0 /* CommandResult.Success */;
28366
+ }
28340
28367
  // ---------------------------------------------------------------------------
28341
28368
  // Import/Export
28342
28369
  // ---------------------------------------------------------------------------
@@ -28372,7 +28399,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28372
28399
  */
28373
28400
  function getBorderId(border) {
28374
28401
  for (let [key, value] of Object.entries(borders)) {
28375
- if (stringify(value) === stringify(border)) {
28402
+ if (deepEquals(value, border)) {
28376
28403
  return parseInt(key, 10);
28377
28404
  }
28378
28405
  }
@@ -28440,8 +28467,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28440
28467
  allowDispatch(cmd) {
28441
28468
  switch (cmd.type) {
28442
28469
  case "UPDATE_CELL":
28470
+ return this.checkCellOutOfSheet(cmd);
28443
28471
  case "CLEAR_CELL":
28444
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28472
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28445
28473
  default:
28446
28474
  return 0 /* CommandResult.Success */;
28447
28475
  }
@@ -28600,14 +28628,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28600
28628
  */
28601
28629
  getCellById(cellId) {
28602
28630
  // this must be as fast as possible
28603
- for (const sheetId in this.cells) {
28604
- const sheet = this.cells[sheetId];
28605
- const cell = sheet[cellId];
28606
- if (cell) {
28607
- return cell;
28608
- }
28609
- }
28610
- return undefined;
28631
+ const position = this.getters.getCellPosition(cellId);
28632
+ const sheet = this.cells[position.sheetId];
28633
+ return sheet[cellId];
28611
28634
  }
28612
28635
  /*
28613
28636
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28848,13 +28871,23 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28848
28871
  dependencies: [],
28849
28872
  };
28850
28873
  }
28851
- checkCellOutOfSheet(sheetId, col, row) {
28874
+ checkCellOutOfSheet(cmd) {
28875
+ const { sheetId, col, row } = cmd;
28852
28876
  const sheet = this.getters.tryGetSheet(sheetId);
28853
28877
  if (!sheet)
28854
28878
  return 27 /* CommandResult.InvalidSheetId */;
28855
28879
  const sheetZone = this.getters.getSheetZone(sheetId);
28856
28880
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28857
28881
  }
28882
+ checkUselessClearCell(cmd) {
28883
+ const cell = this.getters.getCell(cmd);
28884
+ if (!cell)
28885
+ return 88 /* CommandResult.NoChanges */;
28886
+ if (!cell.content && !cell.style && !cell.format) {
28887
+ return 88 /* CommandResult.NoChanges */;
28888
+ }
28889
+ return 0 /* CommandResult.Success */;
28890
+ }
28858
28891
  }
28859
28892
  CellPlugin.getters = [
28860
28893
  "zoneToXC",
@@ -31915,10 +31948,13 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31915
31948
  // begin with the end.
31916
31949
  rows.sort((a, b) => b - a);
31917
31950
  for (let group of groupConsecutive(rows)) {
31951
+ // indexes are sorted in the descending order
31952
+ const from = group[group.length - 1];
31953
+ const to = group[0];
31918
31954
  // Move the cells.
31919
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31920
- // Effectively delete the element and recompute the left-right/top-bottom.
31921
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
31955
+ this.moveCellOnRowsDeletion(sheet, from, to);
31956
+ // Effectively delete the rows
31957
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31922
31958
  }
31923
31959
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31924
31960
  if (count) {
@@ -31940,8 +31976,6 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31940
31976
  this.addEmptyRows(sheet, quantity);
31941
31977
  // Move the cells.
31942
31978
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31943
- // Recompute the left-right/top-bottom.
31944
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31945
31979
  if (index < sheet.panes.ySplit) {
31946
31980
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31947
31981
  }
@@ -32042,35 +32076,20 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32042
32076
  }
32043
32077
  }
32044
32078
  }
32045
- updateRowsStructureOnDeletion(index, sheet) {
32079
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
32046
32080
  const rows = [];
32047
- const cellsQueue = sheet.rows.map((row) => row.cells);
32081
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
32048
32082
  for (let i in sheet.rows) {
32049
- if (Number(i) === index) {
32083
+ const row = Number(i);
32084
+ if (row >= deleteFromRow && row <= deleteToRow) {
32050
32085
  continue;
32051
32086
  }
32052
32087
  rows.push({
32053
- cells: cellsQueue.shift(),
32088
+ cells: cellsQueue.pop(),
32054
32089
  });
32055
32090
  }
32056
32091
  this.history.update("sheets", sheet.id, "rows", rows);
32057
32092
  }
32058
- /**
32059
- * Update the rows of the sheet after an addition:
32060
- * - Rename the rows
32061
- *
32062
- * @param sheet Sheet on which the deletion occurs
32063
- * @param addedRow Index of the added row
32064
- * @param rowsToAdd Number of the rows to add
32065
- */
32066
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
32067
- const rows = [];
32068
- const cellsQueue = sheet.rows.map((row) => row.cells);
32069
- sheet.rows.forEach(() => rows.push({
32070
- cells: cellsQueue.shift(),
32071
- }));
32072
- this.history.update("sheets", sheet.id, "rows", rows);
32073
- }
32074
32093
  /**
32075
32094
  * Add empty rows at the end of the rows
32076
32095
  *
@@ -32527,6 +32546,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32527
32546
  }
32528
32547
  return evaluatedCell;
32529
32548
  };
32549
+ const rangeCache = {};
32530
32550
  /**
32531
32551
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32532
32552
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32543,21 +32563,26 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32543
32563
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32544
32564
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32545
32565
  const sheetZone = getters.getSheetZone(sheetId);
32546
- const result = [];
32547
32566
  const zone = intersection(range.zone, sheetZone);
32548
32567
  if (!zone) {
32549
- result.push([]);
32550
- return result;
32568
+ return [[]];
32569
+ }
32570
+ const { top, left, bottom, right } = zone;
32571
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32572
+ if (cacheKey in rangeCache) {
32573
+ return rangeCache[cacheKey];
32551
32574
  }
32575
+ const result = new Array(right - left + 1);
32552
32576
  // Performance issue: nested loop is faster than a map here
32553
- for (let col = zone.left; col <= zone.right; col++) {
32554
- const rowValues = [];
32555
- for (let row = zone.top; row <= zone.bottom; row++) {
32577
+ for (let col = left; col <= right; col++) {
32578
+ const rowValues = new Array(bottom - top + 1);
32579
+ for (let row = top; row <= bottom; row++) {
32556
32580
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32557
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32581
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32558
32582
  }
32559
- result.push(rowValues);
32583
+ result[col - left] = rowValues;
32560
32584
  }
32585
+ rangeCache[cacheKey] = result;
32561
32586
  return result;
32562
32587
  }
32563
32588
  /**
@@ -41671,9 +41696,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
41671
41696
  * Apply the changes of the given HistoryChange to the state
41672
41697
  */
41673
41698
  function applyChange(change, target) {
41674
- let val = change.root;
41675
- let key = change.path[change.path.length - 1];
41676
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41699
+ let val = change.path[0];
41700
+ const key = change.path[change.path.length - 1];
41701
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41677
41702
  const p = change.path[pathIndex];
41678
41703
  if (val[p] === undefined) {
41679
41704
  const nextPath = change.path[pathIndex + 1];
@@ -42428,13 +42453,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42428
42453
  }
42429
42454
  addChange(...args) {
42430
42455
  const val = args.pop();
42431
- const [root, ...path] = args;
42456
+ const root = args[0];
42432
42457
  let value = root;
42433
- let key = path[path.length - 1];
42434
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
42435
- const p = path[pathIndex];
42458
+ let key = args[args.length - 1];
42459
+ const pathLength = args.length - 2;
42460
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
42461
+ const p = args[pathIndex];
42436
42462
  if (value[p] === undefined) {
42437
- const nextPath = path[pathIndex + 1];
42463
+ const nextPath = args[pathIndex + 1];
42438
42464
  value[p] = createEmptyStructure(nextPath);
42439
42465
  }
42440
42466
  value = value[p];
@@ -42443,8 +42469,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42443
42469
  return;
42444
42470
  }
42445
42471
  this.changes.push({
42446
- root,
42447
- path,
42472
+ path: args,
42448
42473
  before: value[key],
42449
42474
  after: val,
42450
42475
  });
@@ -44218,7 +44243,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
44218
44243
  */
44219
44244
  checkDispatchAllowed(command) {
44220
44245
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
44221
- return new DispatchResult(results.flat());
44246
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
44247
+ return new DispatchResult(results.flat());
44248
+ }
44249
+ return DispatchResult.Success;
44222
44250
  }
44223
44251
  finalize() {
44224
44252
  this.status = 3 /* Status.Finalizing */;
@@ -44448,9 +44476,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
44448
44476
  Object.defineProperty(exports, '__esModule', { value: true });
44449
44477
 
44450
44478
 
44451
- __info__.version = '16.1.27';
44452
- __info__.date = '2023-11-16T11:57:02.419Z';
44453
- __info__.hash = '81f7214';
44479
+ __info__.version = '16.1.28';
44480
+ __info__.date = '2023-11-24T13:11:01.992Z';
44481
+ __info__.hash = '257f369';
44454
44482
 
44455
44483
 
44456
44484
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);