@odoo/o-spreadsheet 19.0.16 → 19.0.17

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 19.0.16
6
- * @date 2026-01-07T16:21:15.857Z
7
- * @hash 9f3f13a
5
+ * @version 19.0.17
6
+ * @date 2026-01-14T10:01:24.044Z
7
+ * @hash 2165bad
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -20099,9 +20099,10 @@ stores.inject(MyMetaStore, storeInstance);
20099
20099
  throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
20100
20100
  }
20101
20101
  }
20102
- function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
20102
+ function addPivotDependencies(evalContext, pivotId, forMeasures) {
20103
20103
  //TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
20104
20104
  const dependencies = [];
20105
+ const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
20105
20106
  if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
20106
20107
  const { sheetId, zone } = coreDefinition.dataSet;
20107
20108
  const xc = zoneToXc(zone);
@@ -20118,8 +20119,7 @@ stores.inject(MyMetaStore, storeInstance);
20118
20119
  }
20119
20120
  for (const measure of forMeasures) {
20120
20121
  if (measure.computedBy) {
20121
- const formula = evalContext.getters.getMeasureCompiledFormula(measure);
20122
- dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
20122
+ dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
20123
20123
  }
20124
20124
  }
20125
20125
  const originPosition = evalContext.__originCellPosition;
@@ -20616,7 +20616,7 @@ stores.inject(MyMetaStore, storeInstance);
20616
20616
  assertDomainLength(domainArgs);
20617
20617
  const pivot = this.getters.getPivot(pivotId);
20618
20618
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
20619
- addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
20619
+ addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
20620
20620
  pivot.init({ reload: pivot.needsReevaluation });
20621
20621
  const error = pivot.assertIsValid({ throwOnError: false });
20622
20622
  if (error) {
@@ -20649,8 +20649,7 @@ stores.inject(MyMetaStore, storeInstance);
20649
20649
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
20650
20650
  assertDomainLength(domainArgs);
20651
20651
  const pivot = this.getters.getPivot(_pivotId);
20652
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
20653
- addPivotDependencies(this, coreDefinition, []);
20652
+ addPivotDependencies(this, _pivotId, []);
20654
20653
  pivot.init({ reload: pivot.needsReevaluation });
20655
20654
  const error = pivot.assertIsValid({ throwOnError: false });
20656
20655
  if (error) {
@@ -20708,7 +20707,7 @@ stores.inject(MyMetaStore, storeInstance);
20708
20707
  const pivotId = getPivotId(_pivotFormulaId, this.getters);
20709
20708
  const pivot = this.getters.getPivot(pivotId);
20710
20709
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
20711
- addPivotDependencies(this, coreDefinition, coreDefinition.measures);
20710
+ addPivotDependencies(this, pivotId, coreDefinition.measures);
20712
20711
  pivot.init({ reload: pivot.needsReevaluation });
20713
20712
  const error = pivot.assertIsValid({ throwOnError: false });
20714
20713
  if (error) {
@@ -35483,7 +35482,7 @@ stores.inject(MyMetaStore, storeInstance);
35483
35482
  }
35484
35483
  captureSelection(zone, col, row) {
35485
35484
  this.model.selection.capture(this, {
35486
- cell: { col: col ?? zone.left, row: row ?? zone.right },
35485
+ cell: { col: col ?? zone.left, row: row ?? zone.top },
35487
35486
  zone,
35488
35487
  }, {
35489
35488
  handleEvent: this.handleEvent.bind(this),
@@ -57876,6 +57875,12 @@ stores.inject(MyMetaStore, storeInstance);
57876
57875
  case "ACTIVATE_SHEET":
57877
57876
  this.isSearchDirty = true;
57878
57877
  this.shouldFinalizeUpdateSelection = true;
57878
+ if (this.searchOptions.specificRange) {
57879
+ this.searchOptions.specificRange = {
57880
+ ...this.searchOptions.specificRange,
57881
+ sheetId: this.getters.getActiveSheetId(),
57882
+ };
57883
+ }
57879
57884
  break;
57880
57885
  case "REPLACE_SEARCH":
57881
57886
  for (const match of cmd.matches) {
@@ -58295,9 +58300,20 @@ stores.inject(MyMetaStore, storeInstance);
58295
58300
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
58296
58301
  this.store.updateSearchOptions({ specificRange });
58297
58302
  }
58303
+ get specificRange() {
58304
+ const range = this.store.searchOptions.specificRange;
58305
+ return range ? this.env.model.getters.getRangeString(range, "forceSheetReference") : "";
58306
+ }
58298
58307
  get pendingSearch() {
58299
58308
  return this.updateSearchContent.isDebouncePending();
58300
58309
  }
58310
+ get selectionInputKey() {
58311
+ // Selections input are made to work with objects linked to a sheet id. They store the active sheet id at their creation,
58312
+ // and have specific behaviour linked to it (eg. go back to the initial sheet after confirmation).
58313
+ // We don't want all those behaviors here, so we force the recreation of the component when the active sheet changes.
58314
+ // The only drawback is that the input loses focus when changing sheet.
58315
+ return this.env.model.getters.getActiveSheetId();
58316
+ }
58301
58317
  }
58302
58318
 
58303
58319
  css /* scss */ `
@@ -67607,6 +67623,7 @@ stores.inject(MyMetaStore, storeInstance);
67607
67623
  "getMeasureCompiledFormula",
67608
67624
  "getPivotName",
67609
67625
  "isExistingPivot",
67626
+ "getMeasureFullDependencies",
67610
67627
  ];
67611
67628
  nextFormulaId = 1;
67612
67629
  pivots = {};
@@ -67689,7 +67706,7 @@ stores.inject(MyMetaStore, storeInstance);
67689
67706
  }
67690
67707
  case "UPDATE_PIVOT": {
67691
67708
  this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
67692
- this.compileCalculatedMeasures(cmd.pivot.measures);
67709
+ this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
67693
67710
  break;
67694
67711
  }
67695
67712
  }
@@ -67707,9 +67724,14 @@ stores.inject(MyMetaStore, storeInstance);
67707
67724
  this.history.update("pivots", pivotId, "definition", newDefinition);
67708
67725
  }
67709
67726
  }
67710
- for (const sheetId in this.compiledMeasureFormulas) {
67711
- for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
67712
- const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
67727
+ for (const pivotId in this.compiledMeasureFormulas) {
67728
+ for (const measureId in this.compiledMeasureFormulas[pivotId]) {
67729
+ const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
67730
+ if (!measure || !measure.computedBy) {
67731
+ continue;
67732
+ }
67733
+ const sheetId = measure.computedBy.sheetId;
67734
+ const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
67713
67735
  const newDependencies = [];
67714
67736
  for (const range of compiledFormula.dependencies) {
67715
67737
  const change = applyChange(range);
@@ -67721,8 +67743,9 @@ stores.inject(MyMetaStore, storeInstance);
67721
67743
  }
67722
67744
  }
67723
67745
  const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
67724
- if (newFormulaString !== formulaString) {
67725
- this.replaceMeasureFormula(sheetId, formulaString, newFormulaString);
67746
+ const oldFormulaString = measure.computedBy.formula;
67747
+ if (newFormulaString !== oldFormulaString) {
67748
+ this.replaceMeasureFormula(pivotId, measure, newFormulaString);
67726
67749
  }
67727
67750
  }
67728
67751
  }
@@ -67760,30 +67783,59 @@ stores.inject(MyMetaStore, storeInstance);
67760
67783
  isExistingPivot(pivotId) {
67761
67784
  return pivotId in this.pivots;
67762
67785
  }
67763
- getMeasureCompiledFormula(measure) {
67786
+ getMeasureCompiledFormula(pivotId, measure) {
67764
67787
  if (!measure.computedBy) {
67765
67788
  throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
67766
67789
  }
67767
- const sheetId = measure.computedBy.sheetId;
67768
- return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
67790
+ return this.compiledMeasureFormulas[pivotId][measure.id].formula;
67791
+ }
67792
+ getMeasureFullDependencies(pivotId, measure) {
67793
+ if (!measure.computedBy) {
67794
+ throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
67795
+ }
67796
+ return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
67769
67797
  }
67770
67798
  // -------------------------------------------------------------------------
67771
67799
  // Private
67772
67800
  // -------------------------------------------------------------------------
67773
67801
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
67774
67802
  this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
67775
- this.compileCalculatedMeasures(pivot.measures);
67803
+ this.compileCalculatedMeasures(pivotId, pivot.measures);
67776
67804
  this.history.update("formulaIds", formulaId, pivotId);
67777
67805
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
67778
67806
  }
67779
- compileCalculatedMeasures(measures) {
67807
+ compileCalculatedMeasures(pivotId, measures) {
67780
67808
  for (const measure of measures) {
67781
67809
  if (measure.computedBy) {
67782
- const sheetId = measure.computedBy.sheetId;
67783
67810
  const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
67784
- this.history.update("compiledMeasureFormulas", sheetId, measure.computedBy.formula, compiledFormula);
67811
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
67785
67812
  }
67786
67813
  }
67814
+ for (const measure of measures) {
67815
+ if (measure.computedBy) {
67816
+ const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
67817
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
67818
+ }
67819
+ }
67820
+ }
67821
+ computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
67822
+ const rangeDependencies = [];
67823
+ const definition = this.getPivotCoreDefinition(pivotId);
67824
+ const formula = this.getMeasureCompiledFormula(pivotId, measure);
67825
+ exploredMeasures.add(measure.id);
67826
+ for (const token of formula.tokens) {
67827
+ if (token.type !== "SYMBOL") {
67828
+ continue;
67829
+ }
67830
+ const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
67831
+ measure.id !== measureCandidate.id);
67832
+ if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
67833
+ continue;
67834
+ }
67835
+ rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
67836
+ }
67837
+ rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
67838
+ return rangeDependencies;
67787
67839
  }
67788
67840
  insertPivot(position, formulaId, table) {
67789
67841
  this.resizeSheet(position.sheetId, position, table);
@@ -67843,21 +67895,17 @@ stores.inject(MyMetaStore, storeInstance);
67843
67895
  dependencies: rangeDependencies,
67844
67896
  };
67845
67897
  }
67846
- replaceMeasureFormula(sheetId, formulaString, newFormulaString) {
67847
- this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
67848
- this.history.update("compiledMeasureFormulas", sheetId, newFormulaString, this.compileMeasureFormula(sheetId, newFormulaString));
67849
- for (const pivotId in this.pivots) {
67850
- const pivot = this.pivots[pivotId];
67851
- if (!pivot) {
67852
- continue;
67853
- }
67854
- for (const measure of pivot.definition.measures) {
67855
- if (measure.computedBy?.formula === formulaString) {
67856
- const measureIndex = pivot.definition.measures.indexOf(measure);
67857
- this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
67858
- }
67859
- }
67898
+ replaceMeasureFormula(pivotId, measure, newFormulaString) {
67899
+ const pivot = this.pivots[pivotId];
67900
+ if (!pivot) {
67901
+ return;
67860
67902
  }
67903
+ const measureIndex = pivot.definition.measures.indexOf(measure);
67904
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
67905
+ formula: newFormulaString,
67906
+ sheetId: measure.computedBy.sheetId,
67907
+ });
67908
+ this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
67861
67909
  }
67862
67910
  checkSortedColumnInMeasures(definition) {
67863
67911
  const measures = definition.measures.map((measure) => measure.id);
@@ -71707,14 +71755,16 @@ stores.inject(MyMetaStore, storeInstance);
71707
71755
  function withPivotPresentationLayer (PivotClass) {
71708
71756
  class PivotPresentationLayer extends PivotClass {
71709
71757
  getters;
71758
+ pivotId;
71710
71759
  cache = {};
71711
71760
  rankAsc = {};
71712
71761
  rankDesc = {};
71713
71762
  runningTotal = {};
71714
71763
  runningTotalInPercent = {};
71715
- constructor(custom, params) {
71764
+ constructor(pivotId, custom, params) {
71716
71765
  super(custom, params);
71717
71766
  this.getters = params.getters;
71767
+ this.pivotId = pivotId;
71718
71768
  }
71719
71769
  markAsDirtyForEvaluation() {
71720
71770
  this.cache = {};
@@ -71764,7 +71814,7 @@ stores.inject(MyMetaStore, storeInstance);
71764
71814
  return handleError(error, measure.aggregator.toUpperCase());
71765
71815
  }
71766
71816
  }
71767
- const formula = this.getters.getMeasureCompiledFormula(measure);
71817
+ const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
71768
71818
  const getSymbolValue = (symbolName) => {
71769
71819
  const { columns, rows } = this.definition;
71770
71820
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
@@ -72519,7 +72569,7 @@ stores.inject(MyMetaStore, storeInstance);
72519
72569
  const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
72520
72570
  if (!(pivotId in this.pivots)) {
72521
72571
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
72522
- this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
72572
+ this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
72523
72573
  }
72524
72574
  else if (recreate) {
72525
72575
  this.pivots[pivotId].onDefinitionChange(definition);
@@ -89124,9 +89174,9 @@ stores.inject(MyMetaStore, storeInstance);
89124
89174
  exports.tokenize = tokenize;
89125
89175
 
89126
89176
 
89127
- __info__.version = "19.0.16";
89128
- __info__.date = "2026-01-07T16:21:15.857Z";
89129
- __info__.hash = "9f3f13a";
89177
+ __info__.version = "19.0.17";
89178
+ __info__.date = "2026-01-14T10:01:24.044Z";
89179
+ __info__.hash = "2165bad";
89130
89180
 
89131
89181
 
89132
89182
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);