@odoo/o-spreadsheet 18.0.50 → 18.0.54

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.0.50
6
- * @date 2025-12-02T05:32:00.480Z
7
- * @hash 7ed20c4
5
+ * @version 18.0.54
6
+ * @date 2026-01-14T10:00:02.287Z
7
+ * @hash c0048a0
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -5839,17 +5839,41 @@
5839
5839
  const today = DateTime.now();
5840
5840
  switch (dateValue) {
5841
5841
  case "today":
5842
- return jsDateToNumber(today);
5843
- case "yesterday":
5844
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
5845
- case "tomorrow":
5846
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
5842
+ return Math.floor(jsDateToNumber(today));
5843
+ case "yesterday": {
5844
+ today.setDate(today.getDate() - 1);
5845
+ return Math.floor(jsDateToNumber(today));
5846
+ }
5847
+ case "tomorrow": {
5848
+ today.setDate(today.getDate() + 1);
5849
+ return Math.floor(jsDateToNumber(today));
5850
+ }
5847
5851
  case "lastWeek":
5848
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
5849
- case "lastMonth":
5850
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
5852
+ today.setDate(today.getDate() - 6);
5853
+ return Math.floor(jsDateToNumber(today));
5854
+ case "lastMonth": {
5855
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
5856
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
5857
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
5858
+ today.setDate(1);
5859
+ }
5860
+ else {
5861
+ today.setDate(today.getDate() + 1);
5862
+ today.setMonth(today.getMonth() - 1);
5863
+ }
5864
+ return Math.floor(jsDateToNumber(today));
5865
+ }
5851
5866
  case "lastYear":
5852
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
5867
+ // Handle leap year case
5868
+ if (today.getMonth() === 1 && today.getDate() === 29) {
5869
+ today.setDate(28);
5870
+ today.setFullYear(today.getFullYear() - 1);
5871
+ }
5872
+ else {
5873
+ today.setDate(today.getDate() + 1);
5874
+ today.setFullYear(today.getFullYear() - 1);
5875
+ }
5876
+ return Math.floor(jsDateToNumber(today));
5853
5877
  }
5854
5878
  }
5855
5879
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -18540,9 +18564,10 @@ stores.inject(MyMetaStore, storeInstance);
18540
18564
  throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
18541
18565
  }
18542
18566
  }
18543
- function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
18567
+ function addPivotDependencies(evalContext, pivotId, forMeasures) {
18544
18568
  //TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
18545
18569
  const dependencies = [];
18570
+ const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
18546
18571
  if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
18547
18572
  const { sheetId, zone } = coreDefinition.dataSet;
18548
18573
  const xc = zoneToXc(zone);
@@ -18559,8 +18584,7 @@ stores.inject(MyMetaStore, storeInstance);
18559
18584
  }
18560
18585
  for (const measure of forMeasures) {
18561
18586
  if (measure.computedBy) {
18562
- const formula = evalContext.getters.getMeasureCompiledFormula(measure);
18563
- dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
18587
+ dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
18564
18588
  }
18565
18589
  }
18566
18590
  const originPosition = evalContext.__originCellPosition;
@@ -19001,7 +19025,7 @@ stores.inject(MyMetaStore, storeInstance);
19001
19025
  assertDomainLength(domainArgs);
19002
19026
  const pivot = this.getters.getPivot(pivotId);
19003
19027
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
19004
- addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
19028
+ addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
19005
19029
  pivot.init({ reload: pivot.needsReevaluation });
19006
19030
  const error = pivot.assertIsValid({ throwOnError: false });
19007
19031
  if (error) {
@@ -19034,8 +19058,7 @@ stores.inject(MyMetaStore, storeInstance);
19034
19058
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
19035
19059
  assertDomainLength(domainArgs);
19036
19060
  const pivot = this.getters.getPivot(_pivotId);
19037
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
19038
- addPivotDependencies(this, coreDefinition, []);
19061
+ addPivotDependencies(this, _pivotId, []);
19039
19062
  pivot.init({ reload: pivot.needsReevaluation });
19040
19063
  const error = pivot.assertIsValid({ throwOnError: false });
19041
19064
  if (error) {
@@ -19089,7 +19112,7 @@ stores.inject(MyMetaStore, storeInstance);
19089
19112
  const pivotId = getPivotId(_pivotFormulaId, this.getters);
19090
19113
  const pivot = this.getters.getPivot(pivotId);
19091
19114
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
19092
- addPivotDependencies(this, coreDefinition, coreDefinition.measures);
19115
+ addPivotDependencies(this, pivotId, coreDefinition.measures);
19093
19116
  pivot.init({ reload: pivot.needsReevaluation });
19094
19117
  const error = pivot.assertIsValid({ throwOnError: false });
19095
19118
  if (error) {
@@ -40346,14 +40369,15 @@ stores.inject(MyMetaStore, storeInstance);
40346
40369
  }
40347
40370
 
40348
40371
  css /* scss */ `
40349
- .o-cf-preview {
40372
+ .o-spreadsheet .o-cf-preview {
40350
40373
  &.o-cf-cursor-ptr {
40351
40374
  cursor: pointer;
40352
40375
  }
40353
40376
 
40354
40377
  border-bottom: 1px solid ${GRAY_300};
40355
- height: 60px;
40378
+ height: 80px;
40356
40379
  padding: 10px;
40380
+ box-sizing: border-box;
40357
40381
  position: relative;
40358
40382
  cursor: pointer;
40359
40383
  &:hover,
@@ -40367,7 +40391,6 @@ stores.inject(MyMetaStore, storeInstance);
40367
40391
  .o-cf-preview-icon {
40368
40392
  border: 1px solid ${GRAY_300};
40369
40393
  background-color: #fff;
40370
- position: absolute;
40371
40394
  height: 50px;
40372
40395
  width: 50px;
40373
40396
  .o-icon {
@@ -40376,12 +40399,6 @@ stores.inject(MyMetaStore, storeInstance);
40376
40399
  }
40377
40400
  }
40378
40401
  .o-cf-preview-description {
40379
- left: 65px;
40380
- margin-bottom: auto;
40381
- margin-right: 8px;
40382
- margin-top: auto;
40383
- position: relative;
40384
- width: 142px;
40385
40402
  .o-cf-preview-description-rule {
40386
40403
  margin-bottom: 4px;
40387
40404
  max-height: 2.8em;
@@ -40391,16 +40408,11 @@ stores.inject(MyMetaStore, storeInstance);
40391
40408
  font-size: 12px;
40392
40409
  }
40393
40410
  }
40394
- .o-cf-delete {
40395
- left: 90%;
40396
- top: 39%;
40397
- position: absolute;
40398
- }
40399
40411
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
40400
40412
  display: none !important;
40401
40413
  }
40402
40414
  .o-cf-drag-handle {
40403
- left: -8px;
40415
+ left: 2px;
40404
40416
  cursor: move;
40405
40417
  .o-icon {
40406
40418
  width: 6px;
@@ -41285,7 +41297,7 @@ stores.inject(MyMetaStore, storeInstance);
41285
41297
  return false;
41286
41298
  }
41287
41299
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
41288
- const today = jsDateToRoundNumber(DateTime.now());
41300
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
41289
41301
  return isDateBetween(dateValue, today, criterionValue);
41290
41302
  }
41291
41303
  return areDatesSameDay(dateValue, criterionValue);
@@ -42447,6 +42459,11 @@ stores.inject(MyMetaStore, storeInstance);
42447
42459
  case "UPDATE_CELL":
42448
42460
  case "ACTIVATE_SHEET":
42449
42461
  this.isSearchDirty = true;
42462
+ if (this.searchOptions.specificRange) {
42463
+ this.searchOptions.specificRange = this.searchOptions.specificRange.clone({
42464
+ sheetId: this.getters.getActiveSheetId(),
42465
+ });
42466
+ }
42450
42467
  break;
42451
42468
  case "REPLACE_SEARCH":
42452
42469
  for (const match of cmd.matches) {
@@ -42852,9 +42869,20 @@ stores.inject(MyMetaStore, storeInstance);
42852
42869
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
42853
42870
  this.store.updateSearchOptions({ specificRange });
42854
42871
  }
42872
+ get specificRange() {
42873
+ const range = this.store.searchOptions.specificRange;
42874
+ return range ? this.env.model.getters.getRangeString(range, "forceSheetReference") : "";
42875
+ }
42855
42876
  get pendingSearch() {
42856
42877
  return this.updateSearchContent.isDebouncePending();
42857
42878
  }
42879
+ get selectionInputKey() {
42880
+ // Selections input are made to work with objects linked to a sheet id. They store the active sheet id at their creation,
42881
+ // and have specific behaviour linked to it (eg. go back to the initial sheet after confirmation).
42882
+ // We don't want all those behaviors here, so we force the recreation of the component when the active sheet changes.
42883
+ // The only drawback is that the input loses focus when changing sheet.
42884
+ return this.env.model.getters.getActiveSheetId();
42885
+ }
42858
42886
  }
42859
42887
 
42860
42888
  css /* scss */ `
@@ -44989,7 +45017,37 @@ stores.inject(MyMetaStore, storeInstance);
44989
45017
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
44990
45018
  isMeasureCandidate: (field) => !["datetime", "boolean"].includes(field.type),
44991
45019
  isGroupable: () => true,
45020
+ adaptRanges: (getters, definition, applyChange) => {
45021
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
45022
+ return definition;
45023
+ }
45024
+ const { sheetId, zone } = definition.dataSet;
45025
+ const range = getters.getRangeFromZone(sheetId, zone);
45026
+ const adaptedRange = adaptPivotRange(range, applyChange);
45027
+ if (adaptedRange === range) {
45028
+ return definition;
45029
+ }
45030
+ const dataSet = adaptedRange && {
45031
+ sheetId: adaptedRange.sheetId,
45032
+ zone: adaptedRange.zone,
45033
+ };
45034
+ return { ...definition, dataSet };
45035
+ },
44992
45036
  });
45037
+ function adaptPivotRange(range, applyChange) {
45038
+ if (!range) {
45039
+ return undefined;
45040
+ }
45041
+ const change = applyChange(range);
45042
+ switch (change.changeType) {
45043
+ case "NONE":
45044
+ return range;
45045
+ case "REMOVE":
45046
+ return undefined;
45047
+ default:
45048
+ return change.range;
45049
+ }
45050
+ }
44993
45051
 
44994
45052
  class PivotSidePanelStore extends SpreadsheetStore {
44995
45053
  pivotId;
@@ -46876,21 +46934,20 @@ stores.inject(MyMetaStore, storeInstance);
46876
46934
  this.highlightStore.register(this);
46877
46935
  }
46878
46936
  get highlights() {
46879
- let zone;
46880
46937
  const position = this.model.getters.getActivePosition();
46881
- const cell = this.getters.getEvaluatedCell(position);
46882
46938
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
46883
- zone = spreader
46939
+ const zone = spreader
46884
46940
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
46885
46941
  : this.model.getters.getSpreadZone(position, { ignoreSpillError: true });
46886
46942
  if (!zone) {
46887
46943
  return [];
46888
46944
  }
46945
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
46889
46946
  return [
46890
46947
  {
46891
46948
  sheetId: position.sheetId,
46892
46949
  zone,
46893
- dashed: cell.value === CellErrorType.SpilledBlocked,
46950
+ dashed: isArrayFormulaBlocked,
46894
46951
  color: "#17A2B8",
46895
46952
  noFill: true,
46896
46953
  thinLine: true,
@@ -54951,6 +55008,7 @@ stores.inject(MyMetaStore, storeInstance);
54951
55008
  class RangeAdapter {
54952
55009
  getters;
54953
55010
  providers = [];
55011
+ isAdaptingRanges = false;
54954
55012
  constructor(getters) {
54955
55013
  this.getters = getters;
54956
55014
  }
@@ -54979,6 +55037,9 @@ stores.inject(MyMetaStore, storeInstance);
54979
55037
  }
54980
55038
  beforeHandle(command) { }
54981
55039
  handle(cmd) {
55040
+ if (this.isAdaptingRanges) {
55041
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
55042
+ }
54982
55043
  switch (cmd.type) {
54983
55044
  case "REMOVE_COLUMNS_ROWS": {
54984
55045
  let start = cmd.dimension === "COL" ? "left" : "top";
@@ -55134,10 +55195,12 @@ stores.inject(MyMetaStore, storeInstance);
55134
55195
  return adaptedRange;
55135
55196
  }
55136
55197
  executeOnAllRanges(adaptRange, sheetId) {
55198
+ this.isAdaptingRanges = true;
55137
55199
  const func = this.verifyRangeRemoved(adaptRange);
55138
55200
  for (const provider of this.providers) {
55139
55201
  provider(func, sheetId);
55140
55202
  }
55203
+ this.isAdaptingRanges = false;
55141
55204
  }
55142
55205
  /**
55143
55206
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -57156,6 +57219,7 @@ stores.inject(MyMetaStore, storeInstance);
57156
57219
  "getMeasureCompiledFormula",
57157
57220
  "getPivotName",
57158
57221
  "isExistingPivot",
57222
+ "getMeasureFullDependencies",
57159
57223
  ];
57160
57224
  nextFormulaId = 1;
57161
57225
  pivots = {};
@@ -57238,15 +57302,32 @@ stores.inject(MyMetaStore, storeInstance);
57238
57302
  }
57239
57303
  case "UPDATE_PIVOT": {
57240
57304
  this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
57241
- this.compileCalculatedMeasures(cmd.pivot.measures);
57305
+ this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
57242
57306
  break;
57243
57307
  }
57244
57308
  }
57245
57309
  }
57246
57310
  adaptRanges(applyChange) {
57247
- for (const sheetId in this.compiledMeasureFormulas) {
57248
- for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
57249
- const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
57311
+ for (const pivotId in this.pivots) {
57312
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
57313
+ if (!definition) {
57314
+ continue;
57315
+ }
57316
+ const newDefinition = pivotRegistry
57317
+ .get(definition.type)
57318
+ ?.adaptRanges?.(this.getters, definition, applyChange);
57319
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
57320
+ this.history.update("pivots", pivotId, "definition", newDefinition);
57321
+ }
57322
+ }
57323
+ for (const pivotId in this.compiledMeasureFormulas) {
57324
+ for (const measureId in this.compiledMeasureFormulas[pivotId]) {
57325
+ const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
57326
+ if (!measure || !measure.computedBy) {
57327
+ continue;
57328
+ }
57329
+ const sheetId = measure.computedBy.sheetId;
57330
+ const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
57250
57331
  const newDependencies = [];
57251
57332
  for (const range of compiledFormula.dependencies) {
57252
57333
  const change = applyChange(range);
@@ -57258,8 +57339,9 @@ stores.inject(MyMetaStore, storeInstance);
57258
57339
  }
57259
57340
  }
57260
57341
  const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
57261
- if (newFormulaString !== formulaString) {
57262
- this.replaceMeasureFormula(sheetId, formulaString, newFormulaString);
57342
+ const oldFormulaString = measure.computedBy.formula;
57343
+ if (newFormulaString !== oldFormulaString) {
57344
+ this.replaceMeasureFormula(pivotId, measure, newFormulaString);
57263
57345
  }
57264
57346
  }
57265
57347
  }
@@ -57297,31 +57379,60 @@ stores.inject(MyMetaStore, storeInstance);
57297
57379
  isExistingPivot(pivotId) {
57298
57380
  return pivotId in this.pivots;
57299
57381
  }
57300
- getMeasureCompiledFormula(measure) {
57382
+ getMeasureCompiledFormula(pivotId, measure) {
57383
+ if (!measure.computedBy) {
57384
+ throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
57385
+ }
57386
+ return this.compiledMeasureFormulas[pivotId][measure.id].formula;
57387
+ }
57388
+ getMeasureFullDependencies(pivotId, measure) {
57301
57389
  if (!measure.computedBy) {
57302
57390
  throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
57303
57391
  }
57304
- const sheetId = measure.computedBy.sheetId;
57305
- return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
57392
+ return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
57306
57393
  }
57307
57394
  // -------------------------------------------------------------------------
57308
57395
  // Private
57309
57396
  // -------------------------------------------------------------------------
57310
57397
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
57311
57398
  this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
57312
- this.compileCalculatedMeasures(pivot.measures);
57399
+ this.compileCalculatedMeasures(pivotId, pivot.measures);
57313
57400
  this.history.update("formulaIds", formulaId, pivotId);
57314
57401
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
57315
57402
  }
57316
- compileCalculatedMeasures(measures) {
57403
+ compileCalculatedMeasures(pivotId, measures) {
57317
57404
  for (const measure of measures) {
57318
57405
  if (measure.computedBy) {
57319
- const sheetId = measure.computedBy.sheetId;
57320
57406
  const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
57321
- this.history.update("compiledMeasureFormulas", sheetId, measure.computedBy.formula, compiledFormula);
57407
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
57408
+ }
57409
+ }
57410
+ for (const measure of measures) {
57411
+ if (measure.computedBy) {
57412
+ const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
57413
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
57322
57414
  }
57323
57415
  }
57324
57416
  }
57417
+ computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
57418
+ const rangeDependencies = [];
57419
+ const definition = this.getPivotCoreDefinition(pivotId);
57420
+ const formula = this.getMeasureCompiledFormula(pivotId, measure);
57421
+ exploredMeasures.add(measure.id);
57422
+ for (const token of formula.tokens) {
57423
+ if (token.type !== "SYMBOL") {
57424
+ continue;
57425
+ }
57426
+ const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
57427
+ measure.id !== measureCandidate.id);
57428
+ if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
57429
+ continue;
57430
+ }
57431
+ rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
57432
+ }
57433
+ rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
57434
+ return rangeDependencies;
57435
+ }
57325
57436
  insertPivot(position, formulaId, table) {
57326
57437
  this.resizeSheet(position.sheetId, position, table);
57327
57438
  const pivotCells = table.getPivotCells();
@@ -57378,28 +57489,17 @@ stores.inject(MyMetaStore, storeInstance);
57378
57489
  dependencies: rangeDependencies,
57379
57490
  };
57380
57491
  }
57381
- replaceMeasureFormula(sheetId, formulaString, newFormulaString) {
57382
- this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
57383
- this.history.update("compiledMeasureFormulas", sheetId, newFormulaString, this.compileMeasureFormula(sheetId, newFormulaString));
57384
- for (const pivotId in this.pivots) {
57385
- const pivot = this.pivots[pivotId];
57386
- if (!pivot) {
57387
- continue;
57388
- }
57389
- const def = deepCopy(pivot.definition);
57390
- for (const measure of def.measures) {
57391
- if (measure.computedBy?.formula === formulaString) {
57392
- const measureIndex = def.measures.indexOf(measure);
57393
- if (measureIndex !== -1) {
57394
- def.measures[measureIndex].computedBy = {
57395
- formula: newFormulaString,
57396
- sheetId,
57397
- };
57398
- }
57399
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: def });
57400
- }
57401
- }
57492
+ replaceMeasureFormula(pivotId, measure, newFormulaString) {
57493
+ const pivot = this.pivots[pivotId];
57494
+ if (!pivot) {
57495
+ return;
57402
57496
  }
57497
+ const measureIndex = pivot.definition.measures.indexOf(measure);
57498
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
57499
+ formula: newFormulaString,
57500
+ sheetId: measure.computedBy.sheetId,
57501
+ });
57502
+ this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
57403
57503
  }
57404
57504
  checkDuplicatedMeasureIds(definition) {
57405
57505
  const uniqueIds = new Set(definition.measures.map((m) => m.id));
@@ -57495,20 +57595,6 @@ stores.inject(MyMetaStore, storeInstance);
57495
57595
  }
57496
57596
  }
57497
57597
 
57498
- function adaptPivotRange(range, applyChange) {
57499
- if (!range) {
57500
- return undefined;
57501
- }
57502
- const change = applyChange(range);
57503
- switch (change.changeType) {
57504
- case "NONE":
57505
- return range;
57506
- case "REMOVE":
57507
- return undefined;
57508
- default:
57509
- return change.range;
57510
- }
57511
- }
57512
57598
  class SpreadsheetPivotCorePlugin extends CorePlugin {
57513
57599
  allowDispatch(cmd) {
57514
57600
  switch (cmd.type) {
@@ -57519,27 +57605,6 @@ stores.inject(MyMetaStore, storeInstance);
57519
57605
  }
57520
57606
  return "Success" /* CommandResult.Success */;
57521
57607
  }
57522
- adaptRanges(applyChange) {
57523
- for (const pivotId of this.getters.getPivotIds()) {
57524
- const definition = this.getters.getPivotCoreDefinition(pivotId);
57525
- if (definition.type !== "SPREADSHEET") {
57526
- continue;
57527
- }
57528
- if (definition.dataSet) {
57529
- const { sheetId, zone } = definition.dataSet;
57530
- const range = this.getters.getRangeFromZone(sheetId, zone);
57531
- const adaptedRange = adaptPivotRange(range, applyChange);
57532
- if (adaptedRange === range) {
57533
- return;
57534
- }
57535
- const dataSet = adaptedRange && {
57536
- sheetId: adaptedRange.sheetId,
57537
- zone: adaptedRange.zone,
57538
- };
57539
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
57540
- }
57541
- }
57542
- }
57543
57608
  checkDataSetValidity(definition) {
57544
57609
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
57545
57610
  const { zone, sheetId } = definition.dataSet;
@@ -58897,6 +58962,9 @@ stores.inject(MyMetaStore, storeInstance);
58897
58962
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
58898
58963
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
58899
58964
  }
58965
+ isArrayFormulaSpillBlocked(position) {
58966
+ return this.blockedArrayFormulas.has(position);
58967
+ }
58900
58968
  updateDependencies(position) {
58901
58969
  // removing dependencies is slow because it requires
58902
58970
  // to traverse the entire r-tree.
@@ -58908,13 +58976,8 @@ stores.inject(MyMetaStore, storeInstance);
58908
58976
  addDependencies(position, dependencies) {
58909
58977
  this.formulaDependencies().addDependencies(position, dependencies);
58910
58978
  for (const range of dependencies) {
58911
- const sheetId = range.sheetId;
58912
- const { left, bottom, right, top } = range.zone;
58913
- for (let col = left; col <= right; col++) {
58914
- for (let row = top; row <= bottom; row++) {
58915
- this.computeAndSave({ sheetId, col, row });
58916
- }
58917
- }
58979
+ // ensure that all ranges are computed
58980
+ this.compilationParams.ensureRange(range);
58918
58981
  }
58919
58982
  }
58920
58983
  updateCompilationParameters() {
@@ -59113,6 +59176,10 @@ stores.inject(MyMetaStore, storeInstance);
59113
59176
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
59114
59177
  const nbColumns = formulaReturn.length;
59115
59178
  const nbRows = formulaReturn[0].length;
59179
+ if (nbRows === 0) {
59180
+ // empty matrix
59181
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
59182
+ }
59116
59183
  const resultZone = {
59117
59184
  top: formulaPosition.row,
59118
59185
  bottom: formulaPosition.row + nbRows - 1,
@@ -59385,6 +59452,7 @@ stores.inject(MyMetaStore, storeInstance);
59385
59452
  "getEvaluatedCellsPositions",
59386
59453
  "getSpreadZone",
59387
59454
  "getArrayFormulaSpreadingOn",
59455
+ "isArrayFormulaSpillBlocked",
59388
59456
  "isEmpty",
59389
59457
  ];
59390
59458
  shouldRebuildDependenciesGraph = true;
@@ -59497,6 +59565,9 @@ stores.inject(MyMetaStore, storeInstance);
59497
59565
  getArrayFormulaSpreadingOn(position) {
59498
59566
  return this.evaluator.getArrayFormulaSpreadingOn(position);
59499
59567
  }
59568
+ isArrayFormulaSpillBlocked(position) {
59569
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
59570
+ }
59500
59571
  /**
59501
59572
  * Check if a zone only contains empty cells
59502
59573
  */
@@ -60720,14 +60791,16 @@ stores.inject(MyMetaStore, storeInstance);
60720
60791
  function withPivotPresentationLayer (PivotClass) {
60721
60792
  class PivotPresentationLayer extends PivotClass {
60722
60793
  getters;
60794
+ pivotId;
60723
60795
  cache = {};
60724
60796
  rankAsc = {};
60725
60797
  rankDesc = {};
60726
60798
  runningTotal = {};
60727
60799
  runningTotalInPercent = {};
60728
- constructor(custom, params) {
60800
+ constructor(pivotId, custom, params) {
60729
60801
  super(custom, params);
60730
60802
  this.getters = params.getters;
60803
+ this.pivotId = pivotId;
60731
60804
  }
60732
60805
  markAsDirtyForEvaluation() {
60733
60806
  this.cache = {};
@@ -60777,7 +60850,7 @@ stores.inject(MyMetaStore, storeInstance);
60777
60850
  return handleError(error, measure.aggregator.toUpperCase());
60778
60851
  }
60779
60852
  }
60780
- const formula = this.getters.getMeasureCompiledFormula(measure);
60853
+ const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
60781
60854
  const getSymbolValue = (symbolName) => {
60782
60855
  const { columns, rows } = this.definition;
60783
60856
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
@@ -61495,7 +61568,7 @@ stores.inject(MyMetaStore, storeInstance);
61495
61568
  const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
61496
61569
  if (!(pivotId in this.pivots)) {
61497
61570
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
61498
- this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
61571
+ this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
61499
61572
  }
61500
61573
  else if (recreate) {
61501
61574
  this.pivots[pivotId].onDefinitionChange(definition);
@@ -74769,9 +74842,9 @@ stores.inject(MyMetaStore, storeInstance);
74769
74842
  exports.tokenize = tokenize;
74770
74843
 
74771
74844
 
74772
- __info__.version = "18.0.50";
74773
- __info__.date = "2025-12-02T05:32:00.480Z";
74774
- __info__.hash = "7ed20c4";
74845
+ __info__.version = "18.0.54";
74846
+ __info__.date = "2026-01-14T10:00:02.287Z";
74847
+ __info__.hash = "c0048a0";
74775
74848
 
74776
74849
 
74777
74850
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);