@odoo/o-spreadsheet 18.2.39 → 18.2.40
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.
- package/dist/o-spreadsheet.cjs.js +93 -44
- package/dist/o-spreadsheet.d.ts +10 -4
- package/dist/o-spreadsheet.esm.js +93 -44
- package/dist/o-spreadsheet.iife.js +93 -44
- package/dist/o-spreadsheet.iife.min.js +5 -5
- package/dist/o_spreadsheet.css +3 -3
- package/dist/o_spreadsheet.xml +5 -4
- package/package.json +1 -1
|
@@ -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.2.
|
|
6
|
-
* @date
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.40
|
|
6
|
+
* @date 2026-01-14T09:59:34.210Z
|
|
7
|
+
* @hash 755a787
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -19119,9 +19119,10 @@ function assertDomainLength(domain) {
|
|
|
19119
19119
|
throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
|
|
19120
19120
|
}
|
|
19121
19121
|
}
|
|
19122
|
-
function addPivotDependencies(evalContext,
|
|
19122
|
+
function addPivotDependencies(evalContext, pivotId, forMeasures) {
|
|
19123
19123
|
//TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
|
|
19124
19124
|
const dependencies = [];
|
|
19125
|
+
const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
|
|
19125
19126
|
if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
|
|
19126
19127
|
const { sheetId, zone } = coreDefinition.dataSet;
|
|
19127
19128
|
const xc = zoneToXc(zone);
|
|
@@ -19138,8 +19139,7 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
|
|
|
19138
19139
|
}
|
|
19139
19140
|
for (const measure of forMeasures) {
|
|
19140
19141
|
if (measure.computedBy) {
|
|
19141
|
-
|
|
19142
|
-
dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
19142
|
+
dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
|
|
19143
19143
|
}
|
|
19144
19144
|
}
|
|
19145
19145
|
const originPosition = evalContext.__originCellPosition;
|
|
@@ -19580,7 +19580,7 @@ const PIVOT_VALUE = {
|
|
|
19580
19580
|
assertDomainLength(domainArgs);
|
|
19581
19581
|
const pivot = this.getters.getPivot(pivotId);
|
|
19582
19582
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
19583
|
-
addPivotDependencies(this,
|
|
19583
|
+
addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
|
|
19584
19584
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
19585
19585
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19586
19586
|
if (error) {
|
|
@@ -19613,8 +19613,7 @@ const PIVOT_HEADER = {
|
|
|
19613
19613
|
const _pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19614
19614
|
assertDomainLength(domainArgs);
|
|
19615
19615
|
const pivot = this.getters.getPivot(_pivotId);
|
|
19616
|
-
|
|
19617
|
-
addPivotDependencies(this, coreDefinition, []);
|
|
19616
|
+
addPivotDependencies(this, _pivotId, []);
|
|
19618
19617
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
19619
19618
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19620
19619
|
if (error) {
|
|
@@ -19668,7 +19667,7 @@ const PIVOT = {
|
|
|
19668
19667
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19669
19668
|
const pivot = this.getters.getPivot(pivotId);
|
|
19670
19669
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
19671
|
-
addPivotDependencies(this,
|
|
19670
|
+
addPivotDependencies(this, pivotId, coreDefinition.measures);
|
|
19672
19671
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
19673
19672
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19674
19673
|
if (error) {
|
|
@@ -21325,7 +21324,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
21325
21324
|
}
|
|
21326
21325
|
captureSelection(zone, col, row) {
|
|
21327
21326
|
this.model.selection.capture(this, {
|
|
21328
|
-
cell: { col: col ?? zone.left, row: row ?? zone.
|
|
21327
|
+
cell: { col: col ?? zone.left, row: row ?? zone.top },
|
|
21329
21328
|
zone,
|
|
21330
21329
|
}, {
|
|
21331
21330
|
handleEvent: this.handleEvent.bind(this),
|
|
@@ -44866,6 +44865,11 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
44866
44865
|
case "ACTIVATE_SHEET":
|
|
44867
44866
|
this.isSearchDirty = true;
|
|
44868
44867
|
this.shouldFinalizeUpdateSelection = true;
|
|
44868
|
+
if (this.searchOptions.specificRange) {
|
|
44869
|
+
this.searchOptions.specificRange = this.searchOptions.specificRange.clone({
|
|
44870
|
+
sheetId: this.getters.getActiveSheetId(),
|
|
44871
|
+
});
|
|
44872
|
+
}
|
|
44869
44873
|
break;
|
|
44870
44874
|
case "REPLACE_SEARCH":
|
|
44871
44875
|
for (const match of cmd.matches) {
|
|
@@ -45287,9 +45291,20 @@ class FindAndReplacePanel extends owl.Component {
|
|
|
45287
45291
|
const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
|
|
45288
45292
|
this.store.updateSearchOptions({ specificRange });
|
|
45289
45293
|
}
|
|
45294
|
+
get specificRange() {
|
|
45295
|
+
const range = this.store.searchOptions.specificRange;
|
|
45296
|
+
return range ? this.env.model.getters.getRangeString(range, "forceSheetReference") : "";
|
|
45297
|
+
}
|
|
45290
45298
|
get pendingSearch() {
|
|
45291
45299
|
return this.updateSearchContent.isDebouncePending();
|
|
45292
45300
|
}
|
|
45301
|
+
get selectionInputKey() {
|
|
45302
|
+
// Selections input are made to work with objects linked to a sheet id. They store the active sheet id at their creation,
|
|
45303
|
+
// and have specific behaviour linked to it (eg. go back to the initial sheet after confirmation).
|
|
45304
|
+
// We don't want all those behaviors here, so we force the recreation of the component when the active sheet changes.
|
|
45305
|
+
// The only drawback is that the input loses focus when changing sheet.
|
|
45306
|
+
return this.env.model.getters.getActiveSheetId();
|
|
45307
|
+
}
|
|
45293
45308
|
}
|
|
45294
45309
|
|
|
45295
45310
|
css /* scss */ `
|
|
@@ -59820,6 +59835,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59820
59835
|
"getMeasureCompiledFormula",
|
|
59821
59836
|
"getPivotName",
|
|
59822
59837
|
"isExistingPivot",
|
|
59838
|
+
"getMeasureFullDependencies",
|
|
59823
59839
|
];
|
|
59824
59840
|
nextFormulaId = 1;
|
|
59825
59841
|
pivots = {};
|
|
@@ -59902,7 +59918,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59902
59918
|
}
|
|
59903
59919
|
case "UPDATE_PIVOT": {
|
|
59904
59920
|
this.history.update("pivots", cmd.pivotId, "definition", this.repairSortedColumn(deepCopy(cmd.pivot)));
|
|
59905
|
-
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
59921
|
+
this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
|
|
59906
59922
|
break;
|
|
59907
59923
|
}
|
|
59908
59924
|
}
|
|
@@ -59920,9 +59936,14 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59920
59936
|
this.history.update("pivots", pivotId, "definition", newDefinition);
|
|
59921
59937
|
}
|
|
59922
59938
|
}
|
|
59923
|
-
for (const
|
|
59924
|
-
for (const
|
|
59925
|
-
const
|
|
59939
|
+
for (const pivotId in this.compiledMeasureFormulas) {
|
|
59940
|
+
for (const measureId in this.compiledMeasureFormulas[pivotId]) {
|
|
59941
|
+
const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
|
|
59942
|
+
if (!measure || !measure.computedBy) {
|
|
59943
|
+
continue;
|
|
59944
|
+
}
|
|
59945
|
+
const sheetId = measure.computedBy.sheetId;
|
|
59946
|
+
const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
|
|
59926
59947
|
const newDependencies = [];
|
|
59927
59948
|
for (const range of compiledFormula.dependencies) {
|
|
59928
59949
|
const change = applyChange(range);
|
|
@@ -59934,8 +59955,9 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59934
59955
|
}
|
|
59935
59956
|
}
|
|
59936
59957
|
const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
|
|
59937
|
-
|
|
59938
|
-
|
|
59958
|
+
const oldFormulaString = measure.computedBy.formula;
|
|
59959
|
+
if (newFormulaString !== oldFormulaString) {
|
|
59960
|
+
this.replaceMeasureFormula(pivotId, measure, newFormulaString);
|
|
59939
59961
|
}
|
|
59940
59962
|
}
|
|
59941
59963
|
}
|
|
@@ -59973,12 +59995,17 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59973
59995
|
isExistingPivot(pivotId) {
|
|
59974
59996
|
return pivotId in this.pivots;
|
|
59975
59997
|
}
|
|
59976
|
-
getMeasureCompiledFormula(measure) {
|
|
59998
|
+
getMeasureCompiledFormula(pivotId, measure) {
|
|
59977
59999
|
if (!measure.computedBy) {
|
|
59978
60000
|
throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
|
|
59979
60001
|
}
|
|
59980
|
-
|
|
59981
|
-
|
|
60002
|
+
return this.compiledMeasureFormulas[pivotId][measure.id].formula;
|
|
60003
|
+
}
|
|
60004
|
+
getMeasureFullDependencies(pivotId, measure) {
|
|
60005
|
+
if (!measure.computedBy) {
|
|
60006
|
+
throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
|
|
60007
|
+
}
|
|
60008
|
+
return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
|
|
59982
60009
|
}
|
|
59983
60010
|
// -------------------------------------------------------------------------
|
|
59984
60011
|
// Private
|
|
@@ -59988,18 +60015,42 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59988
60015
|
definition: this.repairSortedColumn(deepCopy(pivot)),
|
|
59989
60016
|
formulaId,
|
|
59990
60017
|
});
|
|
59991
|
-
this.compileCalculatedMeasures(pivot.measures);
|
|
60018
|
+
this.compileCalculatedMeasures(pivotId, pivot.measures);
|
|
59992
60019
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
59993
60020
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
59994
60021
|
}
|
|
59995
|
-
compileCalculatedMeasures(measures) {
|
|
60022
|
+
compileCalculatedMeasures(pivotId, measures) {
|
|
59996
60023
|
for (const measure of measures) {
|
|
59997
60024
|
if (measure.computedBy) {
|
|
59998
|
-
const sheetId = measure.computedBy.sheetId;
|
|
59999
60025
|
const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
|
|
60000
|
-
this.history.update("compiledMeasureFormulas",
|
|
60026
|
+
this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
|
|
60001
60027
|
}
|
|
60002
60028
|
}
|
|
60029
|
+
for (const measure of measures) {
|
|
60030
|
+
if (measure.computedBy) {
|
|
60031
|
+
const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
|
|
60032
|
+
this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
|
|
60033
|
+
}
|
|
60034
|
+
}
|
|
60035
|
+
}
|
|
60036
|
+
computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
|
|
60037
|
+
const rangeDependencies = [];
|
|
60038
|
+
const definition = this.getPivotCoreDefinition(pivotId);
|
|
60039
|
+
const formula = this.getMeasureCompiledFormula(pivotId, measure);
|
|
60040
|
+
exploredMeasures.add(measure.id);
|
|
60041
|
+
for (const token of formula.tokens) {
|
|
60042
|
+
if (token.type !== "SYMBOL") {
|
|
60043
|
+
continue;
|
|
60044
|
+
}
|
|
60045
|
+
const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
|
|
60046
|
+
measure.id !== measureCandidate.id);
|
|
60047
|
+
if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
|
|
60048
|
+
continue;
|
|
60049
|
+
}
|
|
60050
|
+
rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
|
|
60051
|
+
}
|
|
60052
|
+
rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
60053
|
+
return rangeDependencies;
|
|
60003
60054
|
}
|
|
60004
60055
|
insertPivot(position, formulaId, table) {
|
|
60005
60056
|
this.resizeSheet(position.sheetId, position, table);
|
|
@@ -60057,21 +60108,17 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
60057
60108
|
dependencies: rangeDependencies,
|
|
60058
60109
|
};
|
|
60059
60110
|
}
|
|
60060
|
-
replaceMeasureFormula(
|
|
60061
|
-
|
|
60062
|
-
|
|
60063
|
-
|
|
60064
|
-
const pivot = this.pivots[pivotId];
|
|
60065
|
-
if (!pivot) {
|
|
60066
|
-
continue;
|
|
60067
|
-
}
|
|
60068
|
-
for (const measure of pivot.definition.measures) {
|
|
60069
|
-
if (measure.computedBy?.formula === formulaString) {
|
|
60070
|
-
const measureIndex = pivot.definition.measures.indexOf(measure);
|
|
60071
|
-
this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
|
|
60072
|
-
}
|
|
60073
|
-
}
|
|
60111
|
+
replaceMeasureFormula(pivotId, measure, newFormulaString) {
|
|
60112
|
+
const pivot = this.pivots[pivotId];
|
|
60113
|
+
if (!pivot) {
|
|
60114
|
+
return;
|
|
60074
60115
|
}
|
|
60116
|
+
const measureIndex = pivot.definition.measures.indexOf(measure);
|
|
60117
|
+
this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
|
|
60118
|
+
formula: newFormulaString,
|
|
60119
|
+
sheetId: measure.computedBy.sheetId,
|
|
60120
|
+
});
|
|
60121
|
+
this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
|
|
60075
60122
|
}
|
|
60076
60123
|
checkDuplicatedMeasureIds(definition) {
|
|
60077
60124
|
const uniqueIds = new Set(definition.measures.map((m) => m.id));
|
|
@@ -63336,14 +63383,16 @@ const PERCENT_FORMAT = "0.00%";
|
|
|
63336
63383
|
function withPivotPresentationLayer (PivotClass) {
|
|
63337
63384
|
class PivotPresentationLayer extends PivotClass {
|
|
63338
63385
|
getters;
|
|
63386
|
+
pivotId;
|
|
63339
63387
|
cache = {};
|
|
63340
63388
|
rankAsc = {};
|
|
63341
63389
|
rankDesc = {};
|
|
63342
63390
|
runningTotal = {};
|
|
63343
63391
|
runningTotalInPercent = {};
|
|
63344
|
-
constructor(custom, params) {
|
|
63392
|
+
constructor(pivotId, custom, params) {
|
|
63345
63393
|
super(custom, params);
|
|
63346
63394
|
this.getters = params.getters;
|
|
63395
|
+
this.pivotId = pivotId;
|
|
63347
63396
|
}
|
|
63348
63397
|
markAsDirtyForEvaluation() {
|
|
63349
63398
|
this.cache = {};
|
|
@@ -63393,7 +63442,7 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
63393
63442
|
return handleError(error, measure.aggregator.toUpperCase());
|
|
63394
63443
|
}
|
|
63395
63444
|
}
|
|
63396
|
-
const formula = this.getters.getMeasureCompiledFormula(measure);
|
|
63445
|
+
const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
|
|
63397
63446
|
const getSymbolValue = (symbolName) => {
|
|
63398
63447
|
const { columns, rows } = this.definition;
|
|
63399
63448
|
if (columns.find((col) => col.nameWithGranularity === symbolName)) {
|
|
@@ -64121,7 +64170,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
64121
64170
|
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
64122
64171
|
if (!(pivotId in this.pivots)) {
|
|
64123
64172
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
64124
|
-
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
64173
|
+
this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
|
|
64125
64174
|
}
|
|
64126
64175
|
else if (recreate) {
|
|
64127
64176
|
this.pivots[pivotId].onDefinitionChange(definition);
|
|
@@ -77421,6 +77470,6 @@ exports.tokenColors = tokenColors;
|
|
|
77421
77470
|
exports.tokenize = tokenize;
|
|
77422
77471
|
|
|
77423
77472
|
|
|
77424
|
-
__info__.version = "18.2.
|
|
77425
|
-
__info__.date = "
|
|
77426
|
-
__info__.hash = "
|
|
77473
|
+
__info__.version = "18.2.40";
|
|
77474
|
+
__info__.date = "2026-01-14T09:59:34.210Z";
|
|
77475
|
+
__info__.hash = "755a787";
|
package/dist/o-spreadsheet.d.ts
CHANGED
|
@@ -4795,14 +4795,18 @@ interface Pivot$1 {
|
|
|
4795
4795
|
definition: PivotCoreDefinition;
|
|
4796
4796
|
formulaId: string;
|
|
4797
4797
|
}
|
|
4798
|
+
interface MeasureState {
|
|
4799
|
+
formula: RangeCompiledFormula;
|
|
4800
|
+
dependencies: Range[];
|
|
4801
|
+
}
|
|
4798
4802
|
interface CoreState {
|
|
4799
4803
|
nextFormulaId: number;
|
|
4800
4804
|
pivots: Record<UID, Pivot$1 | undefined>;
|
|
4801
4805
|
formulaIds: Record<UID, string | undefined>;
|
|
4802
|
-
compiledMeasureFormulas: Record<UID, Record<string,
|
|
4806
|
+
compiledMeasureFormulas: Record<UID, Record<string, MeasureState | undefined>>;
|
|
4803
4807
|
}
|
|
4804
4808
|
declare class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState {
|
|
4805
|
-
static getters: readonly ["getPivotCoreDefinition", "getPivotDisplayName", "getPivotId", "getPivotFormulaId", "getPivotIds", "getMeasureCompiledFormula", "getPivotName", "isExistingPivot"];
|
|
4809
|
+
static getters: readonly ["getPivotCoreDefinition", "getPivotDisplayName", "getPivotId", "getPivotFormulaId", "getPivotIds", "getMeasureCompiledFormula", "getPivotName", "isExistingPivot", "getMeasureFullDependencies"];
|
|
4806
4810
|
readonly nextFormulaId: number;
|
|
4807
4811
|
readonly pivots: {
|
|
4808
4812
|
[pivotId: UID]: Pivot$1 | undefined;
|
|
@@ -4810,7 +4814,7 @@ declare class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
|
|
|
4810
4814
|
readonly formulaIds: {
|
|
4811
4815
|
[formulaId: UID]: UID | undefined;
|
|
4812
4816
|
};
|
|
4813
|
-
readonly compiledMeasureFormulas: Record<UID, Record<string,
|
|
4817
|
+
readonly compiledMeasureFormulas: Record<UID, Record<string, MeasureState>>;
|
|
4814
4818
|
allowDispatch(cmd: CoreCommand): CommandResult.Success | CommandResult.NoChanges | CommandResult.PivotIdNotFound | CommandResult.EmptyName | CommandResult.InvalidDefinition;
|
|
4815
4819
|
handle(cmd: CoreCommand): void;
|
|
4816
4820
|
adaptRanges(applyChange: ApplyRangeChange): void;
|
|
@@ -4829,9 +4833,11 @@ declare class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
|
|
|
4829
4833
|
getPivotFormulaId(pivotId: UID): string;
|
|
4830
4834
|
getPivotIds(): UID[];
|
|
4831
4835
|
isExistingPivot(pivotId: UID): boolean;
|
|
4832
|
-
getMeasureCompiledFormula(measure: PivotCoreMeasure): RangeCompiledFormula;
|
|
4836
|
+
getMeasureCompiledFormula(pivotId: UID, measure: PivotCoreMeasure): RangeCompiledFormula;
|
|
4837
|
+
getMeasureFullDependencies(pivotId: UID, measure: PivotCoreMeasure): Range[];
|
|
4833
4838
|
private addPivot;
|
|
4834
4839
|
private compileCalculatedMeasures;
|
|
4840
|
+
private computeMeasureFullDependencies;
|
|
4835
4841
|
private insertPivot;
|
|
4836
4842
|
private resizeSheet;
|
|
4837
4843
|
private getPivotCore;
|
|
@@ -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.2.
|
|
6
|
-
* @date
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.40
|
|
6
|
+
* @date 2026-01-14T09:59:34.210Z
|
|
7
|
+
* @hash 755a787
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -19117,9 +19117,10 @@ function assertDomainLength(domain) {
|
|
|
19117
19117
|
throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
|
|
19118
19118
|
}
|
|
19119
19119
|
}
|
|
19120
|
-
function addPivotDependencies(evalContext,
|
|
19120
|
+
function addPivotDependencies(evalContext, pivotId, forMeasures) {
|
|
19121
19121
|
//TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
|
|
19122
19122
|
const dependencies = [];
|
|
19123
|
+
const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
|
|
19123
19124
|
if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
|
|
19124
19125
|
const { sheetId, zone } = coreDefinition.dataSet;
|
|
19125
19126
|
const xc = zoneToXc(zone);
|
|
@@ -19136,8 +19137,7 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
|
|
|
19136
19137
|
}
|
|
19137
19138
|
for (const measure of forMeasures) {
|
|
19138
19139
|
if (measure.computedBy) {
|
|
19139
|
-
|
|
19140
|
-
dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
19140
|
+
dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
|
|
19141
19141
|
}
|
|
19142
19142
|
}
|
|
19143
19143
|
const originPosition = evalContext.__originCellPosition;
|
|
@@ -19578,7 +19578,7 @@ const PIVOT_VALUE = {
|
|
|
19578
19578
|
assertDomainLength(domainArgs);
|
|
19579
19579
|
const pivot = this.getters.getPivot(pivotId);
|
|
19580
19580
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
19581
|
-
addPivotDependencies(this,
|
|
19581
|
+
addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
|
|
19582
19582
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
19583
19583
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19584
19584
|
if (error) {
|
|
@@ -19611,8 +19611,7 @@ const PIVOT_HEADER = {
|
|
|
19611
19611
|
const _pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19612
19612
|
assertDomainLength(domainArgs);
|
|
19613
19613
|
const pivot = this.getters.getPivot(_pivotId);
|
|
19614
|
-
|
|
19615
|
-
addPivotDependencies(this, coreDefinition, []);
|
|
19614
|
+
addPivotDependencies(this, _pivotId, []);
|
|
19616
19615
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
19617
19616
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19618
19617
|
if (error) {
|
|
@@ -19666,7 +19665,7 @@ const PIVOT = {
|
|
|
19666
19665
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19667
19666
|
const pivot = this.getters.getPivot(pivotId);
|
|
19668
19667
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
19669
|
-
addPivotDependencies(this,
|
|
19668
|
+
addPivotDependencies(this, pivotId, coreDefinition.measures);
|
|
19670
19669
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
19671
19670
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
19672
19671
|
if (error) {
|
|
@@ -21323,7 +21322,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
21323
21322
|
}
|
|
21324
21323
|
captureSelection(zone, col, row) {
|
|
21325
21324
|
this.model.selection.capture(this, {
|
|
21326
|
-
cell: { col: col ?? zone.left, row: row ?? zone.
|
|
21325
|
+
cell: { col: col ?? zone.left, row: row ?? zone.top },
|
|
21327
21326
|
zone,
|
|
21328
21327
|
}, {
|
|
21329
21328
|
handleEvent: this.handleEvent.bind(this),
|
|
@@ -44864,6 +44863,11 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
44864
44863
|
case "ACTIVATE_SHEET":
|
|
44865
44864
|
this.isSearchDirty = true;
|
|
44866
44865
|
this.shouldFinalizeUpdateSelection = true;
|
|
44866
|
+
if (this.searchOptions.specificRange) {
|
|
44867
|
+
this.searchOptions.specificRange = this.searchOptions.specificRange.clone({
|
|
44868
|
+
sheetId: this.getters.getActiveSheetId(),
|
|
44869
|
+
});
|
|
44870
|
+
}
|
|
44867
44871
|
break;
|
|
44868
44872
|
case "REPLACE_SEARCH":
|
|
44869
44873
|
for (const match of cmd.matches) {
|
|
@@ -45285,9 +45289,20 @@ class FindAndReplacePanel extends Component {
|
|
|
45285
45289
|
const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
|
|
45286
45290
|
this.store.updateSearchOptions({ specificRange });
|
|
45287
45291
|
}
|
|
45292
|
+
get specificRange() {
|
|
45293
|
+
const range = this.store.searchOptions.specificRange;
|
|
45294
|
+
return range ? this.env.model.getters.getRangeString(range, "forceSheetReference") : "";
|
|
45295
|
+
}
|
|
45288
45296
|
get pendingSearch() {
|
|
45289
45297
|
return this.updateSearchContent.isDebouncePending();
|
|
45290
45298
|
}
|
|
45299
|
+
get selectionInputKey() {
|
|
45300
|
+
// Selections input are made to work with objects linked to a sheet id. They store the active sheet id at their creation,
|
|
45301
|
+
// and have specific behaviour linked to it (eg. go back to the initial sheet after confirmation).
|
|
45302
|
+
// We don't want all those behaviors here, so we force the recreation of the component when the active sheet changes.
|
|
45303
|
+
// The only drawback is that the input loses focus when changing sheet.
|
|
45304
|
+
return this.env.model.getters.getActiveSheetId();
|
|
45305
|
+
}
|
|
45291
45306
|
}
|
|
45292
45307
|
|
|
45293
45308
|
css /* scss */ `
|
|
@@ -59818,6 +59833,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59818
59833
|
"getMeasureCompiledFormula",
|
|
59819
59834
|
"getPivotName",
|
|
59820
59835
|
"isExistingPivot",
|
|
59836
|
+
"getMeasureFullDependencies",
|
|
59821
59837
|
];
|
|
59822
59838
|
nextFormulaId = 1;
|
|
59823
59839
|
pivots = {};
|
|
@@ -59900,7 +59916,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59900
59916
|
}
|
|
59901
59917
|
case "UPDATE_PIVOT": {
|
|
59902
59918
|
this.history.update("pivots", cmd.pivotId, "definition", this.repairSortedColumn(deepCopy(cmd.pivot)));
|
|
59903
|
-
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
59919
|
+
this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
|
|
59904
59920
|
break;
|
|
59905
59921
|
}
|
|
59906
59922
|
}
|
|
@@ -59918,9 +59934,14 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59918
59934
|
this.history.update("pivots", pivotId, "definition", newDefinition);
|
|
59919
59935
|
}
|
|
59920
59936
|
}
|
|
59921
|
-
for (const
|
|
59922
|
-
for (const
|
|
59923
|
-
const
|
|
59937
|
+
for (const pivotId in this.compiledMeasureFormulas) {
|
|
59938
|
+
for (const measureId in this.compiledMeasureFormulas[pivotId]) {
|
|
59939
|
+
const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
|
|
59940
|
+
if (!measure || !measure.computedBy) {
|
|
59941
|
+
continue;
|
|
59942
|
+
}
|
|
59943
|
+
const sheetId = measure.computedBy.sheetId;
|
|
59944
|
+
const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
|
|
59924
59945
|
const newDependencies = [];
|
|
59925
59946
|
for (const range of compiledFormula.dependencies) {
|
|
59926
59947
|
const change = applyChange(range);
|
|
@@ -59932,8 +59953,9 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59932
59953
|
}
|
|
59933
59954
|
}
|
|
59934
59955
|
const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
|
|
59935
|
-
|
|
59936
|
-
|
|
59956
|
+
const oldFormulaString = measure.computedBy.formula;
|
|
59957
|
+
if (newFormulaString !== oldFormulaString) {
|
|
59958
|
+
this.replaceMeasureFormula(pivotId, measure, newFormulaString);
|
|
59937
59959
|
}
|
|
59938
59960
|
}
|
|
59939
59961
|
}
|
|
@@ -59971,12 +59993,17 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59971
59993
|
isExistingPivot(pivotId) {
|
|
59972
59994
|
return pivotId in this.pivots;
|
|
59973
59995
|
}
|
|
59974
|
-
getMeasureCompiledFormula(measure) {
|
|
59996
|
+
getMeasureCompiledFormula(pivotId, measure) {
|
|
59975
59997
|
if (!measure.computedBy) {
|
|
59976
59998
|
throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
|
|
59977
59999
|
}
|
|
59978
|
-
|
|
59979
|
-
|
|
60000
|
+
return this.compiledMeasureFormulas[pivotId][measure.id].formula;
|
|
60001
|
+
}
|
|
60002
|
+
getMeasureFullDependencies(pivotId, measure) {
|
|
60003
|
+
if (!measure.computedBy) {
|
|
60004
|
+
throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
|
|
60005
|
+
}
|
|
60006
|
+
return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
|
|
59980
60007
|
}
|
|
59981
60008
|
// -------------------------------------------------------------------------
|
|
59982
60009
|
// Private
|
|
@@ -59986,18 +60013,42 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
59986
60013
|
definition: this.repairSortedColumn(deepCopy(pivot)),
|
|
59987
60014
|
formulaId,
|
|
59988
60015
|
});
|
|
59989
|
-
this.compileCalculatedMeasures(pivot.measures);
|
|
60016
|
+
this.compileCalculatedMeasures(pivotId, pivot.measures);
|
|
59990
60017
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
59991
60018
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
59992
60019
|
}
|
|
59993
|
-
compileCalculatedMeasures(measures) {
|
|
60020
|
+
compileCalculatedMeasures(pivotId, measures) {
|
|
59994
60021
|
for (const measure of measures) {
|
|
59995
60022
|
if (measure.computedBy) {
|
|
59996
|
-
const sheetId = measure.computedBy.sheetId;
|
|
59997
60023
|
const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
|
|
59998
|
-
this.history.update("compiledMeasureFormulas",
|
|
60024
|
+
this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
|
|
59999
60025
|
}
|
|
60000
60026
|
}
|
|
60027
|
+
for (const measure of measures) {
|
|
60028
|
+
if (measure.computedBy) {
|
|
60029
|
+
const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
|
|
60030
|
+
this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
|
|
60031
|
+
}
|
|
60032
|
+
}
|
|
60033
|
+
}
|
|
60034
|
+
computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
|
|
60035
|
+
const rangeDependencies = [];
|
|
60036
|
+
const definition = this.getPivotCoreDefinition(pivotId);
|
|
60037
|
+
const formula = this.getMeasureCompiledFormula(pivotId, measure);
|
|
60038
|
+
exploredMeasures.add(measure.id);
|
|
60039
|
+
for (const token of formula.tokens) {
|
|
60040
|
+
if (token.type !== "SYMBOL") {
|
|
60041
|
+
continue;
|
|
60042
|
+
}
|
|
60043
|
+
const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
|
|
60044
|
+
measure.id !== measureCandidate.id);
|
|
60045
|
+
if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
|
|
60046
|
+
continue;
|
|
60047
|
+
}
|
|
60048
|
+
rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
|
|
60049
|
+
}
|
|
60050
|
+
rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
60051
|
+
return rangeDependencies;
|
|
60001
60052
|
}
|
|
60002
60053
|
insertPivot(position, formulaId, table) {
|
|
60003
60054
|
this.resizeSheet(position.sheetId, position, table);
|
|
@@ -60055,21 +60106,17 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
60055
60106
|
dependencies: rangeDependencies,
|
|
60056
60107
|
};
|
|
60057
60108
|
}
|
|
60058
|
-
replaceMeasureFormula(
|
|
60059
|
-
|
|
60060
|
-
|
|
60061
|
-
|
|
60062
|
-
const pivot = this.pivots[pivotId];
|
|
60063
|
-
if (!pivot) {
|
|
60064
|
-
continue;
|
|
60065
|
-
}
|
|
60066
|
-
for (const measure of pivot.definition.measures) {
|
|
60067
|
-
if (measure.computedBy?.formula === formulaString) {
|
|
60068
|
-
const measureIndex = pivot.definition.measures.indexOf(measure);
|
|
60069
|
-
this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
|
|
60070
|
-
}
|
|
60071
|
-
}
|
|
60109
|
+
replaceMeasureFormula(pivotId, measure, newFormulaString) {
|
|
60110
|
+
const pivot = this.pivots[pivotId];
|
|
60111
|
+
if (!pivot) {
|
|
60112
|
+
return;
|
|
60072
60113
|
}
|
|
60114
|
+
const measureIndex = pivot.definition.measures.indexOf(measure);
|
|
60115
|
+
this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
|
|
60116
|
+
formula: newFormulaString,
|
|
60117
|
+
sheetId: measure.computedBy.sheetId,
|
|
60118
|
+
});
|
|
60119
|
+
this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
|
|
60073
60120
|
}
|
|
60074
60121
|
checkDuplicatedMeasureIds(definition) {
|
|
60075
60122
|
const uniqueIds = new Set(definition.measures.map((m) => m.id));
|
|
@@ -63334,14 +63381,16 @@ const PERCENT_FORMAT = "0.00%";
|
|
|
63334
63381
|
function withPivotPresentationLayer (PivotClass) {
|
|
63335
63382
|
class PivotPresentationLayer extends PivotClass {
|
|
63336
63383
|
getters;
|
|
63384
|
+
pivotId;
|
|
63337
63385
|
cache = {};
|
|
63338
63386
|
rankAsc = {};
|
|
63339
63387
|
rankDesc = {};
|
|
63340
63388
|
runningTotal = {};
|
|
63341
63389
|
runningTotalInPercent = {};
|
|
63342
|
-
constructor(custom, params) {
|
|
63390
|
+
constructor(pivotId, custom, params) {
|
|
63343
63391
|
super(custom, params);
|
|
63344
63392
|
this.getters = params.getters;
|
|
63393
|
+
this.pivotId = pivotId;
|
|
63345
63394
|
}
|
|
63346
63395
|
markAsDirtyForEvaluation() {
|
|
63347
63396
|
this.cache = {};
|
|
@@ -63391,7 +63440,7 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
63391
63440
|
return handleError(error, measure.aggregator.toUpperCase());
|
|
63392
63441
|
}
|
|
63393
63442
|
}
|
|
63394
|
-
const formula = this.getters.getMeasureCompiledFormula(measure);
|
|
63443
|
+
const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
|
|
63395
63444
|
const getSymbolValue = (symbolName) => {
|
|
63396
63445
|
const { columns, rows } = this.definition;
|
|
63397
63446
|
if (columns.find((col) => col.nameWithGranularity === symbolName)) {
|
|
@@ -64119,7 +64168,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
64119
64168
|
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
64120
64169
|
if (!(pivotId in this.pivots)) {
|
|
64121
64170
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
64122
|
-
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
64171
|
+
this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
|
|
64123
64172
|
}
|
|
64124
64173
|
else if (recreate) {
|
|
64125
64174
|
this.pivots[pivotId].onDefinitionChange(definition);
|
|
@@ -77374,6 +77423,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
77374
77423
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
77375
77424
|
|
|
77376
77425
|
|
|
77377
|
-
__info__.version = "18.2.
|
|
77378
|
-
__info__.date = "
|
|
77379
|
-
__info__.hash = "
|
|
77426
|
+
__info__.version = "18.2.40";
|
|
77427
|
+
__info__.date = "2026-01-14T09:59:34.210Z";
|
|
77428
|
+
__info__.hash = "755a787";
|