@odoo/o-spreadsheet 19.1.0-alpha.13 → 19.1.0-alpha.14
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-engine.d.ts +18 -6
- package/dist/o-spreadsheet-engine.esm.js +342 -60
- package/dist/o-spreadsheet-engine.iife.js +342 -60
- package/dist/o-spreadsheet-engine.min.iife.js +313 -313
- package/dist/o-spreadsheet.d.ts +35 -21
- package/dist/o_spreadsheet.esm.js +518 -143
- package/dist/o_spreadsheet.iife.js +518 -143
- package/dist/o_spreadsheet.min.iife.js +320 -320
- package/dist/o_spreadsheet.xml +31 -16
- package/package.json +1 -1
|
@@ -3,8 +3,8 @@
|
|
|
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
5
|
* @version 19.1.0-alpha.3
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
6
|
+
* @date 2025-12-02T05:34:07.213Z
|
|
7
|
+
* @hash 04cf666
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports) {
|
|
@@ -3109,8 +3109,56 @@
|
|
|
3109
3109
|
return isMatrix(arg) && !isSingleElementMatrix(arg);
|
|
3110
3110
|
}
|
|
3111
3111
|
|
|
3112
|
+
function stackHorizontally(ranges, options) {
|
|
3113
|
+
const matrices = ranges.map(toMatrix);
|
|
3114
|
+
const nbRowsArr = matrices.map((m) => m?.[0]?.length ?? 0);
|
|
3115
|
+
const nbRows = Math.max(...nbRowsArr);
|
|
3116
|
+
if (options?.requireSameRowCount) {
|
|
3117
|
+
const firstLength = nbRowsArr[0];
|
|
3118
|
+
if (nbRowsArr.some((len) => len !== firstLength)) {
|
|
3119
|
+
return new EvaluationError(_t("All ranges in [[FUNCTION_NAME]] must have the same number of columns (got %s).", nbRowsArr.join(", ")));
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
const result = [];
|
|
3123
|
+
for (const matrix of matrices) {
|
|
3124
|
+
for (let col = 0; col < matrix.length; col++) {
|
|
3125
|
+
// Fill with nulls if needed
|
|
3126
|
+
const array = Array(nbRows).fill({ value: null });
|
|
3127
|
+
for (let row = 0; row < matrix[col].length; row++) {
|
|
3128
|
+
array[row] = matrix[col][row];
|
|
3129
|
+
}
|
|
3130
|
+
result.push(array);
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
return result;
|
|
3134
|
+
}
|
|
3135
|
+
function stackVertically(ranges, options) {
|
|
3136
|
+
const matrices = ranges.map(toMatrix);
|
|
3137
|
+
const nbColsArr = matrices.map((m) => m?.length ?? 0);
|
|
3138
|
+
const nbCols = Math.max(...nbColsArr);
|
|
3139
|
+
if (options?.requireSameColCount) {
|
|
3140
|
+
const firstLength = nbColsArr[0];
|
|
3141
|
+
if (nbColsArr.some((len) => len !== firstLength)) {
|
|
3142
|
+
return new EvaluationError(_t("All ranges in [[FUNCTION_NAME]] must have the same number of columns (got %s).", nbColsArr.join(", ")));
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
const nbRows = matrices.reduce((acc, m) => acc + (m?.[0]?.length ?? 0), 0);
|
|
3146
|
+
const result = generateMatrix(nbCols, nbRows, () => ({
|
|
3147
|
+
value: null,
|
|
3148
|
+
}));
|
|
3149
|
+
let currentRow = 0;
|
|
3150
|
+
for (const matrix of matrices) {
|
|
3151
|
+
for (let col = 0; col < matrix.length; col++) {
|
|
3152
|
+
for (let row = 0; row < matrix[col].length; row++) {
|
|
3153
|
+
result[col][currentRow + row] = matrix[col][row];
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
currentRow += matrix[0]?.length ?? 0;
|
|
3157
|
+
}
|
|
3158
|
+
return result;
|
|
3159
|
+
}
|
|
3112
3160
|
// -----------------------------------------------------------------------------
|
|
3113
|
-
//
|
|
3161
|
+
// ARRAY.CONSTRAIN
|
|
3114
3162
|
// -----------------------------------------------------------------------------
|
|
3115
3163
|
const ARRAY_CONSTRAIN = {
|
|
3116
3164
|
description: _t("Returns a result array constrained to a specific width and height."),
|
|
@@ -3136,6 +3184,30 @@
|
|
|
3136
3184
|
isExported: false,
|
|
3137
3185
|
};
|
|
3138
3186
|
// -----------------------------------------------------------------------------
|
|
3187
|
+
// ARRAY.LITERAL
|
|
3188
|
+
// -----------------------------------------------------------------------------
|
|
3189
|
+
const ARRAY_LITERAL = {
|
|
3190
|
+
description: _t("Appends ranges vertically and in sequence to return a larger array. All ranges must have the same number of columns."),
|
|
3191
|
+
args: [arg("range (any, range<any>, repeating)", _t("The range to be appended."))],
|
|
3192
|
+
compute: function (...ranges) {
|
|
3193
|
+
return stackVertically(ranges, { requireSameColCount: true });
|
|
3194
|
+
},
|
|
3195
|
+
isExported: false,
|
|
3196
|
+
hidden: true,
|
|
3197
|
+
};
|
|
3198
|
+
// -----------------------------------------------------------------------------
|
|
3199
|
+
// ARRAY.ROW
|
|
3200
|
+
// -----------------------------------------------------------------------------
|
|
3201
|
+
const ARRAY_ROW = {
|
|
3202
|
+
description: _t("Appends ranges horizontally and in sequence to return a larger array. All ranges must have the same number of rows."),
|
|
3203
|
+
args: [arg("range (any, range<any>, repeating)", _t("The range to be appended."))],
|
|
3204
|
+
compute: function (...ranges) {
|
|
3205
|
+
return stackHorizontally(ranges, { requireSameRowCount: true });
|
|
3206
|
+
},
|
|
3207
|
+
isExported: false,
|
|
3208
|
+
hidden: true,
|
|
3209
|
+
};
|
|
3210
|
+
// -----------------------------------------------------------------------------
|
|
3139
3211
|
// CHOOSECOLS
|
|
3140
3212
|
// -----------------------------------------------------------------------------
|
|
3141
3213
|
const CHOOSECOLS = {
|
|
@@ -3281,20 +3353,7 @@
|
|
|
3281
3353
|
description: _t("Appends ranges horizontally and in sequence to return a larger array."),
|
|
3282
3354
|
args: [arg("range (any, range<any>, repeating)", _t("The range to be appended."))],
|
|
3283
3355
|
compute: function (...ranges) {
|
|
3284
|
-
|
|
3285
|
-
const result = [];
|
|
3286
|
-
for (const range of ranges) {
|
|
3287
|
-
const _range = toMatrix(range);
|
|
3288
|
-
for (let col = 0; col < _range.length; col++) {
|
|
3289
|
-
//TODO: fill with #N/A for unavailable values instead of zeroes
|
|
3290
|
-
const array = Array(nbRows).fill({ value: null });
|
|
3291
|
-
for (let row = 0; row < _range[col].length; row++) {
|
|
3292
|
-
array[row] = _range[col][row];
|
|
3293
|
-
}
|
|
3294
|
-
result.push(array);
|
|
3295
|
-
}
|
|
3296
|
-
}
|
|
3297
|
-
return result;
|
|
3356
|
+
return stackHorizontally(ranges);
|
|
3298
3357
|
},
|
|
3299
3358
|
isExported: true,
|
|
3300
3359
|
};
|
|
@@ -3553,22 +3612,7 @@
|
|
|
3553
3612
|
description: _t("Appends ranges vertically and in sequence to return a larger array."),
|
|
3554
3613
|
args: [arg("range (any, range<any>, repeating)", _t("The range to be appended."))],
|
|
3555
3614
|
compute: function (...ranges) {
|
|
3556
|
-
|
|
3557
|
-
const nbRows = ranges.reduce((acc, range) => acc + toMatrix(range)[0].length, 0);
|
|
3558
|
-
const result = Array(nbColumns)
|
|
3559
|
-
.fill([])
|
|
3560
|
-
.map(() => Array(nbRows).fill({ value: 0 })); // TODO fill with #N/A
|
|
3561
|
-
let currentRow = 0;
|
|
3562
|
-
for (const range of ranges) {
|
|
3563
|
-
const _array = toMatrix(range);
|
|
3564
|
-
for (let col = 0; col < _array.length; col++) {
|
|
3565
|
-
for (let row = 0; row < _array[col].length; row++) {
|
|
3566
|
-
result[col][currentRow + row] = _array[col][row];
|
|
3567
|
-
}
|
|
3568
|
-
}
|
|
3569
|
-
currentRow += _array[0].length;
|
|
3570
|
-
}
|
|
3571
|
-
return result;
|
|
3615
|
+
return stackVertically(ranges);
|
|
3572
3616
|
},
|
|
3573
3617
|
isExported: true,
|
|
3574
3618
|
};
|
|
@@ -3628,6 +3672,8 @@
|
|
|
3628
3672
|
var array = /*#__PURE__*/Object.freeze({
|
|
3629
3673
|
__proto__: null,
|
|
3630
3674
|
ARRAY_CONSTRAIN: ARRAY_CONSTRAIN,
|
|
3675
|
+
ARRAY_LITERAL: ARRAY_LITERAL,
|
|
3676
|
+
ARRAY_ROW: ARRAY_ROW,
|
|
3631
3677
|
CHOOSECOLS: CHOOSECOLS,
|
|
3632
3678
|
CHOOSEROWS: CHOOSEROWS,
|
|
3633
3679
|
EXPAND: EXPAND,
|
|
@@ -6083,6 +6129,47 @@
|
|
|
6083
6129
|
return newZones;
|
|
6084
6130
|
}
|
|
6085
6131
|
}
|
|
6132
|
+
/**
|
|
6133
|
+
* Splits zone z2 by removing the overlapping zone z1 (fully inside z2).
|
|
6134
|
+
* Returns the remaining parts of z2 that don't overlap with z1.
|
|
6135
|
+
*
|
|
6136
|
+
* Diagram:
|
|
6137
|
+
* ┌──────────── z2 ─────────────┐
|
|
6138
|
+
* │ 1 │
|
|
6139
|
+
* │--------─────────────--------│
|
|
6140
|
+
* │ 2 | z1 | 3 │
|
|
6141
|
+
* │--------─────────────--------│
|
|
6142
|
+
* │ 4 │
|
|
6143
|
+
* └─────────────────────────────┘
|
|
6144
|
+
*
|
|
6145
|
+
* Input:
|
|
6146
|
+
* z1 = { top: 2, bottom: 3, left: 2, right: 3 }
|
|
6147
|
+
* z2 = { top: 1, bottom: 4, left: 1, right: 4 }
|
|
6148
|
+
*
|
|
6149
|
+
* Output:
|
|
6150
|
+
* [
|
|
6151
|
+
* { top: 4, bottom: 4, left: 1, right: 4 }, // bottom
|
|
6152
|
+
* { top: 2, bottom: 3, left: 4, right: 4 }, // right
|
|
6153
|
+
* { top: 2, bottom: 3, left: 1, right: 1 }, // left
|
|
6154
|
+
* { top: 1, bottom: 1, left: 1, right: 4 } // top
|
|
6155
|
+
* ]
|
|
6156
|
+
*/
|
|
6157
|
+
function splitZone(z1, z2) {
|
|
6158
|
+
const zones = [];
|
|
6159
|
+
if (z1.bottom < z2.bottom) {
|
|
6160
|
+
zones.push({ ...z2, top: z1.bottom + 1 });
|
|
6161
|
+
}
|
|
6162
|
+
if (z1.right < z2.right) {
|
|
6163
|
+
zones.push({ ...z2, left: z1.right + 1, top: z1.top, bottom: z1.bottom });
|
|
6164
|
+
}
|
|
6165
|
+
if (z1.left > z2.left) {
|
|
6166
|
+
zones.push({ ...z2, right: z1.left - 1, top: z1.top, bottom: z1.bottom });
|
|
6167
|
+
}
|
|
6168
|
+
if (z1.top > z2.top) {
|
|
6169
|
+
zones.push({ ...z2, bottom: z1.top - 1 });
|
|
6170
|
+
}
|
|
6171
|
+
return zones;
|
|
6172
|
+
}
|
|
6086
6173
|
|
|
6087
6174
|
function isSheetDependent(cmd) {
|
|
6088
6175
|
return "sheetId" in cmd;
|
|
@@ -6113,7 +6200,6 @@
|
|
|
6113
6200
|
"REDO",
|
|
6114
6201
|
"ADD_MERGE",
|
|
6115
6202
|
"REMOVE_MERGE",
|
|
6116
|
-
"DUPLICATE_SHEET",
|
|
6117
6203
|
"UPDATE_LOCALE",
|
|
6118
6204
|
"ADD_PIVOT",
|
|
6119
6205
|
"UPDATE_PIVOT",
|
|
@@ -9603,7 +9689,9 @@
|
|
|
9603
9689
|
while (!chars.isOver()) {
|
|
9604
9690
|
let token = tokenizeNewLine(chars) ||
|
|
9605
9691
|
tokenizeSpace(chars) ||
|
|
9692
|
+
tokenizeArrayRowSeparator(chars, locale) ||
|
|
9606
9693
|
tokenizeArgsSeparator(chars, locale) ||
|
|
9694
|
+
tokenizeBraces(chars) ||
|
|
9607
9695
|
tokenizeParenthesis(chars) ||
|
|
9608
9696
|
tokenizeOperator(chars) ||
|
|
9609
9697
|
tokenizeString(chars) ||
|
|
@@ -9636,6 +9724,17 @@
|
|
|
9636
9724
|
}
|
|
9637
9725
|
return null;
|
|
9638
9726
|
}
|
|
9727
|
+
const braces = {
|
|
9728
|
+
"{": { type: "LEFT_BRACE", value: "{" },
|
|
9729
|
+
"}": { type: "RIGHT_BRACE", value: "}" },
|
|
9730
|
+
};
|
|
9731
|
+
function tokenizeBraces(chars) {
|
|
9732
|
+
if (chars.current === "{" || chars.current === "}") {
|
|
9733
|
+
const value = chars.shift();
|
|
9734
|
+
return braces[value];
|
|
9735
|
+
}
|
|
9736
|
+
return null;
|
|
9737
|
+
}
|
|
9639
9738
|
function tokenizeArgsSeparator(chars, locale) {
|
|
9640
9739
|
if (chars.current === locale.formulaArgSeparator) {
|
|
9641
9740
|
const value = chars.shift();
|
|
@@ -9644,6 +9743,20 @@
|
|
|
9644
9743
|
}
|
|
9645
9744
|
return null;
|
|
9646
9745
|
}
|
|
9746
|
+
function tokenizeArrayRowSeparator(chars, locale) {
|
|
9747
|
+
// The array row separator is used in array literals to separate rows.
|
|
9748
|
+
// It is not explicitly defined in locales, but depends on the formulaArgSeparator.
|
|
9749
|
+
// Example: {1,2,3;4,5,6} — here, ';' separates rows and ',' separates columns.
|
|
9750
|
+
const rowSeparator = locale.formulaArgSeparator === ";" ? "\\" : ";";
|
|
9751
|
+
if (!rowSeparator) {
|
|
9752
|
+
return null;
|
|
9753
|
+
}
|
|
9754
|
+
if (chars.current === rowSeparator) {
|
|
9755
|
+
chars.shift();
|
|
9756
|
+
return { type: "ARRAY_ROW_SEPARATOR", value: rowSeparator };
|
|
9757
|
+
}
|
|
9758
|
+
return null;
|
|
9759
|
+
}
|
|
9647
9760
|
function tokenizeOperator(chars) {
|
|
9648
9761
|
for (const op of OPERATORS) {
|
|
9649
9762
|
if (chars.currentStartsWith(op)) {
|
|
@@ -9864,6 +9977,9 @@
|
|
|
9864
9977
|
else if (token.type === "ARG_SEPARATOR") {
|
|
9865
9978
|
localizedFormula += toLocale.formulaArgSeparator;
|
|
9866
9979
|
}
|
|
9980
|
+
else if (token.type === "ARRAY_ROW_SEPARATOR") {
|
|
9981
|
+
localizedFormula += toLocale.formulaArgSeparator === ";" ? "\\" : ";";
|
|
9982
|
+
}
|
|
9867
9983
|
else {
|
|
9868
9984
|
localizedFormula += token.value;
|
|
9869
9985
|
}
|
|
@@ -11027,7 +11143,6 @@
|
|
|
11027
11143
|
// -----------------------------------------------------------------------------
|
|
11028
11144
|
const FILTER = {
|
|
11029
11145
|
description: _t("Returns a filtered version of the source range, returning only rows or columns that meet the specified conditions."),
|
|
11030
|
-
// TODO modify args description when vectorization on formulas is available
|
|
11031
11146
|
args: [
|
|
11032
11147
|
arg("range (any, range<any>)", _t("The data to be filtered.")),
|
|
11033
11148
|
arg("condition (boolean, range<boolean>, repeating)", _t("Column or row containing true or false values corresponding to the range.")),
|
|
@@ -17227,6 +17342,8 @@
|
|
|
17227
17342
|
tokenStartIndex: current.tokenIndex,
|
|
17228
17343
|
tokenEndIndex: rightParen.tokenIndex,
|
|
17229
17344
|
};
|
|
17345
|
+
case "LEFT_BRACE":
|
|
17346
|
+
return parseArrayLiteral(tokens, current);
|
|
17230
17347
|
case "OPERATOR":
|
|
17231
17348
|
const operator = current.value;
|
|
17232
17349
|
if (UNARY_OPERATORS_PREFIX.includes(operator)) {
|
|
@@ -17280,6 +17397,34 @@
|
|
|
17280
17397
|
}
|
|
17281
17398
|
return token;
|
|
17282
17399
|
}
|
|
17400
|
+
function parseArrayLiteral(tokens, leftBrace) {
|
|
17401
|
+
const rows = [];
|
|
17402
|
+
let currentRow = [parseExpression(tokens)]; // there must be at least one element
|
|
17403
|
+
while (tokens.current?.type !== "RIGHT_BRACE") {
|
|
17404
|
+
const nextToken = tokens.shift();
|
|
17405
|
+
if (!nextToken) {
|
|
17406
|
+
throw new BadExpressionError(_t("Missing closing brace"));
|
|
17407
|
+
}
|
|
17408
|
+
else if (nextToken.type === "ARG_SEPARATOR") {
|
|
17409
|
+
currentRow.push(parseExpression(tokens));
|
|
17410
|
+
}
|
|
17411
|
+
else if (nextToken.type === "ARRAY_ROW_SEPARATOR") {
|
|
17412
|
+
rows.push(currentRow);
|
|
17413
|
+
currentRow = [parseExpression(tokens)];
|
|
17414
|
+
}
|
|
17415
|
+
else {
|
|
17416
|
+
throw new BadExpressionError(_t("Unexpected token: %s", nextToken.value));
|
|
17417
|
+
}
|
|
17418
|
+
}
|
|
17419
|
+
const rightBrace = consumeOrThrow(tokens, "RIGHT_BRACE", _t("Missing closing brace"));
|
|
17420
|
+
rows.push(currentRow);
|
|
17421
|
+
return {
|
|
17422
|
+
type: "ARRAY",
|
|
17423
|
+
value: rows,
|
|
17424
|
+
tokenStartIndex: leftBrace.tokenIndex,
|
|
17425
|
+
tokenEndIndex: rightBrace.tokenIndex,
|
|
17426
|
+
};
|
|
17427
|
+
}
|
|
17283
17428
|
function parseExpression(tokens, parent_priority = 0) {
|
|
17284
17429
|
if (tokens.length === 0) {
|
|
17285
17430
|
throw new BadExpressionError();
|
|
@@ -17370,6 +17515,13 @@
|
|
|
17370
17515
|
yield* astIterator(arg);
|
|
17371
17516
|
}
|
|
17372
17517
|
break;
|
|
17518
|
+
case "ARRAY":
|
|
17519
|
+
for (const row of ast.value) {
|
|
17520
|
+
for (const cell of row) {
|
|
17521
|
+
yield* astIterator(cell);
|
|
17522
|
+
}
|
|
17523
|
+
}
|
|
17524
|
+
break;
|
|
17373
17525
|
case "UNARY_OPERATION":
|
|
17374
17526
|
yield* astIterator(ast.operand);
|
|
17375
17527
|
break;
|
|
@@ -17387,6 +17539,11 @@
|
|
|
17387
17539
|
...ast,
|
|
17388
17540
|
args: ast.args.map((child) => mapAst(child, fn)),
|
|
17389
17541
|
};
|
|
17542
|
+
case "ARRAY":
|
|
17543
|
+
return {
|
|
17544
|
+
...ast,
|
|
17545
|
+
value: ast.value.map((row) => row.map((cell) => mapAst(cell, fn))),
|
|
17546
|
+
};
|
|
17390
17547
|
case "UNARY_OPERATION":
|
|
17391
17548
|
return {
|
|
17392
17549
|
...ast,
|
|
@@ -17545,6 +17702,23 @@
|
|
|
17545
17702
|
code.append(...args);
|
|
17546
17703
|
const fnName = ast.value.toUpperCase();
|
|
17547
17704
|
return code.return(`ctx['${fnName}'](${args.map((arg) => arg.returnExpression)})`);
|
|
17705
|
+
case "ARRAY": {
|
|
17706
|
+
// a literal array is compiled into function calls
|
|
17707
|
+
const arrayFunctionCall = {
|
|
17708
|
+
type: "FUNCALL",
|
|
17709
|
+
value: "ARRAY.LITERAL",
|
|
17710
|
+
args: ast.value.map((row) => ({
|
|
17711
|
+
type: "FUNCALL",
|
|
17712
|
+
value: "ARRAY.ROW",
|
|
17713
|
+
args: row,
|
|
17714
|
+
tokenStartIndex: 0,
|
|
17715
|
+
tokenEndIndex: 0,
|
|
17716
|
+
})),
|
|
17717
|
+
tokenStartIndex: 0,
|
|
17718
|
+
tokenEndIndex: 0,
|
|
17719
|
+
};
|
|
17720
|
+
return compileAST(arrayFunctionCall);
|
|
17721
|
+
}
|
|
17548
17722
|
case "UNARY_OPERATION": {
|
|
17549
17723
|
const fnName = UNARY_OPERATOR_MAP[ast.value];
|
|
17550
17724
|
const operand = compileAST(ast.operand, false, false).assignResultToVariable();
|
|
@@ -25887,6 +26061,17 @@
|
|
|
25887
26061
|
}
|
|
25888
26062
|
}
|
|
25889
26063
|
|
|
26064
|
+
function schemeToColorScale(scheme) {
|
|
26065
|
+
const colors = COLORSCHEMES[scheme];
|
|
26066
|
+
return colors === undefined
|
|
26067
|
+
? undefined
|
|
26068
|
+
: {
|
|
26069
|
+
minColor: colors[0],
|
|
26070
|
+
midColor: colors.length === 3 ? colors[1] : undefined,
|
|
26071
|
+
maxColor: colors[colors.length - 1],
|
|
26072
|
+
};
|
|
26073
|
+
}
|
|
26074
|
+
|
|
25890
26075
|
/**
|
|
25891
26076
|
* parses a formula (as a string) into the same formula,
|
|
25892
26077
|
* but with the references to other cells extracted
|
|
@@ -26531,13 +26716,22 @@
|
|
|
26531
26716
|
return data;
|
|
26532
26717
|
},
|
|
26533
26718
|
})
|
|
26534
|
-
.add("19.
|
|
26719
|
+
.add("19.1.0", {
|
|
26535
26720
|
migrate(data) {
|
|
26536
26721
|
for (const sheet of data.sheets || []) {
|
|
26537
26722
|
for (const figure of sheet.figures || []) {
|
|
26538
26723
|
if (figure.tag === "chart" && figure.data.type === "geo") {
|
|
26539
26724
|
if ("colorScale" in figure.data && typeof figure.data.colorScale === "string") {
|
|
26540
|
-
figure.data.colorScale =
|
|
26725
|
+
figure.data.colorScale = schemeToColorScale(figure.data.colorScale);
|
|
26726
|
+
}
|
|
26727
|
+
}
|
|
26728
|
+
if (figure.tag === "carousel") {
|
|
26729
|
+
for (const definition of Object.values(figure.data.chartDefinitions) || []) {
|
|
26730
|
+
if (definition.type === "geo") {
|
|
26731
|
+
if ("colorScale" in definition && typeof definition.colorScale === "string") {
|
|
26732
|
+
definition.colorScale = schemeToColorScale(definition.colorScale);
|
|
26733
|
+
}
|
|
26734
|
+
}
|
|
26541
26735
|
}
|
|
26542
26736
|
}
|
|
26543
26737
|
}
|
|
@@ -26800,18 +26994,22 @@
|
|
|
26800
26994
|
return messages;
|
|
26801
26995
|
}
|
|
26802
26996
|
function fixChartDefinitions(data, initialMessages) {
|
|
26997
|
+
/**
|
|
26998
|
+
* Revisions created after version 18.5.1 contain the full chart definition in the command
|
|
26999
|
+
* if the data was alreay updated to 18.5.1, then those older revision cannot (by definition) be reaplied
|
|
27000
|
+
* and should not be replayed.
|
|
27001
|
+
* FIXME: every command should be versionned when upgraded to allow finer tuning.
|
|
27002
|
+
*/
|
|
27003
|
+
if (!data.version || compareVersions(String(data.version), "18.5.1") >= 0) {
|
|
27004
|
+
return initialMessages;
|
|
27005
|
+
}
|
|
26803
27006
|
const messages = [];
|
|
26804
27007
|
const map = {};
|
|
26805
27008
|
for (const sheet of data.sheets || []) {
|
|
26806
27009
|
sheet.figures?.forEach((figure) => {
|
|
26807
27010
|
if (figure.tag === "chart") {
|
|
26808
27011
|
// chart definition
|
|
26809
|
-
|
|
26810
|
-
map[figure.data.chartId] = figure.data;
|
|
26811
|
-
}
|
|
26812
|
-
else {
|
|
26813
|
-
map[figure.id] = figure.data;
|
|
26814
|
-
}
|
|
27012
|
+
map[figure.id] = figure.data;
|
|
26815
27013
|
}
|
|
26816
27014
|
});
|
|
26817
27015
|
}
|
|
@@ -29851,7 +30049,8 @@
|
|
|
29851
30049
|
}
|
|
29852
30050
|
break;
|
|
29853
30051
|
case "DUPLICATE_SHEET": {
|
|
29854
|
-
for (const
|
|
30052
|
+
for (const figure of this.getFigures(cmd.sheetId)) {
|
|
30053
|
+
const figureId = figure.id;
|
|
29855
30054
|
const fig = this.figures[cmd.sheetId]?.[figureId];
|
|
29856
30055
|
if (!fig) {
|
|
29857
30056
|
continue;
|
|
@@ -32184,10 +32383,17 @@
|
|
|
32184
32383
|
if (!pivot) {
|
|
32185
32384
|
continue;
|
|
32186
32385
|
}
|
|
32187
|
-
|
|
32386
|
+
const def = deepCopy(pivot.definition);
|
|
32387
|
+
for (const measure of def.measures) {
|
|
32188
32388
|
if (measure.computedBy?.formula === formulaString) {
|
|
32189
|
-
const measureIndex =
|
|
32190
|
-
|
|
32389
|
+
const measureIndex = def.measures.indexOf(measure);
|
|
32390
|
+
if (measureIndex !== -1) {
|
|
32391
|
+
def.measures[measureIndex].computedBy = {
|
|
32392
|
+
formula: newFormulaString,
|
|
32393
|
+
sheetId,
|
|
32394
|
+
};
|
|
32395
|
+
}
|
|
32396
|
+
this.dispatch("UPDATE_PIVOT", { pivotId, pivot: def });
|
|
32191
32397
|
}
|
|
32192
32398
|
}
|
|
32193
32399
|
}
|
|
@@ -33219,6 +33425,9 @@
|
|
|
33219
33425
|
const { sheetId, zone } = definition.dataSet;
|
|
33220
33426
|
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
33221
33427
|
const adaptedRange = adaptPivotRange(range, applyChange);
|
|
33428
|
+
if (adaptedRange === range) {
|
|
33429
|
+
return;
|
|
33430
|
+
}
|
|
33222
33431
|
const dataSet = adaptedRange && {
|
|
33223
33432
|
sheetId: adaptedRange.sheetId,
|
|
33224
33433
|
zone: adaptedRange.zone,
|
|
@@ -38950,6 +39159,10 @@
|
|
|
38950
39159
|
? `(${astToFormula(ast.operand)})`
|
|
38951
39160
|
: astToFormula(ast.operand);
|
|
38952
39161
|
return ast.value + rightOperand;
|
|
39162
|
+
case "ARRAY":
|
|
39163
|
+
return ("{" +
|
|
39164
|
+
ast.value.map((row) => row.map((cell) => astToFormula(cell)).join(",")).join(";") +
|
|
39165
|
+
"}");
|
|
38953
39166
|
case "BIN_OPERATION":
|
|
38954
39167
|
const leftOperation = leftOperandNeedsParenthesis(ast)
|
|
38955
39168
|
? `(${astToFormula(ast.left)})`
|
|
@@ -40514,7 +40727,6 @@
|
|
|
40514
40727
|
pivotRegistry.add("SPREADSHEET", {
|
|
40515
40728
|
ui: SpreadsheetPivot,
|
|
40516
40729
|
definition: SpreadsheetPivotRuntimeDefinition,
|
|
40517
|
-
externalData: false,
|
|
40518
40730
|
dateGranularities: [...dateGranularities],
|
|
40519
40731
|
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
|
|
40520
40732
|
isMeasureCandidate: (field) => field.type !== "boolean",
|
|
@@ -40556,9 +40768,7 @@
|
|
|
40556
40768
|
handle(cmd) {
|
|
40557
40769
|
if (invalidateEvaluationCommands.has(cmd.type)) {
|
|
40558
40770
|
for (const pivotId of this.getters.getPivotIds()) {
|
|
40559
|
-
|
|
40560
|
-
this.setupPivot(pivotId, { recreate: true });
|
|
40561
|
-
}
|
|
40771
|
+
this.setupPivot(pivotId, { recreate: true });
|
|
40562
40772
|
}
|
|
40563
40773
|
}
|
|
40564
40774
|
switch (cmd.type) {
|
|
@@ -40772,7 +40982,7 @@
|
|
|
40772
40982
|
pivot.init({ reload: true });
|
|
40773
40983
|
}
|
|
40774
40984
|
setupPivot(pivotId, { recreate } = { recreate: false }) {
|
|
40775
|
-
const definition = this.getters.getPivotCoreDefinition(pivotId);
|
|
40985
|
+
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
40776
40986
|
if (!(pivotId in this.pivots)) {
|
|
40777
40987
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
40778
40988
|
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
@@ -43843,6 +44053,15 @@
|
|
|
43843
44053
|
return "InvalidFigureId" /* CommandResult.InvalidFigureId */;
|
|
43844
44054
|
}
|
|
43845
44055
|
return "Success" /* CommandResult.Success */;
|
|
44056
|
+
case "DUPLICATE_CAROUSEL_CHART":
|
|
44057
|
+
if (!this.getters.doesCarouselExist(cmd.carouselId) ||
|
|
44058
|
+
!this.getters
|
|
44059
|
+
.getCarousel(cmd.carouselId)
|
|
44060
|
+
.items.some((item) => item.type === "chart" && item.chartId === cmd.chartId) ||
|
|
44061
|
+
this.getters.getChart(cmd.duplicatedChartId)) {
|
|
44062
|
+
return "InvalidFigureId" /* CommandResult.InvalidFigureId */;
|
|
44063
|
+
}
|
|
44064
|
+
return "Success" /* CommandResult.Success */;
|
|
43846
44065
|
case "ADD_NEW_CHART_TO_CAROUSEL":
|
|
43847
44066
|
if (!this.getters.doesCarouselExist(cmd.figureId)) {
|
|
43848
44067
|
return "InvalidFigureId" /* CommandResult.InvalidFigureId */;
|
|
@@ -43867,6 +44086,9 @@
|
|
|
43867
44086
|
case "ADD_FIGURE_CHART_TO_CAROUSEL":
|
|
43868
44087
|
this.addFigureChartToCarousel(cmd.carouselFigureId, cmd.chartFigureId, cmd.sheetId);
|
|
43869
44088
|
break;
|
|
44089
|
+
case "DUPLICATE_CAROUSEL_CHART":
|
|
44090
|
+
this.duplicateCarouselChart(cmd);
|
|
44091
|
+
break;
|
|
43870
44092
|
case "UPDATE_CAROUSEL_ACTIVE_ITEM":
|
|
43871
44093
|
this.carouselStates[cmd.figureId] = this.getCarouselItemId(cmd.item);
|
|
43872
44094
|
break;
|
|
@@ -44005,6 +44227,29 @@
|
|
|
44005
44227
|
});
|
|
44006
44228
|
this.dispatch("DELETE_FIGURE", { sheetId, figureId: chartFigureId });
|
|
44007
44229
|
}
|
|
44230
|
+
duplicateCarouselChart({ carouselId, chartId, sheetId, duplicatedChartId, }) {
|
|
44231
|
+
const chart = this.getters.getChart(chartId);
|
|
44232
|
+
if (!chart) {
|
|
44233
|
+
return;
|
|
44234
|
+
}
|
|
44235
|
+
const carousel = this.getters.getCarousel(carouselId);
|
|
44236
|
+
const duplicatedItemIndex = carousel.items.findIndex((item) => item.type === "chart" && item.chartId === chartId);
|
|
44237
|
+
if (duplicatedItemIndex === -1) {
|
|
44238
|
+
return;
|
|
44239
|
+
}
|
|
44240
|
+
this.dispatch("CREATE_CHART", {
|
|
44241
|
+
chartId: duplicatedChartId,
|
|
44242
|
+
figureId: carouselId,
|
|
44243
|
+
sheetId,
|
|
44244
|
+
definition: chart.getDefinition(),
|
|
44245
|
+
});
|
|
44246
|
+
const carouselItems = insertItemsAtIndex(carousel.items, [{ type: "chart", chartId: duplicatedChartId }], duplicatedItemIndex + 1);
|
|
44247
|
+
this.dispatch("UPDATE_CAROUSEL", {
|
|
44248
|
+
sheetId,
|
|
44249
|
+
figureId: carouselId,
|
|
44250
|
+
definition: { ...carousel, items: carouselItems },
|
|
44251
|
+
});
|
|
44252
|
+
}
|
|
44008
44253
|
getCarouselItemId(item) {
|
|
44009
44254
|
return item.type === "chart" ? item.chartId : "carouselDataView";
|
|
44010
44255
|
}
|
|
@@ -45220,25 +45465,43 @@
|
|
|
45220
45465
|
return "Success" /* CommandResult.Success */;
|
|
45221
45466
|
}
|
|
45222
45467
|
handleEvent(event) {
|
|
45223
|
-
|
|
45224
|
-
let zones = [];
|
|
45468
|
+
let anchor = event.anchor;
|
|
45469
|
+
let zones = [...this.gridSelection.zones];
|
|
45225
45470
|
this.isUnbounded = event.options?.unbounded || false;
|
|
45226
45471
|
switch (event.mode) {
|
|
45227
45472
|
case "overrideSelection":
|
|
45228
45473
|
zones = [anchor.zone];
|
|
45229
45474
|
break;
|
|
45230
45475
|
case "updateAnchor":
|
|
45231
|
-
zones = [...this.gridSelection.zones];
|
|
45232
45476
|
const index = zones.findIndex((z) => isEqual(z, event.previousAnchor.zone));
|
|
45233
45477
|
if (index >= 0) {
|
|
45234
45478
|
zones[index] = anchor.zone;
|
|
45235
45479
|
}
|
|
45236
45480
|
break;
|
|
45237
45481
|
case "newAnchor":
|
|
45238
|
-
zones
|
|
45482
|
+
zones.push(anchor.zone);
|
|
45483
|
+
break;
|
|
45484
|
+
case "commitSelection":
|
|
45485
|
+
const zoneToSplit = zones.find((zone) => isZoneInside(anchor.zone, zone) && !isEqual(anchor.zone, zone));
|
|
45486
|
+
const removeFullAnchor = zones.filter((zone) => isEqual(anchor.zone, zone)).length > 1;
|
|
45487
|
+
if (removeFullAnchor && zones.length > 2) {
|
|
45488
|
+
zones = zones.filter((zone) => !isEqual(zone, anchor.zone));
|
|
45489
|
+
}
|
|
45490
|
+
else if (zoneToSplit) {
|
|
45491
|
+
const splittedZones = splitZone(anchor.zone, zoneToSplit);
|
|
45492
|
+
zones = zones
|
|
45493
|
+
.filter((z) => !isEqual(z, anchor.zone) && !isEqual(z, zoneToSplit))
|
|
45494
|
+
.concat(splittedZones);
|
|
45495
|
+
}
|
|
45496
|
+
zones = uniqueZones(zones);
|
|
45497
|
+
const lastZone = zones[zones.length - 1];
|
|
45498
|
+
anchor = {
|
|
45499
|
+
cell: { col: lastZone.left, row: lastZone.top },
|
|
45500
|
+
zone: lastZone,
|
|
45501
|
+
};
|
|
45239
45502
|
break;
|
|
45240
45503
|
}
|
|
45241
|
-
this.setSelectionMixin(
|
|
45504
|
+
this.setSelectionMixin(anchor, zones);
|
|
45242
45505
|
/** Any change to the selection has to be reflected in the selection processor. */
|
|
45243
45506
|
this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
|
|
45244
45507
|
const { col, row } = this.gridSelection.anchor.cell;
|
|
@@ -45518,7 +45781,7 @@
|
|
|
45518
45781
|
setSelectionMixin(anchor, zones) {
|
|
45519
45782
|
const { anchor: clippedAnchor, zones: clippedZones } = this.clipSelection(this.getters.getActiveSheetId(), { anchor, zones });
|
|
45520
45783
|
this.gridSelection.anchor = clippedAnchor;
|
|
45521
|
-
this.gridSelection.zones =
|
|
45784
|
+
this.gridSelection.zones = clippedZones;
|
|
45522
45785
|
}
|
|
45523
45786
|
/**
|
|
45524
45787
|
* Change the anchor of the selection active cell to an absolute col and row index.
|
|
@@ -47490,6 +47753,9 @@
|
|
|
47490
47753
|
bottom: Math.max(anchorRow, row),
|
|
47491
47754
|
};
|
|
47492
47755
|
const expandedZone = this.getters.expandZone(sheetId, zone);
|
|
47756
|
+
if (isEqual(this.anchor.zone, expandedZone)) {
|
|
47757
|
+
return new DispatchResult("NoChanges" /* CommandResult.NoChanges */);
|
|
47758
|
+
}
|
|
47493
47759
|
const anchor = { zone: expandedZone, cell: { col: anchorCol, row: anchorRow } };
|
|
47494
47760
|
return this.processEvent({
|
|
47495
47761
|
mode: "updateAnchor",
|
|
@@ -47510,6 +47776,22 @@
|
|
|
47510
47776
|
mode: "newAnchor",
|
|
47511
47777
|
});
|
|
47512
47778
|
}
|
|
47779
|
+
/**
|
|
47780
|
+
* Triggered on mouse up to finalize the selection.
|
|
47781
|
+
* - If the current anchor zone already exists in the selection, it will be removed.
|
|
47782
|
+
* - If the anchor zone overlaps with existing zones, it will be split into
|
|
47783
|
+
* multiple non-overlapping parts.
|
|
47784
|
+
*/
|
|
47785
|
+
commitSelection() {
|
|
47786
|
+
return this.processEvent({
|
|
47787
|
+
options: {
|
|
47788
|
+
scrollIntoView: false,
|
|
47789
|
+
unbounded: true,
|
|
47790
|
+
},
|
|
47791
|
+
anchor: this.anchor,
|
|
47792
|
+
mode: "commitSelection",
|
|
47793
|
+
});
|
|
47794
|
+
}
|
|
47513
47795
|
/**
|
|
47514
47796
|
* Increase or decrease the size of the current anchor zone.
|
|
47515
47797
|
* The anchor cell remains where it is. It's the opposite side
|
|
@@ -51024,8 +51306,8 @@
|
|
|
51024
51306
|
|
|
51025
51307
|
|
|
51026
51308
|
__info__.version = "19.1.0-alpha.3";
|
|
51027
|
-
__info__.date = "2025-
|
|
51028
|
-
__info__.hash = "
|
|
51309
|
+
__info__.date = "2025-12-02T05:34:07.213Z";
|
|
51310
|
+
__info__.hash = "04cf666";
|
|
51029
51311
|
|
|
51030
51312
|
|
|
51031
51313
|
})(this.o_spreadsheet_engine = this.o_spreadsheet_engine || {});
|