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