@odoo/o-spreadsheet 18.2.27 → 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 +57 -26
- package/dist/o-spreadsheet.d.ts +10 -10
- package/dist/o-spreadsheet.esm.js +57 -26
- package/dist/o-spreadsheet.iife.js +57 -26
- package/dist/o-spreadsheet.iife.min.js +388 -388
- package/dist/o_spreadsheet.xml +3 -3
- 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",
|
|
@@ -7526,8 +7527,11 @@ function invertMatrix(M) {
|
|
|
7526
7527
|
// (a) Swap 2 rows. This multiply the determinant by -1.
|
|
7527
7528
|
// (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
|
|
7528
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
|
+
}
|
|
7529
7533
|
if (M.length !== M[0].length) {
|
|
7530
|
-
throw new
|
|
7534
|
+
throw new Error("invertMatrix: only square matrices are invertible");
|
|
7531
7535
|
}
|
|
7532
7536
|
let determinant = 1;
|
|
7533
7537
|
const dim = M.length;
|
|
@@ -7596,8 +7600,11 @@ function swapMatrixRows(matrix, row1, row2) {
|
|
|
7596
7600
|
* Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
|
|
7597
7601
|
*/
|
|
7598
7602
|
function multiplyMatrices(matrix1, matrix2) {
|
|
7603
|
+
if (matrix1.length < 1 || matrix2.length < 1) {
|
|
7604
|
+
throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
|
|
7605
|
+
}
|
|
7599
7606
|
if (matrix1.length !== matrix2[0].length) {
|
|
7600
|
-
throw new
|
|
7607
|
+
throw new Error("multiplyMatrices: incompatible matrices size.");
|
|
7601
7608
|
}
|
|
7602
7609
|
const rowsM1 = matrix1[0].length;
|
|
7603
7610
|
const colsM2 = matrix2.length;
|
|
@@ -7623,7 +7630,7 @@ function toScalar(arg) {
|
|
|
7623
7630
|
return arg;
|
|
7624
7631
|
}
|
|
7625
7632
|
if (!isSingleElementMatrix(arg)) {
|
|
7626
|
-
throw new
|
|
7633
|
+
throw new Error("The value should be a scalar or a 1x1 matrix");
|
|
7627
7634
|
}
|
|
7628
7635
|
return arg[0][0];
|
|
7629
7636
|
}
|
|
@@ -7860,6 +7867,16 @@ function getMovingAverageValues(dataset, labels, windowSize = DEFAULT_WINDOW_SIZ
|
|
|
7860
7867
|
}
|
|
7861
7868
|
return values;
|
|
7862
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
|
+
}
|
|
7863
7880
|
|
|
7864
7881
|
const PREVIOUS_VALUE = "(previous)";
|
|
7865
7882
|
const NEXT_VALUE = "(next)";
|
|
@@ -11797,6 +11814,7 @@ const MMULT = {
|
|
|
11797
11814
|
compute: function (matrix1, matrix2) {
|
|
11798
11815
|
const _matrix1 = toNumberMatrix(matrix1, "matrix1");
|
|
11799
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."));
|
|
11800
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 \
|
|
11801
11819
|
number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
|
|
11802
11820
|
return multiplyMatrices(_matrix1, _matrix2);
|
|
@@ -13592,6 +13610,7 @@ const FORECAST = {
|
|
|
13592
13610
|
],
|
|
13593
13611
|
compute: function (x, dataY, dataX) {
|
|
13594
13612
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13613
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13595
13614
|
return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
|
|
13596
13615
|
},
|
|
13597
13616
|
isExported: true,
|
|
@@ -13608,6 +13627,7 @@ const GROWTH = {
|
|
|
13608
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.")),
|
|
13609
13628
|
],
|
|
13610
13629
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
13630
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
13611
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)));
|
|
13612
13632
|
},
|
|
13613
13633
|
};
|
|
@@ -13622,6 +13642,7 @@ const INTERCEPT = {
|
|
|
13622
13642
|
],
|
|
13623
13643
|
compute: function (dataY, dataX) {
|
|
13624
13644
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13645
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13625
13646
|
const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
13626
13647
|
return intercept;
|
|
13627
13648
|
},
|
|
@@ -13671,6 +13692,7 @@ const LINEST = {
|
|
|
13671
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")),
|
|
13672
13693
|
],
|
|
13673
13694
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13695
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13674
13696
|
return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
|
|
13675
13697
|
},
|
|
13676
13698
|
isExported: true,
|
|
@@ -13687,6 +13709,7 @@ const LOGEST = {
|
|
|
13687
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")),
|
|
13688
13710
|
],
|
|
13689
13711
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13712
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13690
13713
|
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
|
|
13691
13714
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13692
13715
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
@@ -13708,9 +13731,7 @@ const MATTHEWS = {
|
|
|
13708
13731
|
const flatX = dataX.flat();
|
|
13709
13732
|
const flatY = dataY.flat();
|
|
13710
13733
|
assertSameNumberOfElements(flatX, flatY);
|
|
13711
|
-
|
|
13712
|
-
return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13713
|
-
}
|
|
13734
|
+
assertNonEmpty(flatX, flatY);
|
|
13714
13735
|
const n = flatX.length;
|
|
13715
13736
|
let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
|
|
13716
13737
|
for (let i = 0; i < n; ++i) {
|
|
@@ -13874,12 +13895,7 @@ const MINIFS = {
|
|
|
13874
13895
|
// -----------------------------------------------------------------------------
|
|
13875
13896
|
function pearson(dataY, dataX) {
|
|
13876
13897
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13877
|
-
|
|
13878
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13879
|
-
}
|
|
13880
|
-
if (flatDataX.length < 2) {
|
|
13881
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
|
|
13882
|
-
}
|
|
13898
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13883
13899
|
const n = flatDataX.length;
|
|
13884
13900
|
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
|
|
13885
13901
|
for (let i = 0; i < n; i++) {
|
|
@@ -13968,6 +13984,7 @@ const POLYFIT_COEFFS = {
|
|
|
13968
13984
|
],
|
|
13969
13985
|
compute: function (dataY, dataX, order, intercept = { value: true }) {
|
|
13970
13986
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13987
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13971
13988
|
return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
|
|
13972
13989
|
},
|
|
13973
13990
|
isExported: false,
|
|
@@ -13987,6 +14004,7 @@ const POLYFIT_FORECAST = {
|
|
|
13987
14004
|
compute: function (x, dataY, dataX, order, intercept = { value: true }) {
|
|
13988
14005
|
const _order = toNumber(order, this.locale);
|
|
13989
14006
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14007
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13990
14008
|
const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
|
|
13991
14009
|
return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
|
|
13992
14010
|
},
|
|
@@ -14103,6 +14121,7 @@ const SLOPE = {
|
|
|
14103
14121
|
],
|
|
14104
14122
|
compute: function (dataY, dataX) {
|
|
14105
14123
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14124
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14106
14125
|
const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
14107
14126
|
return slope;
|
|
14108
14127
|
},
|
|
@@ -14151,6 +14170,7 @@ const SPEARMAN = {
|
|
|
14151
14170
|
],
|
|
14152
14171
|
compute: function (dataX, dataY) {
|
|
14153
14172
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14173
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14154
14174
|
const n = flatDataX.length;
|
|
14155
14175
|
const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
|
|
14156
14176
|
order.sort((a, b) => a[0] - b[0]);
|
|
@@ -14261,6 +14281,7 @@ const STEYX = {
|
|
|
14261
14281
|
],
|
|
14262
14282
|
compute: function (dataY, dataX) {
|
|
14263
14283
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14284
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14264
14285
|
const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
|
|
14265
14286
|
return data[1][2];
|
|
14266
14287
|
},
|
|
@@ -14278,6 +14299,7 @@ const TREND = {
|
|
|
14278
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.")),
|
|
14279
14300
|
],
|
|
14280
14301
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
14302
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
14281
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));
|
|
14282
14304
|
},
|
|
14283
14305
|
};
|
|
@@ -24484,9 +24506,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
24484
24506
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
24485
24507
|
continue;
|
|
24486
24508
|
operator = convertCFCellIsOperator(rule.operator);
|
|
24487
|
-
values.push(rule.formula[0]);
|
|
24509
|
+
values.push(prefixFormula(rule.formula[0]));
|
|
24488
24510
|
if (rule.formula.length === 2) {
|
|
24489
|
-
values.push(rule.formula[1]);
|
|
24511
|
+
values.push(prefixFormula(rule.formula[1]));
|
|
24490
24512
|
}
|
|
24491
24513
|
break;
|
|
24492
24514
|
}
|
|
@@ -24644,6 +24666,11 @@ function convertIcons(xlsxIconSet, index) {
|
|
|
24644
24666
|
? ICON_SETS[iconSet].neutral
|
|
24645
24667
|
: ICON_SETS[iconSet].good;
|
|
24646
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
|
+
}
|
|
24647
24674
|
// ---------------------------------------------------------------------------
|
|
24648
24675
|
// Warnings
|
|
24649
24676
|
// ---------------------------------------------------------------------------
|
|
@@ -36168,7 +36195,7 @@ const splitToColumns = {
|
|
|
36168
36195
|
const reinsertDynamicPivotMenu = {
|
|
36169
36196
|
id: "reinsert_dynamic_pivot",
|
|
36170
36197
|
name: _t("Re-insert dynamic pivot"),
|
|
36171
|
-
sequence:
|
|
36198
|
+
sequence: 60,
|
|
36172
36199
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36173
36200
|
children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
|
|
36174
36201
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -36176,7 +36203,7 @@ const reinsertDynamicPivotMenu = {
|
|
|
36176
36203
|
const reinsertStaticPivotMenu = {
|
|
36177
36204
|
id: "reinsert_static_pivot",
|
|
36178
36205
|
name: _t("Re-insert static pivot"),
|
|
36179
|
-
sequence:
|
|
36206
|
+
sequence: 70,
|
|
36180
36207
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36181
36208
|
children: [REINSERT_STATIC_PIVOT_CHILDREN],
|
|
36182
36209
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -37914,8 +37941,9 @@ topbarMenuRegistry
|
|
|
37914
37941
|
sequence: 40,
|
|
37915
37942
|
separator: true,
|
|
37916
37943
|
})
|
|
37917
|
-
.addChild("
|
|
37944
|
+
.addChild("pivot_data_sources", ["data"], (env) => {
|
|
37918
37945
|
const sequence = 50;
|
|
37946
|
+
const numberOfPivots = env.model.getters.getPivotIds().length;
|
|
37919
37947
|
return env.model.getters.getPivotIds().map((pivotId, index) => {
|
|
37920
37948
|
const highlightProvider = {
|
|
37921
37949
|
get highlights() {
|
|
@@ -37925,7 +37953,7 @@ topbarMenuRegistry
|
|
|
37925
37953
|
return {
|
|
37926
37954
|
id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
|
|
37927
37955
|
name: env.model.getters.getPivotDisplayName(pivotId),
|
|
37928
|
-
sequence: sequence + index,
|
|
37956
|
+
sequence: sequence + index / numberOfPivots,
|
|
37929
37957
|
isReadonlyAllowed: true,
|
|
37930
37958
|
execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
|
|
37931
37959
|
onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
|
|
@@ -63897,7 +63925,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
63897
63925
|
if (!result) {
|
|
63898
63926
|
return EMPTY_PIVOT_CELL;
|
|
63899
63927
|
}
|
|
63900
|
-
|
|
63928
|
+
let { functionName, args } = result;
|
|
63901
63929
|
const formulaId = args[0];
|
|
63902
63930
|
if (!formulaId) {
|
|
63903
63931
|
return EMPTY_PIVOT_CELL;
|
|
@@ -63927,6 +63955,9 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
63927
63955
|
return pivotCells[pivotCol][pivotRow];
|
|
63928
63956
|
}
|
|
63929
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));
|
|
63930
63961
|
if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
|
|
63931
63962
|
const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
|
|
63932
63963
|
return {
|
|
@@ -76547,7 +76578,7 @@ class Model extends EventBus {
|
|
|
76547
76578
|
handlers = [];
|
|
76548
76579
|
uiHandlers = [];
|
|
76549
76580
|
coreHandlers = [];
|
|
76550
|
-
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport =
|
|
76581
|
+
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
|
|
76551
76582
|
const start = performance.now();
|
|
76552
76583
|
console.debug("##### Model creation #####");
|
|
76553
76584
|
super();
|
|
@@ -77238,6 +77269,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
77238
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 };
|
|
77239
77270
|
|
|
77240
77271
|
|
|
77241
|
-
__info__.version = "18.2.
|
|
77242
|
-
__info__.date = "2025-
|
|
77243
|
-
__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",
|
|
@@ -7527,8 +7528,11 @@
|
|
|
7527
7528
|
// (a) Swap 2 rows. This multiply the determinant by -1.
|
|
7528
7529
|
// (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
|
|
7529
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
|
+
}
|
|
7530
7534
|
if (M.length !== M[0].length) {
|
|
7531
|
-
throw new
|
|
7535
|
+
throw new Error("invertMatrix: only square matrices are invertible");
|
|
7532
7536
|
}
|
|
7533
7537
|
let determinant = 1;
|
|
7534
7538
|
const dim = M.length;
|
|
@@ -7597,8 +7601,11 @@
|
|
|
7597
7601
|
* Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
|
|
7598
7602
|
*/
|
|
7599
7603
|
function multiplyMatrices(matrix1, matrix2) {
|
|
7604
|
+
if (matrix1.length < 1 || matrix2.length < 1) {
|
|
7605
|
+
throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
|
|
7606
|
+
}
|
|
7600
7607
|
if (matrix1.length !== matrix2[0].length) {
|
|
7601
|
-
throw new
|
|
7608
|
+
throw new Error("multiplyMatrices: incompatible matrices size.");
|
|
7602
7609
|
}
|
|
7603
7610
|
const rowsM1 = matrix1[0].length;
|
|
7604
7611
|
const colsM2 = matrix2.length;
|
|
@@ -7624,7 +7631,7 @@
|
|
|
7624
7631
|
return arg;
|
|
7625
7632
|
}
|
|
7626
7633
|
if (!isSingleElementMatrix(arg)) {
|
|
7627
|
-
throw new
|
|
7634
|
+
throw new Error("The value should be a scalar or a 1x1 matrix");
|
|
7628
7635
|
}
|
|
7629
7636
|
return arg[0][0];
|
|
7630
7637
|
}
|
|
@@ -7861,6 +7868,16 @@
|
|
|
7861
7868
|
}
|
|
7862
7869
|
return values;
|
|
7863
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
|
+
}
|
|
7864
7881
|
|
|
7865
7882
|
const PREVIOUS_VALUE = "(previous)";
|
|
7866
7883
|
const NEXT_VALUE = "(next)";
|
|
@@ -11798,6 +11815,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
11798
11815
|
compute: function (matrix1, matrix2) {
|
|
11799
11816
|
const _matrix1 = toNumberMatrix(matrix1, "matrix1");
|
|
11800
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."));
|
|
11801
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 \
|
|
11802
11820
|
number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
|
|
11803
11821
|
return multiplyMatrices(_matrix1, _matrix2);
|
|
@@ -13593,6 +13611,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13593
13611
|
],
|
|
13594
13612
|
compute: function (x, dataY, dataX) {
|
|
13595
13613
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13614
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13596
13615
|
return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
|
|
13597
13616
|
},
|
|
13598
13617
|
isExported: true,
|
|
@@ -13609,6 +13628,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13609
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.")),
|
|
13610
13629
|
],
|
|
13611
13630
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
13631
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
13612
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)));
|
|
13613
13633
|
},
|
|
13614
13634
|
};
|
|
@@ -13623,6 +13643,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13623
13643
|
],
|
|
13624
13644
|
compute: function (dataY, dataX) {
|
|
13625
13645
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13646
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13626
13647
|
const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
13627
13648
|
return intercept;
|
|
13628
13649
|
},
|
|
@@ -13672,6 +13693,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13672
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")),
|
|
13673
13694
|
],
|
|
13674
13695
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13696
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13675
13697
|
return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
|
|
13676
13698
|
},
|
|
13677
13699
|
isExported: true,
|
|
@@ -13688,6 +13710,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13688
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")),
|
|
13689
13711
|
],
|
|
13690
13712
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13713
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13691
13714
|
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
|
|
13692
13715
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13693
13716
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
@@ -13709,9 +13732,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13709
13732
|
const flatX = dataX.flat();
|
|
13710
13733
|
const flatY = dataY.flat();
|
|
13711
13734
|
assertSameNumberOfElements(flatX, flatY);
|
|
13712
|
-
|
|
13713
|
-
return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13714
|
-
}
|
|
13735
|
+
assertNonEmpty(flatX, flatY);
|
|
13715
13736
|
const n = flatX.length;
|
|
13716
13737
|
let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
|
|
13717
13738
|
for (let i = 0; i < n; ++i) {
|
|
@@ -13875,12 +13896,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13875
13896
|
// -----------------------------------------------------------------------------
|
|
13876
13897
|
function pearson(dataY, dataX) {
|
|
13877
13898
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13878
|
-
|
|
13879
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13880
|
-
}
|
|
13881
|
-
if (flatDataX.length < 2) {
|
|
13882
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
|
|
13883
|
-
}
|
|
13899
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13884
13900
|
const n = flatDataX.length;
|
|
13885
13901
|
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
|
|
13886
13902
|
for (let i = 0; i < n; i++) {
|
|
@@ -13969,6 +13985,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13969
13985
|
],
|
|
13970
13986
|
compute: function (dataY, dataX, order, intercept = { value: true }) {
|
|
13971
13987
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13988
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13972
13989
|
return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
|
|
13973
13990
|
},
|
|
13974
13991
|
isExported: false,
|
|
@@ -13988,6 +14005,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13988
14005
|
compute: function (x, dataY, dataX, order, intercept = { value: true }) {
|
|
13989
14006
|
const _order = toNumber(order, this.locale);
|
|
13990
14007
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14008
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13991
14009
|
const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
|
|
13992
14010
|
return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
|
|
13993
14011
|
},
|
|
@@ -14104,6 +14122,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14104
14122
|
],
|
|
14105
14123
|
compute: function (dataY, dataX) {
|
|
14106
14124
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14125
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14107
14126
|
const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
14108
14127
|
return slope;
|
|
14109
14128
|
},
|
|
@@ -14152,6 +14171,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14152
14171
|
],
|
|
14153
14172
|
compute: function (dataX, dataY) {
|
|
14154
14173
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14174
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14155
14175
|
const n = flatDataX.length;
|
|
14156
14176
|
const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
|
|
14157
14177
|
order.sort((a, b) => a[0] - b[0]);
|
|
@@ -14262,6 +14282,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14262
14282
|
],
|
|
14263
14283
|
compute: function (dataY, dataX) {
|
|
14264
14284
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14285
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14265
14286
|
const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
|
|
14266
14287
|
return data[1][2];
|
|
14267
14288
|
},
|
|
@@ -14279,6 +14300,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14279
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.")),
|
|
14280
14301
|
],
|
|
14281
14302
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
14303
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
14282
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));
|
|
14283
14305
|
},
|
|
14284
14306
|
};
|
|
@@ -24485,9 +24507,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24485
24507
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
24486
24508
|
continue;
|
|
24487
24509
|
operator = convertCFCellIsOperator(rule.operator);
|
|
24488
|
-
values.push(rule.formula[0]);
|
|
24510
|
+
values.push(prefixFormula(rule.formula[0]));
|
|
24489
24511
|
if (rule.formula.length === 2) {
|
|
24490
|
-
values.push(rule.formula[1]);
|
|
24512
|
+
values.push(prefixFormula(rule.formula[1]));
|
|
24491
24513
|
}
|
|
24492
24514
|
break;
|
|
24493
24515
|
}
|
|
@@ -24645,6 +24667,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24645
24667
|
? ICON_SETS[iconSet].neutral
|
|
24646
24668
|
: ICON_SETS[iconSet].good;
|
|
24647
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
|
+
}
|
|
24648
24675
|
// ---------------------------------------------------------------------------
|
|
24649
24676
|
// Warnings
|
|
24650
24677
|
// ---------------------------------------------------------------------------
|
|
@@ -36169,7 +36196,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36169
36196
|
const reinsertDynamicPivotMenu = {
|
|
36170
36197
|
id: "reinsert_dynamic_pivot",
|
|
36171
36198
|
name: _t("Re-insert dynamic pivot"),
|
|
36172
|
-
sequence:
|
|
36199
|
+
sequence: 60,
|
|
36173
36200
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36174
36201
|
children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
|
|
36175
36202
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -36177,7 +36204,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36177
36204
|
const reinsertStaticPivotMenu = {
|
|
36178
36205
|
id: "reinsert_static_pivot",
|
|
36179
36206
|
name: _t("Re-insert static pivot"),
|
|
36180
|
-
sequence:
|
|
36207
|
+
sequence: 70,
|
|
36181
36208
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36182
36209
|
children: [REINSERT_STATIC_PIVOT_CHILDREN],
|
|
36183
36210
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -37915,8 +37942,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37915
37942
|
sequence: 40,
|
|
37916
37943
|
separator: true,
|
|
37917
37944
|
})
|
|
37918
|
-
.addChild("
|
|
37945
|
+
.addChild("pivot_data_sources", ["data"], (env) => {
|
|
37919
37946
|
const sequence = 50;
|
|
37947
|
+
const numberOfPivots = env.model.getters.getPivotIds().length;
|
|
37920
37948
|
return env.model.getters.getPivotIds().map((pivotId, index) => {
|
|
37921
37949
|
const highlightProvider = {
|
|
37922
37950
|
get highlights() {
|
|
@@ -37926,7 +37954,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37926
37954
|
return {
|
|
37927
37955
|
id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
|
|
37928
37956
|
name: env.model.getters.getPivotDisplayName(pivotId),
|
|
37929
|
-
sequence: sequence + index,
|
|
37957
|
+
sequence: sequence + index / numberOfPivots,
|
|
37930
37958
|
isReadonlyAllowed: true,
|
|
37931
37959
|
execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
|
|
37932
37960
|
onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
|
|
@@ -63898,7 +63926,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63898
63926
|
if (!result) {
|
|
63899
63927
|
return EMPTY_PIVOT_CELL;
|
|
63900
63928
|
}
|
|
63901
|
-
|
|
63929
|
+
let { functionName, args } = result;
|
|
63902
63930
|
const formulaId = args[0];
|
|
63903
63931
|
if (!formulaId) {
|
|
63904
63932
|
return EMPTY_PIVOT_CELL;
|
|
@@ -63928,6 +63956,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63928
63956
|
return pivotCells[pivotCol][pivotRow];
|
|
63929
63957
|
}
|
|
63930
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));
|
|
63931
63962
|
if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
|
|
63932
63963
|
const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
|
|
63933
63964
|
return {
|
|
@@ -76548,7 +76579,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
76548
76579
|
handlers = [];
|
|
76549
76580
|
uiHandlers = [];
|
|
76550
76581
|
coreHandlers = [];
|
|
76551
|
-
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport =
|
|
76582
|
+
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
|
|
76552
76583
|
const start = performance.now();
|
|
76553
76584
|
console.debug("##### Model creation #####");
|
|
76554
76585
|
super();
|
|
@@ -77284,9 +77315,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
77284
77315
|
exports.tokenize = tokenize;
|
|
77285
77316
|
|
|
77286
77317
|
|
|
77287
|
-
__info__.version = "18.2.
|
|
77288
|
-
__info__.date = "2025-
|
|
77289
|
-
__info__.hash = "
|
|
77318
|
+
__info__.version = "18.2.28";
|
|
77319
|
+
__info__.date = "2025-09-05T07:38:26.582Z";
|
|
77320
|
+
__info__.hash = "84335fb";
|
|
77290
77321
|
|
|
77291
77322
|
|
|
77292
77323
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|