@odoo/o-spreadsheet 18.2.27 → 18.2.29
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 +107 -58
- package/dist/o-spreadsheet.d.ts +14 -13
- package/dist/o-spreadsheet.esm.js +107 -58
- package/dist/o-spreadsheet.iife.js +107 -58
- package/dist/o-spreadsheet.iife.min.js +388 -388
- package/dist/o_spreadsheet.xml +4 -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.29
|
|
6
|
+
* @date 2025-09-11T08:44:31.801Z
|
|
7
|
+
* @hash 665bc43
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -3478,6 +3478,7 @@ const invalidateBordersCommands = new Set([
|
|
|
3478
3478
|
"AUTOFILL_CELL",
|
|
3479
3479
|
"SET_BORDER",
|
|
3480
3480
|
"SET_ZONE_BORDERS",
|
|
3481
|
+
"SET_BORDERS_ON_TARGET",
|
|
3481
3482
|
]);
|
|
3482
3483
|
const readonlyAllowedCommands = new Set([
|
|
3483
3484
|
"START",
|
|
@@ -6904,7 +6905,7 @@ class ClipboardHandler {
|
|
|
6904
6905
|
this.getters = getters;
|
|
6905
6906
|
this.dispatch = dispatch;
|
|
6906
6907
|
}
|
|
6907
|
-
copy(data) {
|
|
6908
|
+
copy(data, mode = "copyPaste") {
|
|
6908
6909
|
return;
|
|
6909
6910
|
}
|
|
6910
6911
|
paste(target, clippedContent, options) { }
|
|
@@ -6923,7 +6924,7 @@ class ClipboardHandler {
|
|
|
6923
6924
|
}
|
|
6924
6925
|
|
|
6925
6926
|
class AbstractCellClipboardHandler extends ClipboardHandler {
|
|
6926
|
-
copy(data) {
|
|
6927
|
+
copy(data, mode = "copyPaste") {
|
|
6927
6928
|
return;
|
|
6928
6929
|
}
|
|
6929
6930
|
pasteFromCopy(sheetId, target, content, options) {
|
|
@@ -7528,8 +7529,11 @@ function invertMatrix(M) {
|
|
|
7528
7529
|
// (a) Swap 2 rows. This multiply the determinant by -1.
|
|
7529
7530
|
// (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
|
|
7530
7531
|
// (c) Add to a row a multiple of another row. This does not change the determinant.
|
|
7532
|
+
if (M.length < 1 || M[0].length < 1) {
|
|
7533
|
+
throw new Error("invertMatrix: an empty matrix cannot be inverted.");
|
|
7534
|
+
}
|
|
7531
7535
|
if (M.length !== M[0].length) {
|
|
7532
|
-
throw new
|
|
7536
|
+
throw new Error("invertMatrix: only square matrices are invertible");
|
|
7533
7537
|
}
|
|
7534
7538
|
let determinant = 1;
|
|
7535
7539
|
const dim = M.length;
|
|
@@ -7598,8 +7602,11 @@ function swapMatrixRows(matrix, row1, row2) {
|
|
|
7598
7602
|
* Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
|
|
7599
7603
|
*/
|
|
7600
7604
|
function multiplyMatrices(matrix1, matrix2) {
|
|
7605
|
+
if (matrix1.length < 1 || matrix2.length < 1) {
|
|
7606
|
+
throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
|
|
7607
|
+
}
|
|
7601
7608
|
if (matrix1.length !== matrix2[0].length) {
|
|
7602
|
-
throw new
|
|
7609
|
+
throw new Error("multiplyMatrices: incompatible matrices size.");
|
|
7603
7610
|
}
|
|
7604
7611
|
const rowsM1 = matrix1[0].length;
|
|
7605
7612
|
const colsM2 = matrix2.length;
|
|
@@ -7625,7 +7632,7 @@ function toScalar(arg) {
|
|
|
7625
7632
|
return arg;
|
|
7626
7633
|
}
|
|
7627
7634
|
if (!isSingleElementMatrix(arg)) {
|
|
7628
|
-
throw new
|
|
7635
|
+
throw new Error("The value should be a scalar or a 1x1 matrix");
|
|
7629
7636
|
}
|
|
7630
7637
|
return arg[0][0];
|
|
7631
7638
|
}
|
|
@@ -7862,6 +7869,16 @@ function getMovingAverageValues(dataset, labels, windowSize = DEFAULT_WINDOW_SIZ
|
|
|
7862
7869
|
}
|
|
7863
7870
|
return values;
|
|
7864
7871
|
}
|
|
7872
|
+
function assertNonEmptyMatrix(matrix, argName) {
|
|
7873
|
+
assert(() => matrix.length > 0 && matrix[0].length > 0, _t("[[FUNCTION_NAME]] expects the provided values of %(argName)s to be a non-empty matrix.", {
|
|
7874
|
+
argName,
|
|
7875
|
+
}));
|
|
7876
|
+
}
|
|
7877
|
+
function assertNonEmpty(...data) {
|
|
7878
|
+
if (data.length === 0 || data.some((arg) => arg.length === 0)) {
|
|
7879
|
+
throw new NotAvailableError(_t("[[FUNCTION_NAME]] has no valid input data."));
|
|
7880
|
+
}
|
|
7881
|
+
}
|
|
7865
7882
|
|
|
7866
7883
|
const PREVIOUS_VALUE = "(previous)";
|
|
7867
7884
|
const NEXT_VALUE = "(next)";
|
|
@@ -8624,7 +8641,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8624
8641
|
}
|
|
8625
8642
|
return "Success" /* CommandResult.Success */;
|
|
8626
8643
|
}
|
|
8627
|
-
copy(data) {
|
|
8644
|
+
copy(data, mode = "copyPaste") {
|
|
8628
8645
|
const sheetId = data.sheetId;
|
|
8629
8646
|
const { clippedZones, rowsIndexes, columnsIndexes } = data;
|
|
8630
8647
|
const clippedCells = [];
|
|
@@ -8637,7 +8654,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8637
8654
|
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
8638
8655
|
const pivotId = this.getters.getPivotIdFromPosition(position);
|
|
8639
8656
|
const spreader = this.getters.getArrayFormulaSpreadingOn(position);
|
|
8640
|
-
if (pivotId && spreader) {
|
|
8657
|
+
if (mode !== "shiftCells" && pivotId && spreader) {
|
|
8641
8658
|
const pivotZone = this.getters.getSpreadZone(spreader);
|
|
8642
8659
|
if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
|
|
8643
8660
|
pivotZone &&
|
|
@@ -8655,7 +8672,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8655
8672
|
};
|
|
8656
8673
|
}
|
|
8657
8674
|
}
|
|
8658
|
-
else {
|
|
8675
|
+
else if (mode !== "shiftCells") {
|
|
8659
8676
|
if (spreader && !deepEquals(spreader, position)) {
|
|
8660
8677
|
const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
|
|
8661
8678
|
const content = isSpreaderCopied
|
|
@@ -9348,7 +9365,7 @@ class SheetClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
9348
9365
|
}
|
|
9349
9366
|
|
|
9350
9367
|
class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
9351
|
-
copy(data) {
|
|
9368
|
+
copy(data, mode = "copyPaste") {
|
|
9352
9369
|
const sheetId = data.sheetId;
|
|
9353
9370
|
const { rowsIndexes, columnsIndexes, zones } = data;
|
|
9354
9371
|
const copiedTablesIds = new Set();
|
|
@@ -9378,11 +9395,13 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
9378
9395
|
type: coreTable.type,
|
|
9379
9396
|
};
|
|
9380
9397
|
}
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9398
|
+
if (mode !== "shiftCells") {
|
|
9399
|
+
tableCellsInRow.push({
|
|
9400
|
+
table: copiedTable,
|
|
9401
|
+
style: this.getTableStyleToCopy(position),
|
|
9402
|
+
isWholeTableCopied: copiedTablesIds.has(table.id),
|
|
9403
|
+
});
|
|
9404
|
+
}
|
|
9386
9405
|
}
|
|
9387
9406
|
}
|
|
9388
9407
|
return {
|
|
@@ -11799,6 +11818,7 @@ const MMULT = {
|
|
|
11799
11818
|
compute: function (matrix1, matrix2) {
|
|
11800
11819
|
const _matrix1 = toNumberMatrix(matrix1, "matrix1");
|
|
11801
11820
|
const _matrix2 = toNumberMatrix(matrix2, "matrix2");
|
|
11821
|
+
assert(() => _matrix1.length > 0 && _matrix2.length > 0, _t("The first and second arguments of [[FUNCTION_NAME]] must be non-empty matrices."));
|
|
11802
11822
|
assert(() => _matrix1.length === _matrix2[0].length, _t("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
|
|
11803
11823
|
number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
|
|
11804
11824
|
return multiplyMatrices(_matrix1, _matrix2);
|
|
@@ -13594,6 +13614,7 @@ const FORECAST = {
|
|
|
13594
13614
|
],
|
|
13595
13615
|
compute: function (x, dataY, dataX) {
|
|
13596
13616
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13617
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13597
13618
|
return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
|
|
13598
13619
|
},
|
|
13599
13620
|
isExported: true,
|
|
@@ -13610,6 +13631,7 @@ const GROWTH = {
|
|
|
13610
13631
|
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.")),
|
|
13611
13632
|
],
|
|
13612
13633
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
13634
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
13613
13635
|
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)));
|
|
13614
13636
|
},
|
|
13615
13637
|
};
|
|
@@ -13624,6 +13646,7 @@ const INTERCEPT = {
|
|
|
13624
13646
|
],
|
|
13625
13647
|
compute: function (dataY, dataX) {
|
|
13626
13648
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13649
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13627
13650
|
const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
13628
13651
|
return intercept;
|
|
13629
13652
|
},
|
|
@@ -13673,6 +13696,7 @@ const LINEST = {
|
|
|
13673
13696
|
arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
|
|
13674
13697
|
],
|
|
13675
13698
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13699
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13676
13700
|
return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
|
|
13677
13701
|
},
|
|
13678
13702
|
isExported: true,
|
|
@@ -13689,6 +13713,7 @@ const LOGEST = {
|
|
|
13689
13713
|
arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
|
|
13690
13714
|
],
|
|
13691
13715
|
compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
|
|
13716
|
+
assertNonEmptyMatrix(dataY, "data_y");
|
|
13692
13717
|
const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
|
|
13693
13718
|
for (let i = 0; i < coeffs.length; i++) {
|
|
13694
13719
|
coeffs[i][0] = Math.exp(coeffs[i][0]);
|
|
@@ -13710,9 +13735,7 @@ const MATTHEWS = {
|
|
|
13710
13735
|
const flatX = dataX.flat();
|
|
13711
13736
|
const flatY = dataY.flat();
|
|
13712
13737
|
assertSameNumberOfElements(flatX, flatY);
|
|
13713
|
-
|
|
13714
|
-
return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13715
|
-
}
|
|
13738
|
+
assertNonEmpty(flatX, flatY);
|
|
13716
13739
|
const n = flatX.length;
|
|
13717
13740
|
let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
|
|
13718
13741
|
for (let i = 0; i < n; ++i) {
|
|
@@ -13876,12 +13899,7 @@ const MINIFS = {
|
|
|
13876
13899
|
// -----------------------------------------------------------------------------
|
|
13877
13900
|
function pearson(dataY, dataX) {
|
|
13878
13901
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13879
|
-
|
|
13880
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
13881
|
-
}
|
|
13882
|
-
if (flatDataX.length < 2) {
|
|
13883
|
-
throw new EvaluationError(_t("[[FUNCTION_NAME]] needs at least two values for both parameters."));
|
|
13884
|
-
}
|
|
13902
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13885
13903
|
const n = flatDataX.length;
|
|
13886
13904
|
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
|
|
13887
13905
|
for (let i = 0; i < n; i++) {
|
|
@@ -13970,6 +13988,7 @@ const POLYFIT_COEFFS = {
|
|
|
13970
13988
|
],
|
|
13971
13989
|
compute: function (dataY, dataX, order, intercept = { value: true }) {
|
|
13972
13990
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
13991
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13973
13992
|
return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
|
|
13974
13993
|
},
|
|
13975
13994
|
isExported: false,
|
|
@@ -13989,6 +14008,7 @@ const POLYFIT_FORECAST = {
|
|
|
13989
14008
|
compute: function (x, dataY, dataX, order, intercept = { value: true }) {
|
|
13990
14009
|
const _order = toNumber(order, this.locale);
|
|
13991
14010
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14011
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
13992
14012
|
const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
|
|
13993
14013
|
return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
|
|
13994
14014
|
},
|
|
@@ -14105,6 +14125,7 @@ const SLOPE = {
|
|
|
14105
14125
|
],
|
|
14106
14126
|
compute: function (dataY, dataX) {
|
|
14107
14127
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14128
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14108
14129
|
const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
|
|
14109
14130
|
return slope;
|
|
14110
14131
|
},
|
|
@@ -14153,6 +14174,7 @@ const SPEARMAN = {
|
|
|
14153
14174
|
],
|
|
14154
14175
|
compute: function (dataX, dataY) {
|
|
14155
14176
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14177
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14156
14178
|
const n = flatDataX.length;
|
|
14157
14179
|
const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
|
|
14158
14180
|
order.sort((a, b) => a[0] - b[0]);
|
|
@@ -14263,6 +14285,7 @@ const STEYX = {
|
|
|
14263
14285
|
],
|
|
14264
14286
|
compute: function (dataY, dataX) {
|
|
14265
14287
|
const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
|
|
14288
|
+
assertNonEmpty(flatDataX, flatDataY);
|
|
14266
14289
|
const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
|
|
14267
14290
|
return data[1][2];
|
|
14268
14291
|
},
|
|
@@ -14280,6 +14303,7 @@ const TREND = {
|
|
|
14280
14303
|
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.")),
|
|
14281
14304
|
],
|
|
14282
14305
|
compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
|
|
14306
|
+
assertNonEmptyMatrix(knownDataY, "known_data_y");
|
|
14283
14307
|
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));
|
|
14284
14308
|
},
|
|
14285
14309
|
};
|
|
@@ -23773,7 +23797,7 @@ const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
|
|
|
23773
23797
|
];
|
|
23774
23798
|
const SUPPORTED_VERTICAL_ALIGNMENTS = ["top", "center", "bottom"];
|
|
23775
23799
|
const SUPPORTED_FONTS = ["Arial"];
|
|
23776
|
-
const SUPPORTED_FILL_PATTERNS = ["solid"];
|
|
23800
|
+
const SUPPORTED_FILL_PATTERNS = ["solid", "none"];
|
|
23777
23801
|
const SUPPORTED_CF_TYPES = [
|
|
23778
23802
|
"expression",
|
|
23779
23803
|
"cellIs",
|
|
@@ -23958,7 +23982,7 @@ const SUBTOTAL_FUNCTION_CONVERSION_MAP = {
|
|
|
23958
23982
|
};
|
|
23959
23983
|
/** Mapping between Excel format indexes (see XLSX_FORMAT_MAP) and some supported formats */
|
|
23960
23984
|
const XLSX_FORMATS_CONVERSION_MAP = {
|
|
23961
|
-
0: "",
|
|
23985
|
+
0: "General",
|
|
23962
23986
|
1: "0",
|
|
23963
23987
|
2: "0.00",
|
|
23964
23988
|
3: "#,#00",
|
|
@@ -24284,11 +24308,11 @@ const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/
|
|
|
24284
24308
|
* Excel format are defined in openXML §18.8.31
|
|
24285
24309
|
*/
|
|
24286
24310
|
function convertXlsxFormat(numFmtId, formats, warningManager) {
|
|
24287
|
-
if (numFmtId === 0) {
|
|
24288
|
-
return undefined;
|
|
24289
|
-
}
|
|
24290
24311
|
// Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
|
|
24291
24312
|
let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format;
|
|
24313
|
+
if (format === "General") {
|
|
24314
|
+
return undefined;
|
|
24315
|
+
}
|
|
24292
24316
|
if (format) {
|
|
24293
24317
|
try {
|
|
24294
24318
|
let convertedFormat = format.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
|
|
@@ -24486,9 +24510,9 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
24486
24510
|
if (!rule.operator || !rule.formula || rule.formula.length === 0)
|
|
24487
24511
|
continue;
|
|
24488
24512
|
operator = convertCFCellIsOperator(rule.operator);
|
|
24489
|
-
values.push(rule.formula[0]);
|
|
24513
|
+
values.push(prefixFormula(rule.formula[0]));
|
|
24490
24514
|
if (rule.formula.length === 2) {
|
|
24491
|
-
values.push(rule.formula[1]);
|
|
24515
|
+
values.push(prefixFormula(rule.formula[1]));
|
|
24492
24516
|
}
|
|
24493
24517
|
break;
|
|
24494
24518
|
}
|
|
@@ -24646,6 +24670,11 @@ function convertIcons(xlsxIconSet, index) {
|
|
|
24646
24670
|
? ICON_SETS[iconSet].neutral
|
|
24647
24671
|
: ICON_SETS[iconSet].good;
|
|
24648
24672
|
}
|
|
24673
|
+
/** Prefix the string by "=" if the string looks like a formula */
|
|
24674
|
+
function prefixFormula(formula) {
|
|
24675
|
+
const tokens = tokenize(formula);
|
|
24676
|
+
return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
|
|
24677
|
+
}
|
|
24649
24678
|
// ---------------------------------------------------------------------------
|
|
24650
24679
|
// Warnings
|
|
24651
24680
|
// ---------------------------------------------------------------------------
|
|
@@ -27244,10 +27273,11 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
|
|
|
27244
27273
|
});
|
|
27245
27274
|
}
|
|
27246
27275
|
extractRows(worksheet) {
|
|
27276
|
+
const spilledCells = new Set();
|
|
27247
27277
|
return this.mapOnElements({ parent: worksheet, query: "sheetData row" }, (rowElement) => {
|
|
27248
27278
|
return {
|
|
27249
27279
|
index: this.extractAttr(rowElement, "r", { required: true })?.asNum(),
|
|
27250
|
-
cells: this.extractCells(rowElement),
|
|
27280
|
+
cells: this.extractCells(rowElement, spilledCells),
|
|
27251
27281
|
height: this.extractAttr(rowElement, "ht")?.asNum(),
|
|
27252
27282
|
customHeight: this.extractAttr(rowElement, "customHeight")?.asBool(),
|
|
27253
27283
|
hidden: this.extractAttr(rowElement, "hidden")?.asBool(),
|
|
@@ -27257,14 +27287,26 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
|
|
|
27257
27287
|
};
|
|
27258
27288
|
});
|
|
27259
27289
|
}
|
|
27260
|
-
extractCells(row) {
|
|
27290
|
+
extractCells(row, spilledCells) {
|
|
27261
27291
|
return this.mapOnElements({ parent: row, query: "c" }, (cellElement) => {
|
|
27292
|
+
const xc = this.extractAttr(cellElement, "r", { required: true })?.asString();
|
|
27293
|
+
const formula = this.extractCellFormula(cellElement);
|
|
27294
|
+
if (formula?.ref && formula.sharedIndex === undefined) {
|
|
27295
|
+
const zone = toZone(formula.ref);
|
|
27296
|
+
for (const { col, row } of positions(zone)) {
|
|
27297
|
+
const followerXc = toXC(col, row);
|
|
27298
|
+
if (followerXc !== xc) {
|
|
27299
|
+
spilledCells.add(followerXc);
|
|
27300
|
+
}
|
|
27301
|
+
}
|
|
27302
|
+
}
|
|
27303
|
+
const isSpilled = spilledCells.has(xc);
|
|
27262
27304
|
return {
|
|
27263
|
-
xc
|
|
27305
|
+
xc,
|
|
27264
27306
|
styleIndex: this.extractAttr(cellElement, "s")?.asNum(),
|
|
27265
27307
|
type: CELL_TYPE_CONVERSION_MAP[this.extractAttr(cellElement, "t", { default: "n" })?.asString()],
|
|
27266
|
-
value: this.extractChildTextContent(cellElement, "v"),
|
|
27267
|
-
formula:
|
|
27308
|
+
value: isSpilled ? undefined : this.extractChildTextContent(cellElement, "v") ?? undefined,
|
|
27309
|
+
formula: isSpilled ? undefined : formula,
|
|
27268
27310
|
};
|
|
27269
27311
|
});
|
|
27270
27312
|
}
|
|
@@ -27272,11 +27314,14 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
|
|
|
27272
27314
|
const formulaElement = this.querySelector(cellElement, "f");
|
|
27273
27315
|
if (!formulaElement)
|
|
27274
27316
|
return undefined;
|
|
27275
|
-
|
|
27276
|
-
|
|
27277
|
-
|
|
27278
|
-
|
|
27279
|
-
|
|
27317
|
+
const content = this.extractTextContent(formulaElement);
|
|
27318
|
+
const sharedIndex = this.extractAttr(formulaElement, "si")?.asNum();
|
|
27319
|
+
const ref = this.extractAttr(formulaElement, "ref")?.asString();
|
|
27320
|
+
// This is the case of spilled cells of array formulas where <f> is empty
|
|
27321
|
+
if ((content === undefined || content.trim() === "") && sharedIndex === undefined) {
|
|
27322
|
+
return undefined;
|
|
27323
|
+
}
|
|
27324
|
+
return { content, sharedIndex, ref };
|
|
27280
27325
|
}
|
|
27281
27326
|
extractHyperLinks(worksheet) {
|
|
27282
27327
|
return this.mapOnElements({ parent: worksheet, query: "hyperlink" }, (linkElement) => {
|
|
@@ -36170,7 +36215,7 @@ const splitToColumns = {
|
|
|
36170
36215
|
const reinsertDynamicPivotMenu = {
|
|
36171
36216
|
id: "reinsert_dynamic_pivot",
|
|
36172
36217
|
name: _t("Re-insert dynamic pivot"),
|
|
36173
|
-
sequence:
|
|
36218
|
+
sequence: 60,
|
|
36174
36219
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36175
36220
|
children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
|
|
36176
36221
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -36178,7 +36223,7 @@ const reinsertDynamicPivotMenu = {
|
|
|
36178
36223
|
const reinsertStaticPivotMenu = {
|
|
36179
36224
|
id: "reinsert_static_pivot",
|
|
36180
36225
|
name: _t("Re-insert static pivot"),
|
|
36181
|
-
sequence:
|
|
36226
|
+
sequence: 70,
|
|
36182
36227
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
36183
36228
|
children: [REINSERT_STATIC_PIVOT_CHILDREN],
|
|
36184
36229
|
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
@@ -37916,8 +37961,9 @@ topbarMenuRegistry
|
|
|
37916
37961
|
sequence: 40,
|
|
37917
37962
|
separator: true,
|
|
37918
37963
|
})
|
|
37919
|
-
.addChild("
|
|
37964
|
+
.addChild("pivot_data_sources", ["data"], (env) => {
|
|
37920
37965
|
const sequence = 50;
|
|
37966
|
+
const numberOfPivots = env.model.getters.getPivotIds().length;
|
|
37921
37967
|
return env.model.getters.getPivotIds().map((pivotId, index) => {
|
|
37922
37968
|
const highlightProvider = {
|
|
37923
37969
|
get highlights() {
|
|
@@ -37927,7 +37973,7 @@ topbarMenuRegistry
|
|
|
37927
37973
|
return {
|
|
37928
37974
|
id: `item_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
|
|
37929
37975
|
name: env.model.getters.getPivotDisplayName(pivotId),
|
|
37930
|
-
sequence: sequence + index,
|
|
37976
|
+
sequence: sequence + index / numberOfPivots,
|
|
37931
37977
|
isReadonlyAllowed: true,
|
|
37932
37978
|
execute: (env) => env.openSidePanel("PivotSidePanel", { pivotId }),
|
|
37933
37979
|
onStartHover: (env) => env.getStore(HighlightStore).register(highlightProvider),
|
|
@@ -63899,7 +63945,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
63899
63945
|
if (!result) {
|
|
63900
63946
|
return EMPTY_PIVOT_CELL;
|
|
63901
63947
|
}
|
|
63902
|
-
|
|
63948
|
+
let { functionName, args } = result;
|
|
63903
63949
|
const formulaId = args[0];
|
|
63904
63950
|
if (!formulaId) {
|
|
63905
63951
|
return EMPTY_PIVOT_CELL;
|
|
@@ -63929,6 +63975,9 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
63929
63975
|
return pivotCells[pivotCol][pivotRow];
|
|
63930
63976
|
}
|
|
63931
63977
|
try {
|
|
63978
|
+
const offsetRow = position.row - mainPosition.row;
|
|
63979
|
+
const offsetCol = position.col - mainPosition.col;
|
|
63980
|
+
args = args.map((arg) => (isMatrix(arg) ? arg[offsetCol][offsetRow] : arg));
|
|
63932
63981
|
if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
|
|
63933
63982
|
const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
|
|
63934
63983
|
return {
|
|
@@ -67777,12 +67826,12 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
67777
67826
|
}
|
|
67778
67827
|
case "INSERT_CELL": {
|
|
67779
67828
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
67780
|
-
const copiedData = this.copy(cut);
|
|
67829
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
67781
67830
|
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
67782
67831
|
}
|
|
67783
67832
|
case "DELETE_CELL": {
|
|
67784
67833
|
const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
67785
|
-
const copiedData = this.copy(cut);
|
|
67834
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
67786
67835
|
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
67787
67836
|
}
|
|
67788
67837
|
}
|
|
@@ -67872,13 +67921,13 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
67872
67921
|
});
|
|
67873
67922
|
break;
|
|
67874
67923
|
}
|
|
67875
|
-
const copiedData = this.copy(cut);
|
|
67924
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
67876
67925
|
this.paste(paste, copiedData, { isCutOperation: true });
|
|
67877
67926
|
break;
|
|
67878
67927
|
}
|
|
67879
67928
|
case "INSERT_CELL": {
|
|
67880
67929
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
67881
|
-
const copiedData = this.copy(cut);
|
|
67930
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
67882
67931
|
this.paste(paste, copiedData, { isCutOperation: true });
|
|
67883
67932
|
break;
|
|
67884
67933
|
}
|
|
@@ -67993,11 +68042,11 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
67993
68042
|
}
|
|
67994
68043
|
return false;
|
|
67995
68044
|
}
|
|
67996
|
-
copy(zones) {
|
|
68045
|
+
copy(zones, mode = "copyPaste") {
|
|
67997
68046
|
let copiedData = {};
|
|
67998
68047
|
const clipboardData = this.getClipboardData(zones);
|
|
67999
68048
|
for (const { handlerName, handler } of this.selectClipboardHandlers(clipboardData)) {
|
|
68000
|
-
const data = handler.copy(clipboardData);
|
|
68049
|
+
const data = handler.copy(clipboardData, mode);
|
|
68001
68050
|
copiedData[handlerName] = data;
|
|
68002
68051
|
const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
|
|
68003
68052
|
for (const key of minimalKeys) {
|
|
@@ -68861,7 +68910,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
68861
68910
|
];
|
|
68862
68911
|
for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
|
|
68863
68912
|
const handler = new Handler(this.getters, this.dispatch);
|
|
68864
|
-
const data = handler.copy(getClipboardDataPositions(sheetId, target));
|
|
68913
|
+
const data = handler.copy(getClipboardDataPositions(sheetId, target), "shiftCells");
|
|
68865
68914
|
if (!data) {
|
|
68866
68915
|
continue;
|
|
68867
68916
|
}
|
|
@@ -77285,6 +77334,6 @@ exports.tokenColors = tokenColors;
|
|
|
77285
77334
|
exports.tokenize = tokenize;
|
|
77286
77335
|
|
|
77287
77336
|
|
|
77288
|
-
__info__.version = "18.2.
|
|
77289
|
-
__info__.date = "2025-
|
|
77290
|
-
__info__.hash = "
|
|
77337
|
+
__info__.version = "18.2.29";
|
|
77338
|
+
__info__.date = "2025-09-11T08:44:31.801Z";
|
|
77339
|
+
__info__.hash = "665bc43";
|