@odoo/o-spreadsheet 18.2.26 → 18.2.28
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 +69 -39
- package/dist/o-spreadsheet.d.ts +10 -10
- package/dist/o-spreadsheet.esm.js +69 -39
- package/dist/o-spreadsheet.iife.js +69 -39
- package/dist/o-spreadsheet.iife.min.js +388 -388
- package/dist/o_spreadsheet.xml +10 -7
- 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 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.28
|
|
6
|
+
* @date 2025-09-05T07:38:26.582Z
|
|
7
|
+
* @hash 84335fb
|
|
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';
|
|
@@ -3476,6 +3476,7 @@ const invalidateBordersCommands = new Set([
|
|
|
3476
3476
|
"AUTOFILL_CELL",
|
|
3477
3477
|
"SET_BORDER",
|
|
3478
3478
|
"SET_ZONE_BORDERS",
|
|
3479
|
+
"SET_BORDERS_ON_TARGET",
|
|
3479
3480
|
]);
|
|
3480
3481
|
const readonlyAllowedCommands = new Set([
|
|
3481
3482
|
"START",
|
|
@@ -6821,15 +6822,22 @@ function parseOSClipboardContent(content) {
|
|
|
6821
6822
|
};
|
|
6822
6823
|
}
|
|
6823
6824
|
const htmlDocument = new DOMParser().parseFromString(content[ClipboardMIMEType.Html], "text/html");
|
|
6824
|
-
const oSheetClipboardData = htmlDocument
|
|
6825
|
-
.querySelector("div")
|
|
6826
|
-
?.getAttribute("data-osheet-clipboard");
|
|
6827
|
-
const spreadsheetContent = oSheetClipboardData && JSON.parse(oSheetClipboardData);
|
|
6828
6825
|
return {
|
|
6829
6826
|
text: content[ClipboardMIMEType.PlainText],
|
|
6830
|
-
data:
|
|
6827
|
+
data: getOSheetDataFromHTML(htmlDocument),
|
|
6831
6828
|
};
|
|
6832
6829
|
}
|
|
6830
|
+
function getOSheetDataFromHTML(htmlDocument) {
|
|
6831
|
+
const attributes = [...htmlDocument.documentElement.attributes];
|
|
6832
|
+
// Check if it's a Microsoft Office clipboard data (it will have some namespaces defined in the root element)
|
|
6833
|
+
if (attributes.some((attr) => attr.value.includes("microsoft"))) {
|
|
6834
|
+
return undefined;
|
|
6835
|
+
}
|
|
6836
|
+
const oSheetClipboardData = htmlDocument
|
|
6837
|
+
.querySelector("div")
|
|
6838
|
+
?.getAttribute("data-osheet-clipboard");
|
|
6839
|
+
return oSheetClipboardData && JSON.parse(oSheetClipboardData);
|
|
6840
|
+
}
|
|
6833
6841
|
/**
|
|
6834
6842
|
* Applies each clipboard handler to paste its corresponding data into the target.
|
|
6835
6843
|
*/
|
|
@@ -7519,8 +7527,11 @@ function invertMatrix(M) {
|
|
|
7519
7527
|
// (a) Swap 2 rows. This multiply the determinant by -1.
|
|
7520
7528
|
// (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
|
|
7521
7529
|
// (c) Add to a row a multiple of another row. This does not change the determinant.
|
|
7530
|
+
if (M.length < 1 || M[0].length < 1) {
|
|
7531
|
+
throw new Error("invertMatrix: an empty matrix cannot be inverted.");
|
|
7532
|
+
}
|
|
7522
7533
|
if (M.length !== M[0].length) {
|
|
7523
|
-
throw new
|
|
7534
|
+
throw new Error("invertMatrix: only square matrices are invertible");
|
|
7524
7535
|
}
|
|
7525
7536
|
let determinant = 1;
|
|
7526
7537
|
const dim = M.length;
|
|
@@ -7589,8 +7600,11 @@ function swapMatrixRows(matrix, row1, row2) {
|
|
|
7589
7600
|
* Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
|
|
7590
7601
|
*/
|
|
7591
7602
|
function multiplyMatrices(matrix1, matrix2) {
|
|
7603
|
+
if (matrix1.length < 1 || matrix2.length < 1) {
|
|
7604
|
+
throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
|
|
7605
|
+
}
|
|
7592
7606
|
if (matrix1.length !== matrix2[0].length) {
|
|
7593
|
-
throw new
|
|
7607
|
+
throw new Error("multiplyMatrices: incompatible matrices size.");
|
|
7594
7608
|
}
|
|
7595
7609
|
const rowsM1 = matrix1[0].length;
|
|
7596
7610
|
const colsM2 = matrix2.length;
|
|
@@ -7616,7 +7630,7 @@ function toScalar(arg) {
|
|
|
7616
7630
|
return arg;
|
|
7617
7631
|
}
|
|
7618
7632
|
if (!isSingleElementMatrix(arg)) {
|
|
7619
|
-
throw new
|
|
7633
|
+
throw new Error("The value should be a scalar or a 1x1 matrix");
|
|
7620
7634
|
}
|
|
7621
7635
|
return arg[0][0];
|
|
7622
7636
|
}
|
|
@@ -7853,6 +7867,16 @@ function getMovingAverageValues(dataset, labels, windowSize = DEFAULT_WINDOW_SIZ
|
|
|
7853
7867
|
}
|
|
7854
7868
|
return values;
|
|
7855
7869
|
}
|
|
7870
|
+
function assertNonEmptyMatrix(matrix, argName) {
|
|
7871
|
+
assert(() => matrix.length > 0 && matrix[0].length > 0, _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", {
|
|
7872
|
+
argName,
|
|
7873
|
+
}));
|
|
7874
|
+
}
|
|
7875
|
+
function assertNonEmpty(...data) {
|
|
7876
|
+
if (data.length === 0 || data.some((arg) => arg.length === 0)) {
|
|
7877
|
+
throw new NotAvailableError(_t("[[FUNCTION_NAME]] has no valid input data."));
|
|
7878
|
+
}
|
|
7879
|
+
}
|
|
7856
7880
|
|
|
7857
7881
|
const PREVIOUS_VALUE = "(previous)";
|
|
7858
7882
|
const NEXT_VALUE = "(next)";
|
|
@@ -11790,6 +11814,7 @@ const MMULT = {
|
|
|
11790
11814
|
compute: function (matrix1, matrix2) {
|
|
11791
11815
|
const _matrix1 = toNumberMatrix(matrix1, "matrix1");
|
|
11792
11816
|
const _matrix2 = toNumberMatrix(matrix2, "matrix2");
|
|
11817
|
+
assert(() => _matrix1.length > 0 && _matrix2.length > 0, _t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
|
|
11793
11818
|
assert(() => _matrix1.length === _matrix2[0].length, _t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
|
|
11794
11819
|
number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
|
|
11795
11820
|
return multiplyMatrices(_matrix1, _matrix2);
|
|
@@ -13585,6 +13610,7 @@ const FORECAST = {
|
|
|
13585
13610
|
],
|
|
13586
13611
|
compute: function (x, dataY, dataX) {
|
|
13587
13612
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13613
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13588
13614
|
return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
|
|
13589
13615
|
},
|
|
13590
13616
|
isExported: true,
|
|
@@ -13601,6 +13627,7 @@ const GROWTH = {
|
|
|
13601
13627
|
arg("b (boolean, default=TRUE)", _t("Given a general exponential form of y = b*m^x for a curve fit, calculates b if TRUE or forces b to be 1 and only calculates the m values if FALSE.")),
|
|
13602
13628
|
],
|
|
13603
13629
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
13630
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
13604
13631
|
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "the first argument (known_data_y)")), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b)));
|
|
13605
13632
|
},
|
|
13606
13633
|
};
|
|
@@ -13615,6 +13642,7 @@ const INTERCEPT = {
|
|
|
13615
13642
|
],
|
|
13616
13643
|
compute: function (dataY, dataX) {
|
|
13617
13644
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13645
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13618
13646
|
const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
13619
13647
|
return intercept;
|
|
13620
13648
|
},
|
|
@@ -13664,6 +13692,7 @@ const LINEST = {
|
|
|
13664
13692
|
arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
|
|
13665
13693
|
],
|
|
13666
13694
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13695
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13667
13696
|
return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
|
|
13668
13697
|
},
|
|
13669
13698
|
isExported: true,
|
|
@@ -13680,6 +13709,7 @@ const LOGEST = {
|
|
|
13680
13709
|
arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
|
|
13681
13710
|
],
|
|
13682
13711
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13712
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13683
13713
|
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
|
|
13684
13714
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13685
13715
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
@@ -13701,9 +13731,7 @@ const MATTHEWS = {
|
|
|
13701
13731
|
const flatX = dataX.flat();
|
|
13702
13732
|
const flatY = dataY.flat();
|
|
13703
13733
|
assertSameNumberOfElements(flatX, flatY);
|
|
13704
|
-
|
|
13705
|
-
return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13706
|
-
}
|
|
13734
|
+
assertNonEmpty(flatX, flatY);
|
|
13707
13735
|
const n = flatX.length;
|
|
13708
13736
|
let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
|
|
13709
13737
|
for (let i = 0; i < n; ++i) {
|
|
@@ -13867,12 +13895,7 @@ const MINIFS = {
|
|
|
13867
13895
|
// -----------------------------------------------------------------------------
|
|
13868
13896
|
function pearson(dataY, dataX) {
|
|
13869
13897
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13870
|
-
|
|
13871
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13872
|
-
}
|
|
13873
|
-
if (flatDataX.length < 2) {
|
|
13874
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
|
|
13875
|
-
}
|
|
13898
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13876
13899
|
const n = flatDataX.length;
|
|
13877
13900
|
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
|
|
13878
13901
|
for (let i = 0; i < n; i++) {
|
|
@@ -13961,6 +13984,7 @@ const POLYFIT_COEFFS = {
|
|
|
13961
13984
|
],
|
|
13962
13985
|
compute: function (dataY, dataX, order, intercept = { value: true }) {
|
|
13963
13986
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13987
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13964
13988
|
return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
|
|
13965
13989
|
},
|
|
13966
13990
|
isExported: false,
|
|
@@ -13980,6 +14004,7 @@ const POLYFIT_FORECAST = {
|
|
|
13980
14004
|
compute: function (x, dataY, dataX, order, intercept = { value: true }) {
|
|
13981
14005
|
const _order = toNumber(order, this.locale);
|
|
13982
14006
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14007
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13983
14008
|
const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
|
|
13984
14009
|
return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
|
|
13985
14010
|
},
|
|
@@ -14096,6 +14121,7 @@ const SLOPE = {
|
|
|
14096
14121
|
],
|
|
14097
14122
|
compute: function (dataY, dataX) {
|
|
14098
14123
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14124
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14099
14125
|
const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
14100
14126
|
return slope;
|
|
14101
14127
|
},
|
|
@@ -14144,6 +14170,7 @@ const SPEARMAN = {
|
|
|
14144
14170
|
],
|
|
14145
14171
|
compute: function (dataX, dataY) {
|
|
14146
14172
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14173
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14147
14174
|
const n = flatDataX.length;
|
|
14148
14175
|
const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
|
|
14149
14176
|
order.sort((a, b) => a[0] - b[0]);
|
|
@@ -14254,6 +14281,7 @@ const STEYX = {
|
|
|
14254
14281
|
],
|
|
14255
14282
|
compute: function (dataY, dataX) {
|
|
14256
14283
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14284
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14257
14285
|
const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
|
|
14258
14286
|
return data[1][2];
|
|
14259
14287
|
},
|
|
@@ -14271,6 +14299,7 @@ const TREND = {
|
|
|
14271
14299
|
arg("b (boolean, optional, default=TRUE)", _t("Given a general linear form of y = m*x+b for a curve fit, calculates b if TRUE or forces b to be 0 and only calculates the m values if FALSE, i.e. forces the curve fit to pass through the origin.")),
|
|
14272
14300
|
],
|
|
14273
14301
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
14302
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
14274
14303
|
return predictLinearValues(toNumberMatrix(knownDataY, "the first argument (known_data_y)"), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b));
|
|
14275
14304
|
},
|
|
14276
14305
|
};
|
|
@@ -24477,9 +24506,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
24477
24506
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
24478
24507
|
continue;
|
|
24479
24508
|
operator = convertCFCellIsOperator(rule.operator);
|
|
24480
|
-
values.push(rule.formula[0]);
|
|
24509
|
+
values.push(prefixFormula(rule.formula[0]));
|
|
24481
24510
|
if (rule.formula.length === 2) {
|
|
24482
|
-
values.push(rule.formula[1]);
|
|
24511
|
+
values.push(prefixFormula(rule.formula[1]));
|
|
24483
24512
|
}
|
|
24484
24513
|
break;
|
|
24485
24514
|
}
|
|
@@ -24637,6 +24666,11 @@ function convertIcons(xlsxIconSet, index) {
|
|
|
24637
24666
|
? ICON_SETS[iconSet].neutral
|
|
24638
24667
|
: ICON_SETS[iconSet].good;
|
|
24639
24668
|
}
|
|
24669
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
24670
|
+
function prefixFormula(formula) {
|
|
24671
|
+
const tokens = tokenize(formula);
|
|
24672
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
24673
|
+
}
|
|
24640
24674
|
// ---------------------------------------------------------------------------
|
|
24641
24675
|
// Warnings
|
|
24642
24676
|
// ---------------------------------------------------------------------------
|
|
@@ -30894,10 +30928,6 @@ class ComboChart extends AbstractChart {
|
|
|
30894
30928
|
};
|
|
30895
30929
|
}
|
|
30896
30930
|
getDefinitionForExcel() {
|
|
30897
|
-
// Excel does not support aggregating labels
|
|
30898
|
-
if (this.aggregated) {
|
|
30899
|
-
return undefined;
|
|
30900
|
-
}
|
|
30901
30931
|
const dataSets = this.dataSets
|
|
30902
30932
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
30903
30933
|
.filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
|
|
@@ -32049,10 +32079,6 @@ class ScatterChart extends AbstractChart {
|
|
|
32049
32079
|
return new ScatterChart(definition, this.sheetId, this.getters);
|
|
32050
32080
|
}
|
|
32051
32081
|
getDefinitionForExcel() {
|
|
32052
|
-
// Excel does not support aggregating labels
|
|
32053
|
-
if (this.aggregated) {
|
|
32054
|
-
return undefined;
|
|
32055
|
-
}
|
|
32056
32082
|
const dataSets = this.dataSets
|
|
32057
32083
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
32058
32084
|
.filter((ds) => ds.range !== "");
|
|
@@ -36169,7 +36195,7 @@ const splitToColumns = {
|
|
|
36169
36195
|
const reinsertDynamicPivotMenu = {
|
|
36170
36196
|
id: "reinsert_dynamic_pivot",
|
|
36171
36197
|
name: _t("Re-insert dynamic pivot"),
|
|
36172
|
-
sequence:
|
|
36198
|
+
sequence: 60,
|
|
36173
36199
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36174
36200
|
children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
|
|
36175
36201
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -36177,7 +36203,7 @@ const reinsertDynamicPivotMenu = {
|
|
|
36177
36203
|
const reinsertStaticPivotMenu = {
|
|
36178
36204
|
id: "reinsert_static_pivot",
|
|
36179
36205
|
name: _t("Re-insert static pivot"),
|
|
36180
|
-
sequence:
|
|
36206
|
+
sequence: 70,
|
|
36181
36207
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36182
36208
|
children: [REINSERT_STATIC_PIVOT_CHILDREN],
|
|
36183
36209
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -37915,8 +37941,9 @@ topbarMenuRegistry
|
|
|
37915
37941
|
sequence: 40,
|
|
37916
37942
|
separator: true,
|
|
37917
37943
|
})
|
|
37918
|
-
.addChild("
|
|
37944
|
+
.addChild("pivot_data_sources", ["data"], (env) => {
|
|
37919
37945
|
const sequence = 50;
|
|
37946
|
+
const numberOfPivots = env.model.getters.getPivotIds().length;
|
|
37920
37947
|
return env.model.getters.getPivotIds().map((pivotId, index) => {
|
|
37921
37948
|
const highlightProvider = {
|
|
37922
37949
|
get highlights() {
|
|
@@ -37926,7 +37953,7 @@ topbarMenuRegistry
|
|
|
37926
37953
|
return {
|
|
37927
37954
|
id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
|
|
37928
37955
|
name: env.model.getters.getPivotDisplayName(pivotId),
|
|
37929
|
-
sequence: sequence + index,
|
|
37956
|
+
sequence: sequence + index / numberOfPivots,
|
|
37930
37957
|
isReadonlyAllowed: true,
|
|
37931
37958
|
execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
|
|
37932
37959
|
onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
|
|
@@ -63898,7 +63925,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
63898
63925
|
if (!result) {
|
|
63899
63926
|
return EMPTY_PIVOT_CELL;
|
|
63900
63927
|
}
|
|
63901
|
-
|
|
63928
|
+
let { functionName, args } = result;
|
|
63902
63929
|
const formulaId = args[0];
|
|
63903
63930
|
if (!formulaId) {
|
|
63904
63931
|
return EMPTY_PIVOT_CELL;
|
|
@@ -63928,6 +63955,9 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
63928
63955
|
return pivotCells[pivotCol][pivotRow];
|
|
63929
63956
|
}
|
|
63930
63957
|
try {
|
|
63958
|
+
const offsetRow = position.row - mainPosition.row;
|
|
63959
|
+
const offsetCol = position.col - mainPosition.col;
|
|
63960
|
+
args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
|
|
63931
63961
|
if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
|
|
63932
63962
|
const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
|
|
63933
63963
|
return {
|
|
@@ -76548,7 +76578,7 @@ class Model extends EventBus {
|
|
|
76548
76578
|
handlers = [];
|
|
76549
76579
|
uiHandlers = [];
|
|
76550
76580
|
coreHandlers = [];
|
|
76551
|
-
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport =
|
|
76581
|
+
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
|
|
76552
76582
|
const start = performance.now();
|
|
76553
76583
|
console.debug("##### Model creation #####");
|
|
76554
76584
|
super();
|
|
@@ -77239,6 +77269,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
77239
77269
|
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 };
|
|
77240
77270
|
|
|
77241
77271
|
|
|
77242
|
-
__info__.version = "18.2.
|
|
77243
|
-
__info__.date = "2025-
|
|
77244
|
-
__info__.hash = "
|
|
77272
|
+
__info__.version = "18.2.28";
|
|
77273
|
+
__info__.date = "2025-09-05T07:38:26.582Z";
|
|
77274
|
+
__info__.hash = "84335fb";
|
|
@@ -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 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.28
|
|
6
|
+
* @date 2025-09-05T07:38:26.582Z
|
|
7
|
+
* @hash 84335fb
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -3477,6 +3477,7 @@
|
|
|
3477
3477
|
"AUTOFILL_CELL",
|
|
3478
3478
|
"SET_BORDER",
|
|
3479
3479
|
"SET_ZONE_BORDERS",
|
|
3480
|
+
"SET_BORDERS_ON_TARGET",
|
|
3480
3481
|
]);
|
|
3481
3482
|
const readonlyAllowedCommands = new Set([
|
|
3482
3483
|
"START",
|
|
@@ -6822,15 +6823,22 @@
|
|
|
6822
6823
|
};
|
|
6823
6824
|
}
|
|
6824
6825
|
const htmlDocument = new DOMParser().parseFromString(content[ClipboardMIMEType.Html], "text/html");
|
|
6825
|
-
const oSheetClipboardData = htmlDocument
|
|
6826
|
-
.querySelector("div")
|
|
6827
|
-
?.getAttribute("data-osheet-clipboard");
|
|
6828
|
-
const spreadsheetContent = oSheetClipboardData && JSON.parse(oSheetClipboardData);
|
|
6829
6826
|
return {
|
|
6830
6827
|
text: content[ClipboardMIMEType.PlainText],
|
|
6831
|
-
data:
|
|
6828
|
+
data: getOSheetDataFromHTML(htmlDocument),
|
|
6832
6829
|
};
|
|
6833
6830
|
}
|
|
6831
|
+
function getOSheetDataFromHTML(htmlDocument) {
|
|
6832
|
+
const attributes = [...htmlDocument.documentElement.attributes];
|
|
6833
|
+
// Check if it's a Microsoft Office clipboard data (it will have some namespaces defined in the root element)
|
|
6834
|
+
if (attributes.some((attr) => attr.value.includes("microsoft"))) {
|
|
6835
|
+
return undefined;
|
|
6836
|
+
}
|
|
6837
|
+
const oSheetClipboardData = htmlDocument
|
|
6838
|
+
.querySelector("div")
|
|
6839
|
+
?.getAttribute("data-osheet-clipboard");
|
|
6840
|
+
return oSheetClipboardData && JSON.parse(oSheetClipboardData);
|
|
6841
|
+
}
|
|
6834
6842
|
/**
|
|
6835
6843
|
* Applies each clipboard handler to paste its corresponding data into the target.
|
|
6836
6844
|
*/
|
|
@@ -7520,8 +7528,11 @@
|
|
|
7520
7528
|
// (a) Swap 2 rows. This multiply the determinant by -1.
|
|
7521
7529
|
// (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
|
|
7522
7530
|
// (c) Add to a row a multiple of another row. This does not change the determinant.
|
|
7531
|
+
if (M.length < 1 || M[0].length < 1) {
|
|
7532
|
+
throw new Error("invertMatrix: an empty matrix cannot be inverted.");
|
|
7533
|
+
}
|
|
7523
7534
|
if (M.length !== M[0].length) {
|
|
7524
|
-
throw new
|
|
7535
|
+
throw new Error("invertMatrix: only square matrices are invertible");
|
|
7525
7536
|
}
|
|
7526
7537
|
let determinant = 1;
|
|
7527
7538
|
const dim = M.length;
|
|
@@ -7590,8 +7601,11 @@
|
|
|
7590
7601
|
* Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
|
|
7591
7602
|
*/
|
|
7592
7603
|
function multiplyMatrices(matrix1, matrix2) {
|
|
7604
|
+
if (matrix1.length < 1 || matrix2.length < 1) {
|
|
7605
|
+
throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
|
|
7606
|
+
}
|
|
7593
7607
|
if (matrix1.length !== matrix2[0].length) {
|
|
7594
|
-
throw new
|
|
7608
|
+
throw new Error("multiplyMatrices: incompatible matrices size.");
|
|
7595
7609
|
}
|
|
7596
7610
|
const rowsM1 = matrix1[0].length;
|
|
7597
7611
|
const colsM2 = matrix2.length;
|
|
@@ -7617,7 +7631,7 @@
|
|
|
7617
7631
|
return arg;
|
|
7618
7632
|
}
|
|
7619
7633
|
if (!isSingleElementMatrix(arg)) {
|
|
7620
|
-
throw new
|
|
7634
|
+
throw new Error("The value should be a scalar or a 1x1 matrix");
|
|
7621
7635
|
}
|
|
7622
7636
|
return arg[0][0];
|
|
7623
7637
|
}
|
|
@@ -7854,6 +7868,16 @@
|
|
|
7854
7868
|
}
|
|
7855
7869
|
return values;
|
|
7856
7870
|
}
|
|
7871
|
+
function assertNonEmptyMatrix(matrix, argName) {
|
|
7872
|
+
assert(() => matrix.length > 0 && matrix[0].length > 0, _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", {
|
|
7873
|
+
argName,
|
|
7874
|
+
}));
|
|
7875
|
+
}
|
|
7876
|
+
function assertNonEmpty(...data) {
|
|
7877
|
+
if (data.length === 0 || data.some((arg) => arg.length === 0)) {
|
|
7878
|
+
throw new NotAvailableError(_t("[[FUNCTION_NAME]] has no valid input data."));
|
|
7879
|
+
}
|
|
7880
|
+
}
|
|
7857
7881
|
|
|
7858
7882
|
const PREVIOUS_VALUE = "(previous)";
|
|
7859
7883
|
const NEXT_VALUE = "(next)";
|
|
@@ -11791,6 +11815,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
11791
11815
|
compute: function (matrix1, matrix2) {
|
|
11792
11816
|
const _matrix1 = toNumberMatrix(matrix1, "matrix1");
|
|
11793
11817
|
const _matrix2 = toNumberMatrix(matrix2, "matrix2");
|
|
11818
|
+
assert(() => _matrix1.length > 0 && _matrix2.length > 0, _t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
|
|
11794
11819
|
assert(() => _matrix1.length === _matrix2[0].length, _t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
|
|
11795
11820
|
number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
|
|
11796
11821
|
return multiplyMatrices(_matrix1, _matrix2);
|
|
@@ -13586,6 +13611,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13586
13611
|
],
|
|
13587
13612
|
compute: function (x, dataY, dataX) {
|
|
13588
13613
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13614
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13589
13615
|
return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
|
|
13590
13616
|
},
|
|
13591
13617
|
isExported: true,
|
|
@@ -13602,6 +13628,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13602
13628
|
arg("b (boolean, default=TRUE)", _t("Given a general exponential form of y = b*m^x for a curve fit, calculates b if TRUE or forces b to be 1 and only calculates the m values if FALSE.")),
|
|
13603
13629
|
],
|
|
13604
13630
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
13631
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
13605
13632
|
return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "the first argument (known_data_y)")), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b)));
|
|
13606
13633
|
},
|
|
13607
13634
|
};
|
|
@@ -13616,6 +13643,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13616
13643
|
],
|
|
13617
13644
|
compute: function (dataY, dataX) {
|
|
13618
13645
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13646
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13619
13647
|
const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
13620
13648
|
return intercept;
|
|
13621
13649
|
},
|
|
@@ -13665,6 +13693,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13665
13693
|
arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
|
|
13666
13694
|
],
|
|
13667
13695
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13696
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13668
13697
|
return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
|
|
13669
13698
|
},
|
|
13670
13699
|
isExported: true,
|
|
@@ -13681,6 +13710,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13681
13710
|
arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
|
|
13682
13711
|
],
|
|
13683
13712
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13713
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13684
13714
|
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
|
|
13685
13715
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13686
13716
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
@@ -13702,9 +13732,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13702
13732
|
const flatX = dataX.flat();
|
|
13703
13733
|
const flatY = dataY.flat();
|
|
13704
13734
|
assertSameNumberOfElements(flatX, flatY);
|
|
13705
|
-
|
|
13706
|
-
return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13707
|
-
}
|
|
13735
|
+
assertNonEmpty(flatX, flatY);
|
|
13708
13736
|
const n = flatX.length;
|
|
13709
13737
|
let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
|
|
13710
13738
|
for (let i = 0; i < n; ++i) {
|
|
@@ -13868,12 +13896,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13868
13896
|
// -----------------------------------------------------------------------------
|
|
13869
13897
|
function pearson(dataY, dataX) {
|
|
13870
13898
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13871
|
-
|
|
13872
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13873
|
-
}
|
|
13874
|
-
if (flatDataX.length < 2) {
|
|
13875
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
|
|
13876
|
-
}
|
|
13899
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13877
13900
|
const n = flatDataX.length;
|
|
13878
13901
|
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
|
|
13879
13902
|
for (let i = 0; i < n; i++) {
|
|
@@ -13962,6 +13985,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13962
13985
|
],
|
|
13963
13986
|
compute: function (dataY, dataX, order, intercept = { value: true }) {
|
|
13964
13987
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13988
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13965
13989
|
return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
|
|
13966
13990
|
},
|
|
13967
13991
|
isExported: false,
|
|
@@ -13981,6 +14005,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13981
14005
|
compute: function (x, dataY, dataX, order, intercept = { value: true }) {
|
|
13982
14006
|
const _order = toNumber(order, this.locale);
|
|
13983
14007
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14008
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13984
14009
|
const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
|
|
13985
14010
|
return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
|
|
13986
14011
|
},
|
|
@@ -14097,6 +14122,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14097
14122
|
],
|
|
14098
14123
|
compute: function (dataY, dataX) {
|
|
14099
14124
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14125
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14100
14126
|
const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
14101
14127
|
return slope;
|
|
14102
14128
|
},
|
|
@@ -14145,6 +14171,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14145
14171
|
],
|
|
14146
14172
|
compute: function (dataX, dataY) {
|
|
14147
14173
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14174
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14148
14175
|
const n = flatDataX.length;
|
|
14149
14176
|
const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
|
|
14150
14177
|
order.sort((a, b) => a[0] - b[0]);
|
|
@@ -14255,6 +14282,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14255
14282
|
],
|
|
14256
14283
|
compute: function (dataY, dataX) {
|
|
14257
14284
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14285
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14258
14286
|
const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
|
|
14259
14287
|
return data[1][2];
|
|
14260
14288
|
},
|
|
@@ -14272,6 +14300,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14272
14300
|
arg("b (boolean, optional, default=TRUE)", _t("Given a general linear form of y = m*x+b for a curve fit, calculates b if TRUE or forces b to be 0 and only calculates the m values if FALSE, i.e. forces the curve fit to pass through the origin.")),
|
|
14273
14301
|
],
|
|
14274
14302
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
14303
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
14275
14304
|
return predictLinearValues(toNumberMatrix(knownDataY, "the first argument (known_data_y)"), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b));
|
|
14276
14305
|
},
|
|
14277
14306
|
};
|
|
@@ -24478,9 +24507,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24478
24507
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
24479
24508
|
continue;
|
|
24480
24509
|
operator = convertCFCellIsOperator(rule.operator);
|
|
24481
|
-
values.push(rule.formula[0]);
|
|
24510
|
+
values.push(prefixFormula(rule.formula[0]));
|
|
24482
24511
|
if (rule.formula.length === 2) {
|
|
24483
|
-
values.push(rule.formula[1]);
|
|
24512
|
+
values.push(prefixFormula(rule.formula[1]));
|
|
24484
24513
|
}
|
|
24485
24514
|
break;
|
|
24486
24515
|
}
|
|
@@ -24638,6 +24667,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24638
24667
|
? ICON_SETS[iconSet].neutral
|
|
24639
24668
|
: ICON_SETS[iconSet].good;
|
|
24640
24669
|
}
|
|
24670
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
24671
|
+
function prefixFormula(formula) {
|
|
24672
|
+
const tokens = tokenize(formula);
|
|
24673
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
24674
|
+
}
|
|
24641
24675
|
// ---------------------------------------------------------------------------
|
|
24642
24676
|
// Warnings
|
|
24643
24677
|
// ---------------------------------------------------------------------------
|
|
@@ -30895,10 +30929,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30895
30929
|
};
|
|
30896
30930
|
}
|
|
30897
30931
|
getDefinitionForExcel() {
|
|
30898
|
-
// Excel does not support aggregating labels
|
|
30899
|
-
if (this.aggregated) {
|
|
30900
|
-
return undefined;
|
|
30901
|
-
}
|
|
30902
30932
|
const dataSets = this.dataSets
|
|
30903
30933
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
30904
30934
|
.filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
|
|
@@ -32050,10 +32080,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
32050
32080
|
return new ScatterChart(definition, this.sheetId, this.getters);
|
|
32051
32081
|
}
|
|
32052
32082
|
getDefinitionForExcel() {
|
|
32053
|
-
// Excel does not support aggregating labels
|
|
32054
|
-
if (this.aggregated) {
|
|
32055
|
-
return undefined;
|
|
32056
|
-
}
|
|
32057
32083
|
const dataSets = this.dataSets
|
|
32058
32084
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
32059
32085
|
.filter((ds) => ds.range !== "");
|
|
@@ -36170,7 +36196,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36170
36196
|
const reinsertDynamicPivotMenu = {
|
|
36171
36197
|
id: "reinsert_dynamic_pivot",
|
|
36172
36198
|
name: _t("Re-insert dynamic pivot"),
|
|
36173
|
-
sequence:
|
|
36199
|
+
sequence: 60,
|
|
36174
36200
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36175
36201
|
children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
|
|
36176
36202
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -36178,7 +36204,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36178
36204
|
const reinsertStaticPivotMenu = {
|
|
36179
36205
|
id: "reinsert_static_pivot",
|
|
36180
36206
|
name: _t("Re-insert static pivot"),
|
|
36181
|
-
sequence:
|
|
36207
|
+
sequence: 70,
|
|
36182
36208
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36183
36209
|
children: [REINSERT_STATIC_PIVOT_CHILDREN],
|
|
36184
36210
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -37916,8 +37942,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37916
37942
|
sequence: 40,
|
|
37917
37943
|
separator: true,
|
|
37918
37944
|
})
|
|
37919
|
-
.addChild("
|
|
37945
|
+
.addChild("pivot_data_sources", ["data"], (env) => {
|
|
37920
37946
|
const sequence = 50;
|
|
37947
|
+
const numberOfPivots = env.model.getters.getPivotIds().length;
|
|
37921
37948
|
return env.model.getters.getPivotIds().map((pivotId, index) => {
|
|
37922
37949
|
const highlightProvider = {
|
|
37923
37950
|
get highlights() {
|
|
@@ -37927,7 +37954,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37927
37954
|
return {
|
|
37928
37955
|
id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
|
|
37929
37956
|
name: env.model.getters.getPivotDisplayName(pivotId),
|
|
37930
|
-
sequence: sequence + index,
|
|
37957
|
+
sequence: sequence + index / numberOfPivots,
|
|
37931
37958
|
isReadonlyAllowed: true,
|
|
37932
37959
|
execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
|
|
37933
37960
|
onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
|
|
@@ -63899,7 +63926,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63899
63926
|
if (!result) {
|
|
63900
63927
|
return EMPTY_PIVOT_CELL;
|
|
63901
63928
|
}
|
|
63902
|
-
|
|
63929
|
+
let { functionName, args } = result;
|
|
63903
63930
|
const formulaId = args[0];
|
|
63904
63931
|
if (!formulaId) {
|
|
63905
63932
|
return EMPTY_PIVOT_CELL;
|
|
@@ -63929,6 +63956,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63929
63956
|
return pivotCells[pivotCol][pivotRow];
|
|
63930
63957
|
}
|
|
63931
63958
|
try {
|
|
63959
|
+
const offsetRow = position.row - mainPosition.row;
|
|
63960
|
+
const offsetCol = position.col - mainPosition.col;
|
|
63961
|
+
args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
|
|
63932
63962
|
if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
|
|
63933
63963
|
const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
|
|
63934
63964
|
return {
|
|
@@ -76549,7 +76579,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
76549
76579
|
handlers = [];
|
|
76550
76580
|
uiHandlers = [];
|
|
76551
76581
|
coreHandlers = [];
|
|
76552
|
-
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport =
|
|
76582
|
+
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
|
|
76553
76583
|
const start = performance.now();
|
|
76554
76584
|
console.debug("##### Model creation #####");
|
|
76555
76585
|
super();
|
|
@@ -77285,9 +77315,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
77285
77315
|
exports.tokenize = tokenize;
|
|
77286
77316
|
|
|
77287
77317
|
|
|
77288
|
-
__info__.version = "18.2.
|
|
77289
|
-
__info__.date = "2025-
|
|
77290
|
-
__info__.hash = "
|
|
77318
|
+
__info__.version = "18.2.28";
|
|
77319
|
+
__info__.date = "2025-09-05T07:38:26.582Z";
|
|
77320
|
+
__info__.hash = "84335fb";
|
|
77291
77321
|
|
|
77292
77322
|
|
|
77293
77323
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|