@odoo/o-spreadsheet 18.4.23 → 18.4.24

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.4.23
6
- * @date 2026-01-07T16:21:07.502Z
7
- * @hash a0135e8
5
+ * @version 18.4.24
6
+ * @date 2026-01-14T10:00:55.867Z
7
+ * @hash 0364f56
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -19069,9 +19069,10 @@ stores.inject(MyMetaStore, storeInstance);
19069
19069
  throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
19070
19070
  }
19071
19071
  }
19072
- function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
19072
+ function addPivotDependencies(evalContext, pivotId, forMeasures) {
19073
19073
  //TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
19074
19074
  const dependencies = [];
19075
+ const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
19075
19076
  if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
19076
19077
  const { sheetId, zone } = coreDefinition.dataSet;
19077
19078
  const xc = zoneToXc(zone);
@@ -19088,8 +19089,7 @@ stores.inject(MyMetaStore, storeInstance);
19088
19089
  }
19089
19090
  for (const measure of forMeasures) {
19090
19091
  if (measure.computedBy) {
19091
- const formula = evalContext.getters.getMeasureCompiledFormula(measure);
19092
- dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
19092
+ dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
19093
19093
  }
19094
19094
  }
19095
19095
  const originPosition = evalContext.__originCellPosition;
@@ -19558,7 +19558,7 @@ stores.inject(MyMetaStore, storeInstance);
19558
19558
  assertDomainLength(domainArgs);
19559
19559
  const pivot = this.getters.getPivot(pivotId);
19560
19560
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
19561
- addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
19561
+ addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
19562
19562
  pivot.init({ reload: pivot.needsReevaluation });
19563
19563
  const error = pivot.assertIsValid({ throwOnError: false });
19564
19564
  if (error) {
@@ -19591,8 +19591,7 @@ stores.inject(MyMetaStore, storeInstance);
19591
19591
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
19592
19592
  assertDomainLength(domainArgs);
19593
19593
  const pivot = this.getters.getPivot(_pivotId);
19594
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
19595
- addPivotDependencies(this, coreDefinition, []);
19594
+ addPivotDependencies(this, _pivotId, []);
19596
19595
  pivot.init({ reload: pivot.needsReevaluation });
19597
19596
  const error = pivot.assertIsValid({ throwOnError: false });
19598
19597
  if (error) {
@@ -19650,7 +19649,7 @@ stores.inject(MyMetaStore, storeInstance);
19650
19649
  const pivotId = getPivotId(_pivotFormulaId, this.getters);
19651
19650
  const pivot = this.getters.getPivot(pivotId);
19652
19651
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
19653
- addPivotDependencies(this, coreDefinition, coreDefinition.measures);
19652
+ addPivotDependencies(this, pivotId, coreDefinition.measures);
19654
19653
  pivot.init({ reload: pivot.needsReevaluation });
19655
19654
  const error = pivot.assertIsValid({ throwOnError: false });
19656
19655
  if (error) {
@@ -32904,7 +32903,7 @@ stores.inject(MyMetaStore, storeInstance);
32904
32903
  }
32905
32904
  captureSelection(zone, col, row) {
32906
32905
  this.model.selection.capture(this, {
32907
- cell: { col: col ?? zone.left, row: row ?? zone.right },
32906
+ cell: { col: col ?? zone.left, row: row ?? zone.top },
32908
32907
  zone,
32909
32908
  }, {
32910
32909
  handleEvent: this.handleEvent.bind(this),
@@ -53204,6 +53203,12 @@ stores.inject(MyMetaStore, storeInstance);
53204
53203
  case "ACTIVATE_SHEET":
53205
53204
  this.isSearchDirty = true;
53206
53205
  this.shouldFinalizeUpdateSelection = true;
53206
+ if (this.searchOptions.specificRange) {
53207
+ this.searchOptions.specificRange = {
53208
+ ...this.searchOptions.specificRange,
53209
+ sheetId: this.getters.getActiveSheetId(),
53210
+ };
53211
+ }
53207
53212
  break;
53208
53213
  case "REPLACE_SEARCH":
53209
53214
  for (const match of cmd.matches) {
@@ -53623,9 +53628,20 @@ stores.inject(MyMetaStore, storeInstance);
53623
53628
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
53624
53629
  this.store.updateSearchOptions({ specificRange });
53625
53630
  }
53631
+ get specificRange() {
53632
+ const range = this.store.searchOptions.specificRange;
53633
+ return range ? this.env.model.getters.getRangeString(range, "forceSheetReference") : "";
53634
+ }
53626
53635
  get pendingSearch() {
53627
53636
  return this.updateSearchContent.isDebouncePending();
53628
53637
  }
53638
+ get selectionInputKey() {
53639
+ // Selections input are made to work with objects linked to a sheet id. They store the active sheet id at their creation,
53640
+ // and have specific behaviour linked to it (eg. go back to the initial sheet after confirmation).
53641
+ // We don't want all those behaviors here, so we force the recreation of the component when the active sheet changes.
53642
+ // The only drawback is that the input loses focus when changing sheet.
53643
+ return this.env.model.getters.getActiveSheetId();
53644
+ }
53629
53645
  }
53630
53646
 
53631
53647
  css /* scss */ `
@@ -64252,6 +64268,7 @@ stores.inject(MyMetaStore, storeInstance);
64252
64268
  "getMeasureCompiledFormula",
64253
64269
  "getPivotName",
64254
64270
  "isExistingPivot",
64271
+ "getMeasureFullDependencies",
64255
64272
  ];
64256
64273
  nextFormulaId = 1;
64257
64274
  pivots = {};
@@ -64334,7 +64351,7 @@ stores.inject(MyMetaStore, storeInstance);
64334
64351
  }
64335
64352
  case "UPDATE_PIVOT": {
64336
64353
  this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
64337
- this.compileCalculatedMeasures(cmd.pivot.measures);
64354
+ this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
64338
64355
  break;
64339
64356
  }
64340
64357
  }
@@ -64352,9 +64369,14 @@ stores.inject(MyMetaStore, storeInstance);
64352
64369
  this.history.update("pivots", pivotId, "definition", newDefinition);
64353
64370
  }
64354
64371
  }
64355
- for (const sheetId in this.compiledMeasureFormulas) {
64356
- for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64357
- const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
64372
+ for (const pivotId in this.compiledMeasureFormulas) {
64373
+ for (const measureId in this.compiledMeasureFormulas[pivotId]) {
64374
+ const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
64375
+ if (!measure || !measure.computedBy) {
64376
+ continue;
64377
+ }
64378
+ const sheetId = measure.computedBy.sheetId;
64379
+ const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
64358
64380
  const newDependencies = [];
64359
64381
  for (const range of compiledFormula.dependencies) {
64360
64382
  const change = applyChange(range);
@@ -64366,8 +64388,9 @@ stores.inject(MyMetaStore, storeInstance);
64366
64388
  }
64367
64389
  }
64368
64390
  const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
64369
- if (newFormulaString !== formulaString) {
64370
- this.replaceMeasureFormula(sheetId, formulaString, newFormulaString);
64391
+ const oldFormulaString = measure.computedBy.formula;
64392
+ if (newFormulaString !== oldFormulaString) {
64393
+ this.replaceMeasureFormula(pivotId, measure, newFormulaString);
64371
64394
  }
64372
64395
  }
64373
64396
  }
@@ -64405,30 +64428,59 @@ stores.inject(MyMetaStore, storeInstance);
64405
64428
  isExistingPivot(pivotId) {
64406
64429
  return pivotId in this.pivots;
64407
64430
  }
64408
- getMeasureCompiledFormula(measure) {
64431
+ getMeasureCompiledFormula(pivotId, measure) {
64409
64432
  if (!measure.computedBy) {
64410
64433
  throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
64411
64434
  }
64412
- const sheetId = measure.computedBy.sheetId;
64413
- return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
64435
+ return this.compiledMeasureFormulas[pivotId][measure.id].formula;
64436
+ }
64437
+ getMeasureFullDependencies(pivotId, measure) {
64438
+ if (!measure.computedBy) {
64439
+ throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
64440
+ }
64441
+ return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
64414
64442
  }
64415
64443
  // -------------------------------------------------------------------------
64416
64444
  // Private
64417
64445
  // -------------------------------------------------------------------------
64418
64446
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
64419
64447
  this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
64420
- this.compileCalculatedMeasures(pivot.measures);
64448
+ this.compileCalculatedMeasures(pivotId, pivot.measures);
64421
64449
  this.history.update("formulaIds", formulaId, pivotId);
64422
64450
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
64423
64451
  }
64424
- compileCalculatedMeasures(measures) {
64452
+ compileCalculatedMeasures(pivotId, measures) {
64425
64453
  for (const measure of measures) {
64426
64454
  if (measure.computedBy) {
64427
- const sheetId = measure.computedBy.sheetId;
64428
64455
  const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
64429
- this.history.update("compiledMeasureFormulas", sheetId, measure.computedBy.formula, compiledFormula);
64456
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
64430
64457
  }
64431
64458
  }
64459
+ for (const measure of measures) {
64460
+ if (measure.computedBy) {
64461
+ const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
64462
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
64463
+ }
64464
+ }
64465
+ }
64466
+ computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
64467
+ const rangeDependencies = [];
64468
+ const definition = this.getPivotCoreDefinition(pivotId);
64469
+ const formula = this.getMeasureCompiledFormula(pivotId, measure);
64470
+ exploredMeasures.add(measure.id);
64471
+ for (const token of formula.tokens) {
64472
+ if (token.type !== "SYMBOL") {
64473
+ continue;
64474
+ }
64475
+ const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
64476
+ measure.id !== measureCandidate.id);
64477
+ if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
64478
+ continue;
64479
+ }
64480
+ rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
64481
+ }
64482
+ rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
64483
+ return rangeDependencies;
64432
64484
  }
64433
64485
  insertPivot(position, formulaId, table) {
64434
64486
  this.resizeSheet(position.sheetId, position, table);
@@ -64488,21 +64540,17 @@ stores.inject(MyMetaStore, storeInstance);
64488
64540
  dependencies: rangeDependencies,
64489
64541
  };
64490
64542
  }
64491
- replaceMeasureFormula(sheetId, formulaString, newFormulaString) {
64492
- this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
64493
- this.history.update("compiledMeasureFormulas", sheetId, newFormulaString, this.compileMeasureFormula(sheetId, newFormulaString));
64494
- for (const pivotId in this.pivots) {
64495
- const pivot = this.pivots[pivotId];
64496
- if (!pivot) {
64497
- continue;
64498
- }
64499
- for (const measure of pivot.definition.measures) {
64500
- if (measure.computedBy?.formula === formulaString) {
64501
- const measureIndex = pivot.definition.measures.indexOf(measure);
64502
- this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
64503
- }
64504
- }
64543
+ replaceMeasureFormula(pivotId, measure, newFormulaString) {
64544
+ const pivot = this.pivots[pivotId];
64545
+ if (!pivot) {
64546
+ return;
64505
64547
  }
64548
+ const measureIndex = pivot.definition.measures.indexOf(measure);
64549
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
64550
+ formula: newFormulaString,
64551
+ sheetId: measure.computedBy.sheetId,
64552
+ });
64553
+ this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
64506
64554
  }
64507
64555
  checkSortedColumnInMeasures(definition) {
64508
64556
  const measures = definition.measures.map((measure) => measure.id);
@@ -68030,14 +68078,16 @@ stores.inject(MyMetaStore, storeInstance);
68030
68078
  function withPivotPresentationLayer (PivotClass) {
68031
68079
  class PivotPresentationLayer extends PivotClass {
68032
68080
  getters;
68081
+ pivotId;
68033
68082
  cache = {};
68034
68083
  rankAsc = {};
68035
68084
  rankDesc = {};
68036
68085
  runningTotal = {};
68037
68086
  runningTotalInPercent = {};
68038
- constructor(custom, params) {
68087
+ constructor(pivotId, custom, params) {
68039
68088
  super(custom, params);
68040
68089
  this.getters = params.getters;
68090
+ this.pivotId = pivotId;
68041
68091
  }
68042
68092
  markAsDirtyForEvaluation() {
68043
68093
  this.cache = {};
@@ -68087,7 +68137,7 @@ stores.inject(MyMetaStore, storeInstance);
68087
68137
  return handleError(error, measure.aggregator.toUpperCase());
68088
68138
  }
68089
68139
  }
68090
- const formula = this.getters.getMeasureCompiledFormula(measure);
68140
+ const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
68091
68141
  const getSymbolValue = (symbolName) => {
68092
68142
  const { columns, rows } = this.definition;
68093
68143
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
@@ -68827,7 +68877,7 @@ stores.inject(MyMetaStore, storeInstance);
68827
68877
  const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
68828
68878
  if (!(pivotId in this.pivots)) {
68829
68879
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
68830
- this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
68880
+ this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
68831
68881
  }
68832
68882
  else if (recreate) {
68833
68883
  this.pivots[pivotId].onDefinitionChange(definition);
@@ -85013,9 +85063,9 @@ stores.inject(MyMetaStore, storeInstance);
85013
85063
  exports.tokenize = tokenize;
85014
85064
 
85015
85065
 
85016
- __info__.version = "18.4.23";
85017
- __info__.date = "2026-01-07T16:21:07.502Z";
85018
- __info__.hash = "a0135e8";
85066
+ __info__.version = "18.4.24";
85067
+ __info__.date = "2026-01-14T10:00:55.867Z";
85068
+ __info__.hash = "0364f56";
85019
85069
 
85020
85070
 
85021
85071
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);