@odoo/o-spreadsheet 17.4.0-alpha.11 → 17.4.0-alpha.13
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 +756 -279
- package/dist/o-spreadsheet.d.ts +55 -27
- package/dist/o-spreadsheet.esm.js +756 -279
- package/dist/o-spreadsheet.iife.js +756 -279
- package/dist/o-spreadsheet.iife.min.js +345 -345
- package/dist/o_spreadsheet.xml +6 -6
- package/package.json +2 -2
- package/readme.md +2 -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 17.4.0-alpha.
|
|
6
|
-
* @date 2024-07-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.4.0-alpha.13
|
|
6
|
+
* @date 2024-07-11T06:36:58.556Z
|
|
7
|
+
* @hash e0f506b
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -590,7 +590,7 @@ function getAddHeaderStartIndex(position, base) {
|
|
|
590
590
|
/**
|
|
591
591
|
* Compares two objects.
|
|
592
592
|
*/
|
|
593
|
-
function deepEquals(o1, o2
|
|
593
|
+
function deepEquals(o1, o2) {
|
|
594
594
|
if (o1 === o2)
|
|
595
595
|
return true;
|
|
596
596
|
if ((o1 && !o2) || (o2 && !o1))
|
|
@@ -606,17 +606,13 @@ function deepEquals(o1, o2, ignoreFunctions) {
|
|
|
606
606
|
}
|
|
607
607
|
}
|
|
608
608
|
for (const key in o1) {
|
|
609
|
-
|
|
610
|
-
if (typeOfO1Key !== typeof o2[key])
|
|
609
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
611
610
|
return false;
|
|
612
|
-
if (
|
|
613
|
-
if (!deepEquals(o1[key], o2[key]
|
|
611
|
+
if (typeof o1[key] === "object") {
|
|
612
|
+
if (!deepEquals(o1[key], o2[key]))
|
|
614
613
|
return false;
|
|
615
614
|
}
|
|
616
615
|
else {
|
|
617
|
-
if (ignoreFunctions && typeOfO1Key === "function") {
|
|
618
|
-
continue;
|
|
619
|
-
}
|
|
620
616
|
if (o1[key] !== o2[key])
|
|
621
617
|
return false;
|
|
622
618
|
}
|
|
@@ -1803,7 +1799,7 @@ const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSepa
|
|
|
1803
1799
|
});
|
|
1804
1800
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
1805
1801
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
1806
|
-
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
|
|
1802
|
+
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
|
|
1807
1803
|
const pIntegerAndDecimals = `(?:\\d+(?:${thousandsSeparator}\\d{3,})*(?:${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
|
|
1808
1804
|
const pOnlyDecimals = `(?:${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
|
|
1809
1805
|
const pScientificFormat = "(?:e(?:\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -1836,7 +1832,7 @@ function isNumber(value, locale) {
|
|
|
1836
1832
|
return getNumberRegex(locale).test(value.trim());
|
|
1837
1833
|
}
|
|
1838
1834
|
const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
|
|
1839
|
-
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
|
|
1835
|
+
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
|
|
1840
1836
|
});
|
|
1841
1837
|
/**
|
|
1842
1838
|
* Convert a string into a number. It assumes that the string actually represents
|
|
@@ -2639,11 +2635,11 @@ function generateMatrix(nColumns, nRows, callback) {
|
|
|
2639
2635
|
}
|
|
2640
2636
|
return returned;
|
|
2641
2637
|
}
|
|
2642
|
-
function matrixMap(matrix,
|
|
2638
|
+
function matrixMap(matrix, callback) {
|
|
2643
2639
|
if (matrix.length === 0) {
|
|
2644
2640
|
return [];
|
|
2645
2641
|
}
|
|
2646
|
-
return generateMatrix(matrix.length, matrix[0].length, (col, row) =>
|
|
2642
|
+
return generateMatrix(matrix.length, matrix[0].length, (col, row) => callback(matrix[col][row]));
|
|
2647
2643
|
}
|
|
2648
2644
|
function matrixForEach(matrix, fn) {
|
|
2649
2645
|
const numberOfCols = matrix.length;
|
|
@@ -2743,6 +2739,9 @@ function getPredicate(descr, locale) {
|
|
|
2743
2739
|
* If the character is a special regular expression character, it is escaped with "\\".
|
|
2744
2740
|
*/
|
|
2745
2741
|
const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
|
|
2742
|
+
if (operand === "*") {
|
|
2743
|
+
return /.+/;
|
|
2744
|
+
}
|
|
2746
2745
|
let exp = "";
|
|
2747
2746
|
let predecessor = "";
|
|
2748
2747
|
for (let char of operand) {
|
|
@@ -2766,9 +2765,9 @@ const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
|
|
|
2766
2765
|
}
|
|
2767
2766
|
return new RegExp("^" + exp + "$", "i");
|
|
2768
2767
|
});
|
|
2769
|
-
function evaluatePredicate(value, criterion) {
|
|
2768
|
+
function evaluatePredicate(value = "", criterion) {
|
|
2770
2769
|
const { operator, operand } = criterion;
|
|
2771
|
-
if (
|
|
2770
|
+
if (operand === undefined || value === null || operand === null) {
|
|
2772
2771
|
return false;
|
|
2773
2772
|
}
|
|
2774
2773
|
if (typeof operand === "number" && operator === "=") {
|
|
@@ -5860,19 +5859,22 @@ class TokenizingChars {
|
|
|
5860
5859
|
}
|
|
5861
5860
|
|
|
5862
5861
|
function isValidLocale(locale) {
|
|
5863
|
-
if (!
|
|
5864
|
-
typeof locale
|
|
5865
|
-
typeof locale.
|
|
5866
|
-
typeof locale.code === "string" &&
|
|
5867
|
-
typeof locale.thousandsSeparator === "string" &&
|
|
5868
|
-
typeof locale.decimalSeparator === "string" &&
|
|
5869
|
-
typeof locale.dateFormat === "string" &&
|
|
5870
|
-
typeof locale.timeFormat === "string" &&
|
|
5871
|
-
typeof locale.formulaArgSeparator === "string")) {
|
|
5862
|
+
if (!locale ||
|
|
5863
|
+
typeof locale !== "object" ||
|
|
5864
|
+
!(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
|
|
5872
5865
|
return false;
|
|
5873
5866
|
}
|
|
5874
|
-
|
|
5875
|
-
|
|
5867
|
+
for (const property of [
|
|
5868
|
+
"code",
|
|
5869
|
+
"name",
|
|
5870
|
+
"decimalSeparator",
|
|
5871
|
+
"dateFormat",
|
|
5872
|
+
"timeFormat",
|
|
5873
|
+
"formulaArgSeparator",
|
|
5874
|
+
]) {
|
|
5875
|
+
if (!locale[property] || typeof locale[property] !== "string") {
|
|
5876
|
+
return false;
|
|
5877
|
+
}
|
|
5876
5878
|
}
|
|
5877
5879
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
5878
5880
|
return false;
|
|
@@ -5970,7 +5972,10 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
5970
5972
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
5971
5973
|
return content;
|
|
5972
5974
|
}
|
|
5973
|
-
|
|
5975
|
+
if (locale.thousandsSeparator) {
|
|
5976
|
+
content = content.replaceAll(locale.thousandsSeparator, "");
|
|
5977
|
+
}
|
|
5978
|
+
return content.replace(locale.decimalSeparator, ".");
|
|
5974
5979
|
}
|
|
5975
5980
|
/**
|
|
5976
5981
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -6322,7 +6327,7 @@ const quarterNumberAdapter = {
|
|
|
6322
6327
|
},
|
|
6323
6328
|
toValueAndFormat(normalizedValue) {
|
|
6324
6329
|
return {
|
|
6325
|
-
value:
|
|
6330
|
+
value: _t("Q%(quarter_number)s", { quarter_number: normalizedValue }),
|
|
6326
6331
|
format: "0",
|
|
6327
6332
|
};
|
|
6328
6333
|
},
|
|
@@ -6452,9 +6457,9 @@ function getMaxObjectId(o) {
|
|
|
6452
6457
|
}
|
|
6453
6458
|
const ALL_PERIODS = {
|
|
6454
6459
|
year: _t("Year"),
|
|
6455
|
-
quarter: _t("Quarter"),
|
|
6456
|
-
month: _t("Month"),
|
|
6457
|
-
week: _t("Week"),
|
|
6460
|
+
quarter: _t("Quarter & Year"),
|
|
6461
|
+
month: _t("Month & Year"),
|
|
6462
|
+
week: _t("Week & Year"),
|
|
6458
6463
|
day: _t("Day"),
|
|
6459
6464
|
quarter_number: _t("Quarter"),
|
|
6460
6465
|
month_number: _t("Month"),
|
|
@@ -6606,7 +6611,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
6606
6611
|
const pivotId = this.getters.getPivotIdFromPosition(position);
|
|
6607
6612
|
const spreader = this.getters.getArrayFormulaSpreadingOn(position);
|
|
6608
6613
|
if (pivotId) {
|
|
6609
|
-
if (!deepEquals(spreader, position) || !isCopyingOneCell) {
|
|
6614
|
+
if (spreader && (!deepEquals(spreader, position) || !isCopyingOneCell)) {
|
|
6610
6615
|
const pivotCell = this.getters.getPivotCellFromPosition(position);
|
|
6611
6616
|
const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
|
|
6612
6617
|
const pivotFormula = createPivotFormula(formulaPivotId, pivotCell);
|
|
@@ -7411,6 +7416,146 @@ function transformRangeData(range, executed) {
|
|
|
7411
7416
|
return undefined;
|
|
7412
7417
|
}
|
|
7413
7418
|
|
|
7419
|
+
var State;
|
|
7420
|
+
(function (State) {
|
|
7421
|
+
/**
|
|
7422
|
+
* Initial state.
|
|
7423
|
+
* Expecting any reference for the left part of a range
|
|
7424
|
+
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7425
|
+
*/
|
|
7426
|
+
State[State["LeftRef"] = 0] = "LeftRef";
|
|
7427
|
+
/**
|
|
7428
|
+
* Expecting any reference for the right part of a range
|
|
7429
|
+
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7430
|
+
*/
|
|
7431
|
+
State[State["RightRef"] = 1] = "RightRef";
|
|
7432
|
+
/**
|
|
7433
|
+
* Expecting the separator without any constraint on the right part
|
|
7434
|
+
*/
|
|
7435
|
+
State[State["Separator"] = 2] = "Separator";
|
|
7436
|
+
/**
|
|
7437
|
+
* Expecting the separator for a full column range
|
|
7438
|
+
*/
|
|
7439
|
+
State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
|
|
7440
|
+
/**
|
|
7441
|
+
* Expecting the separator for a full row range
|
|
7442
|
+
*/
|
|
7443
|
+
State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
|
|
7444
|
+
/**
|
|
7445
|
+
* Expecting the right part of a full column range
|
|
7446
|
+
* e.g. "1", "A1"
|
|
7447
|
+
*/
|
|
7448
|
+
State[State["RightColumnRef"] = 5] = "RightColumnRef";
|
|
7449
|
+
/**
|
|
7450
|
+
* Expecting the right part of a full row range
|
|
7451
|
+
* e.g. "A", "A1"
|
|
7452
|
+
*/
|
|
7453
|
+
State[State["RightRowRef"] = 6] = "RightRowRef";
|
|
7454
|
+
/**
|
|
7455
|
+
* Final state. A range has been matched
|
|
7456
|
+
*/
|
|
7457
|
+
State[State["Found"] = 7] = "Found";
|
|
7458
|
+
})(State || (State = {}));
|
|
7459
|
+
const goTo = (state, guard = () => true) => [
|
|
7460
|
+
{
|
|
7461
|
+
goTo: state,
|
|
7462
|
+
guard,
|
|
7463
|
+
},
|
|
7464
|
+
];
|
|
7465
|
+
const goToMulti = (state, guard = () => true) => ({
|
|
7466
|
+
goTo: state,
|
|
7467
|
+
guard,
|
|
7468
|
+
});
|
|
7469
|
+
const machine = {
|
|
7470
|
+
[State.LeftRef]: {
|
|
7471
|
+
REFERENCE: goTo(State.Separator),
|
|
7472
|
+
NUMBER: goTo(State.FullRowSeparator),
|
|
7473
|
+
SYMBOL: [
|
|
7474
|
+
goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
|
|
7475
|
+
goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
|
|
7476
|
+
],
|
|
7477
|
+
},
|
|
7478
|
+
[State.FullColumnSeparator]: {
|
|
7479
|
+
SPACE: goTo(State.FullColumnSeparator),
|
|
7480
|
+
OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
|
|
7481
|
+
},
|
|
7482
|
+
[State.FullRowSeparator]: {
|
|
7483
|
+
SPACE: goTo(State.FullRowSeparator),
|
|
7484
|
+
OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
|
|
7485
|
+
},
|
|
7486
|
+
[State.Separator]: {
|
|
7487
|
+
SPACE: goTo(State.Separator),
|
|
7488
|
+
OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
|
|
7489
|
+
},
|
|
7490
|
+
[State.RightRef]: {
|
|
7491
|
+
SPACE: goTo(State.RightRef),
|
|
7492
|
+
NUMBER: goTo(State.Found),
|
|
7493
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7494
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
7495
|
+
},
|
|
7496
|
+
[State.RightColumnRef]: {
|
|
7497
|
+
SPACE: goTo(State.RightColumnRef),
|
|
7498
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
7499
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7500
|
+
},
|
|
7501
|
+
[State.RightRowRef]: {
|
|
7502
|
+
SPACE: goTo(State.RightRowRef),
|
|
7503
|
+
NUMBER: goTo(State.Found),
|
|
7504
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7505
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
7506
|
+
},
|
|
7507
|
+
[State.Found]: {},
|
|
7508
|
+
};
|
|
7509
|
+
/**
|
|
7510
|
+
* Check if the list of tokens starts with a sequence of tokens representing
|
|
7511
|
+
* a range.
|
|
7512
|
+
* If a range is found, the sequence is removed from the list and is returned
|
|
7513
|
+
* as a single token.
|
|
7514
|
+
*/
|
|
7515
|
+
function matchReference(tokens) {
|
|
7516
|
+
let head = 0;
|
|
7517
|
+
let transitions = machine[State.LeftRef];
|
|
7518
|
+
let matchedTokens = "";
|
|
7519
|
+
while (transitions !== undefined) {
|
|
7520
|
+
const token = tokens[head++];
|
|
7521
|
+
if (!token) {
|
|
7522
|
+
return null;
|
|
7523
|
+
}
|
|
7524
|
+
const transition = transitions[token.type]?.find((transition) => transition.guard(token));
|
|
7525
|
+
const nextState = transition ? transition.goTo : undefined;
|
|
7526
|
+
switch (nextState) {
|
|
7527
|
+
case undefined:
|
|
7528
|
+
return null;
|
|
7529
|
+
case State.Found:
|
|
7530
|
+
matchedTokens += token.value;
|
|
7531
|
+
tokens.splice(0, head);
|
|
7532
|
+
return {
|
|
7533
|
+
type: "REFERENCE",
|
|
7534
|
+
value: matchedTokens,
|
|
7535
|
+
};
|
|
7536
|
+
default:
|
|
7537
|
+
transitions = machine[nextState];
|
|
7538
|
+
matchedTokens += token.value;
|
|
7539
|
+
break;
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
return null;
|
|
7543
|
+
}
|
|
7544
|
+
/**
|
|
7545
|
+
* Take the result of the tokenizer and transform it to be usable in the
|
|
7546
|
+
* manipulations of range
|
|
7547
|
+
*
|
|
7548
|
+
* @param formula
|
|
7549
|
+
*/
|
|
7550
|
+
function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
|
|
7551
|
+
const tokens = tokenize(formula, locale);
|
|
7552
|
+
const result = [];
|
|
7553
|
+
while (tokens.length) {
|
|
7554
|
+
result.push(matchReference(tokens) || tokens.shift());
|
|
7555
|
+
}
|
|
7556
|
+
return result;
|
|
7557
|
+
}
|
|
7558
|
+
|
|
7414
7559
|
const functionRegex = /[a-zA-Z0-9\_]+(\.[a-zA-Z0-9\_]+)*/;
|
|
7415
7560
|
const UNARY_OPERATORS_PREFIX = ["-", "+"];
|
|
7416
7561
|
const UNARY_OPERATORS_POSTFIX = ["%"];
|
|
@@ -7559,7 +7704,7 @@ function parseExpression(tokens, parent_priority = 0) {
|
|
|
7559
7704
|
* Parse an expression (as a string) into an AST.
|
|
7560
7705
|
*/
|
|
7561
7706
|
function parse(str) {
|
|
7562
|
-
return parseTokens(
|
|
7707
|
+
return parseTokens(rangeTokenize(str));
|
|
7563
7708
|
}
|
|
7564
7709
|
function parseTokens(tokens) {
|
|
7565
7710
|
tokens = tokens.filter((x) => x.type !== "SPACE");
|
|
@@ -7695,146 +7840,6 @@ function rightOperandToFormula(operationAST) {
|
|
|
7695
7840
|
return needParenthesis ? `(${astToFormula(rightOperation)})` : astToFormula(rightOperation);
|
|
7696
7841
|
}
|
|
7697
7842
|
|
|
7698
|
-
var State;
|
|
7699
|
-
(function (State) {
|
|
7700
|
-
/**
|
|
7701
|
-
* Initial state.
|
|
7702
|
-
* Expecting any reference for the left part of a range
|
|
7703
|
-
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7704
|
-
*/
|
|
7705
|
-
State[State["LeftRef"] = 0] = "LeftRef";
|
|
7706
|
-
/**
|
|
7707
|
-
* Expecting any reference for the right part of a range
|
|
7708
|
-
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7709
|
-
*/
|
|
7710
|
-
State[State["RightRef"] = 1] = "RightRef";
|
|
7711
|
-
/**
|
|
7712
|
-
* Expecting the separator without any constraint on the right part
|
|
7713
|
-
*/
|
|
7714
|
-
State[State["Separator"] = 2] = "Separator";
|
|
7715
|
-
/**
|
|
7716
|
-
* Expecting the separator for a full column range
|
|
7717
|
-
*/
|
|
7718
|
-
State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
|
|
7719
|
-
/**
|
|
7720
|
-
* Expecting the separator for a full row range
|
|
7721
|
-
*/
|
|
7722
|
-
State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
|
|
7723
|
-
/**
|
|
7724
|
-
* Expecting the right part of a full column range
|
|
7725
|
-
* e.g. "1", "A1"
|
|
7726
|
-
*/
|
|
7727
|
-
State[State["RightColumnRef"] = 5] = "RightColumnRef";
|
|
7728
|
-
/**
|
|
7729
|
-
* Expecting the right part of a full row range
|
|
7730
|
-
* e.g. "A", "A1"
|
|
7731
|
-
*/
|
|
7732
|
-
State[State["RightRowRef"] = 6] = "RightRowRef";
|
|
7733
|
-
/**
|
|
7734
|
-
* Final state. A range has been matched
|
|
7735
|
-
*/
|
|
7736
|
-
State[State["Found"] = 7] = "Found";
|
|
7737
|
-
})(State || (State = {}));
|
|
7738
|
-
const goTo = (state, guard = () => true) => [
|
|
7739
|
-
{
|
|
7740
|
-
goTo: state,
|
|
7741
|
-
guard,
|
|
7742
|
-
},
|
|
7743
|
-
];
|
|
7744
|
-
const goToMulti = (state, guard = () => true) => ({
|
|
7745
|
-
goTo: state,
|
|
7746
|
-
guard,
|
|
7747
|
-
});
|
|
7748
|
-
const machine = {
|
|
7749
|
-
[State.LeftRef]: {
|
|
7750
|
-
REFERENCE: goTo(State.Separator),
|
|
7751
|
-
NUMBER: goTo(State.FullRowSeparator),
|
|
7752
|
-
SYMBOL: [
|
|
7753
|
-
goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
|
|
7754
|
-
goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
|
|
7755
|
-
],
|
|
7756
|
-
},
|
|
7757
|
-
[State.FullColumnSeparator]: {
|
|
7758
|
-
SPACE: goTo(State.FullColumnSeparator),
|
|
7759
|
-
OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
|
|
7760
|
-
},
|
|
7761
|
-
[State.FullRowSeparator]: {
|
|
7762
|
-
SPACE: goTo(State.FullRowSeparator),
|
|
7763
|
-
OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
|
|
7764
|
-
},
|
|
7765
|
-
[State.Separator]: {
|
|
7766
|
-
SPACE: goTo(State.Separator),
|
|
7767
|
-
OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
|
|
7768
|
-
},
|
|
7769
|
-
[State.RightRef]: {
|
|
7770
|
-
SPACE: goTo(State.RightRef),
|
|
7771
|
-
NUMBER: goTo(State.Found),
|
|
7772
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7773
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
7774
|
-
},
|
|
7775
|
-
[State.RightColumnRef]: {
|
|
7776
|
-
SPACE: goTo(State.RightColumnRef),
|
|
7777
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
7778
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7779
|
-
},
|
|
7780
|
-
[State.RightRowRef]: {
|
|
7781
|
-
SPACE: goTo(State.RightRowRef),
|
|
7782
|
-
NUMBER: goTo(State.Found),
|
|
7783
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7784
|
-
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
7785
|
-
},
|
|
7786
|
-
[State.Found]: {},
|
|
7787
|
-
};
|
|
7788
|
-
/**
|
|
7789
|
-
* Check if the list of tokens starts with a sequence of tokens representing
|
|
7790
|
-
* a range.
|
|
7791
|
-
* If a range is found, the sequence is removed from the list and is returned
|
|
7792
|
-
* as a single token.
|
|
7793
|
-
*/
|
|
7794
|
-
function matchReference(tokens) {
|
|
7795
|
-
let head = 0;
|
|
7796
|
-
let transitions = machine[State.LeftRef];
|
|
7797
|
-
let matchedTokens = "";
|
|
7798
|
-
while (transitions !== undefined) {
|
|
7799
|
-
const token = tokens[head++];
|
|
7800
|
-
if (!token) {
|
|
7801
|
-
return null;
|
|
7802
|
-
}
|
|
7803
|
-
const transition = transitions[token.type]?.find((transition) => transition.guard(token));
|
|
7804
|
-
const nextState = transition ? transition.goTo : undefined;
|
|
7805
|
-
switch (nextState) {
|
|
7806
|
-
case undefined:
|
|
7807
|
-
return null;
|
|
7808
|
-
case State.Found:
|
|
7809
|
-
matchedTokens += token.value;
|
|
7810
|
-
tokens.splice(0, head);
|
|
7811
|
-
return {
|
|
7812
|
-
type: "REFERENCE",
|
|
7813
|
-
value: matchedTokens,
|
|
7814
|
-
};
|
|
7815
|
-
default:
|
|
7816
|
-
transitions = machine[nextState];
|
|
7817
|
-
matchedTokens += token.value;
|
|
7818
|
-
break;
|
|
7819
|
-
}
|
|
7820
|
-
}
|
|
7821
|
-
return null;
|
|
7822
|
-
}
|
|
7823
|
-
/**
|
|
7824
|
-
* Take the result of the tokenizer and transform it to be usable in the
|
|
7825
|
-
* manipulations of range
|
|
7826
|
-
*
|
|
7827
|
-
* @param formula
|
|
7828
|
-
*/
|
|
7829
|
-
function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
|
|
7830
|
-
const tokens = tokenize(formula, locale);
|
|
7831
|
-
const result = [];
|
|
7832
|
-
while (tokens.length) {
|
|
7833
|
-
result.push(matchReference(tokens) || tokens.shift());
|
|
7834
|
-
}
|
|
7835
|
-
return result;
|
|
7836
|
-
}
|
|
7837
|
-
|
|
7838
7843
|
/**
|
|
7839
7844
|
* Add the following information on tokens:
|
|
7840
7845
|
* - length
|
|
@@ -8065,8 +8070,8 @@ function detectLink(value) {
|
|
|
8065
8070
|
|
|
8066
8071
|
function evaluateLiteral(literalCell, localeFormat) {
|
|
8067
8072
|
const value = localeFormat.format === PLAIN_TEXT_FORMAT ? literalCell.content : literalCell.parsedValue;
|
|
8068
|
-
const
|
|
8069
|
-
return createEvaluatedCell(
|
|
8073
|
+
const functionResult = { value, format: localeFormat.format };
|
|
8074
|
+
return createEvaluatedCell(functionResult, localeFormat.locale);
|
|
8070
8075
|
}
|
|
8071
8076
|
function parseLiteral(content, locale) {
|
|
8072
8077
|
if (content.startsWith("=")) {
|
|
@@ -8087,13 +8092,13 @@ function parseLiteral(content, locale) {
|
|
|
8087
8092
|
}
|
|
8088
8093
|
return content;
|
|
8089
8094
|
}
|
|
8090
|
-
function createEvaluatedCell(
|
|
8091
|
-
const link = detectLink(
|
|
8095
|
+
function createEvaluatedCell(functionResult, locale = DEFAULT_LOCALE, cell) {
|
|
8096
|
+
const link = detectLink(functionResult.value);
|
|
8092
8097
|
if (!link) {
|
|
8093
|
-
return _createEvaluatedCell(
|
|
8098
|
+
return _createEvaluatedCell(functionResult, locale, cell);
|
|
8094
8099
|
}
|
|
8095
8100
|
const value = parseLiteral(link.label, locale);
|
|
8096
|
-
const format =
|
|
8101
|
+
const format = functionResult.format ||
|
|
8097
8102
|
(typeof value === "number"
|
|
8098
8103
|
? detectDateFormat(link.label, locale) || detectNumberFormat(link.label)
|
|
8099
8104
|
: undefined);
|
|
@@ -8106,8 +8111,8 @@ function createEvaluatedCell(fPayload, locale = DEFAULT_LOCALE, cell) {
|
|
|
8106
8111
|
link,
|
|
8107
8112
|
};
|
|
8108
8113
|
}
|
|
8109
|
-
function _createEvaluatedCell(
|
|
8110
|
-
let { value, format, message } =
|
|
8114
|
+
function _createEvaluatedCell(functionResult, locale, cell) {
|
|
8115
|
+
let { value, format, message } = functionResult;
|
|
8111
8116
|
format = cell?.format || format;
|
|
8112
8117
|
const formattedValue = formatValue(value, { format, locale });
|
|
8113
8118
|
if (isEvaluationError(value)) {
|
|
@@ -10294,7 +10299,6 @@ function getNextNonEmptyBar(bars, startIndex) {
|
|
|
10294
10299
|
return bars.find((bar, i) => i > startIndex && bar.height !== 0);
|
|
10295
10300
|
}
|
|
10296
10301
|
|
|
10297
|
-
// @ts-ignore
|
|
10298
10302
|
window.Chart?.register(waterfallLinesPlugin);
|
|
10299
10303
|
class ChartJsComponent extends Component {
|
|
10300
10304
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
@@ -10327,7 +10331,7 @@ class ChartJsComponent extends Component {
|
|
|
10327
10331
|
onWillUnmount(() => this.chart?.destroy());
|
|
10328
10332
|
useEffect(() => {
|
|
10329
10333
|
const runtime = this.chartRuntime;
|
|
10330
|
-
if (
|
|
10334
|
+
if (runtime !== this.currentRuntime) {
|
|
10331
10335
|
if (runtime.chartJsConfig.type !== this.currentRuntime.chartJsConfig.type) {
|
|
10332
10336
|
this.chart?.destroy();
|
|
10333
10337
|
this.createChart(deepCopy(runtime.chartJsConfig));
|
|
@@ -10342,7 +10346,6 @@ class ChartJsComponent extends Component {
|
|
|
10342
10346
|
createChart(chartData) {
|
|
10343
10347
|
const canvas = this.canvas.el;
|
|
10344
10348
|
const ctx = canvas.getContext("2d");
|
|
10345
|
-
// @ts-ignore
|
|
10346
10349
|
this.chart = new window.Chart(ctx, chartData);
|
|
10347
10350
|
}
|
|
10348
10351
|
updateChartJs(chartRuntime) {
|
|
@@ -19094,7 +19097,7 @@ const PIVOT = {
|
|
|
19094
19097
|
arg("include_column_titles (boolean, default=TRUE)", _t("Whether to include the column titles or not.")),
|
|
19095
19098
|
arg("column_count (number, optional)", _t("number of columns")),
|
|
19096
19099
|
],
|
|
19097
|
-
compute: function (pivotFormulaId, rowCount = { value:
|
|
19100
|
+
compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }, columnCount = { value: Number.MAX_VALUE }) {
|
|
19098
19101
|
const _pivotFormulaId = toString(pivotFormulaId);
|
|
19099
19102
|
const _rowCount = toNumber(rowCount, this.locale);
|
|
19100
19103
|
if (_rowCount < 0) {
|
|
@@ -19518,6 +19521,320 @@ var operators = /*#__PURE__*/Object.freeze({
|
|
|
19518
19521
|
UPLUS: UPLUS
|
|
19519
19522
|
});
|
|
19520
19523
|
|
|
19524
|
+
const transformFromFactor = (factor) => ({
|
|
19525
|
+
transform: (x) => x * factor,
|
|
19526
|
+
inverseTransform: (x) => x / factor,
|
|
19527
|
+
});
|
|
19528
|
+
const standard = { transform: (x) => x, inverseTransform: (x) => x };
|
|
19529
|
+
const ANG2M = 1e-10;
|
|
19530
|
+
const IN2M = 0.0254;
|
|
19531
|
+
const PICAPT2M = IN2M / 72;
|
|
19532
|
+
const FT2M = 0.3048;
|
|
19533
|
+
const YD2M = 0.9144;
|
|
19534
|
+
const MI2M = 1609.34;
|
|
19535
|
+
const NMI2M = 1852;
|
|
19536
|
+
const LY2M = 9.46073047258e15;
|
|
19537
|
+
const UNITS = {
|
|
19538
|
+
// WEIGHT UNITs : Standard = gramme
|
|
19539
|
+
g: { ...standard, category: "weight" },
|
|
19540
|
+
u: { ...transformFromFactor(1.66053e-24), category: "weight" },
|
|
19541
|
+
grain: { ...transformFromFactor(0.0647989), category: "weight" },
|
|
19542
|
+
ozm: { ...transformFromFactor(28.3495), category: "weight" },
|
|
19543
|
+
lbm: { ...transformFromFactor(453.592), category: "weight" },
|
|
19544
|
+
stone: { ...transformFromFactor(6350.29), category: "weight" },
|
|
19545
|
+
sg: { ...transformFromFactor(14593.90294), category: "weight" },
|
|
19546
|
+
cwt: { ...transformFromFactor(45359.237), category: "weight" },
|
|
19547
|
+
uk_cwt: { ...transformFromFactor(50802.3), category: "weight" },
|
|
19548
|
+
ton: { ...transformFromFactor(907184.74), category: "weight" },
|
|
19549
|
+
uk_ton: { ...transformFromFactor(1016046.9), category: "weight" },
|
|
19550
|
+
// DISTANCE UNITS : Standard = meter
|
|
19551
|
+
m: { ...standard, category: "distance" },
|
|
19552
|
+
km: { ...transformFromFactor(1000), category: "distance" },
|
|
19553
|
+
ang: { ...transformFromFactor(ANG2M), category: "distance" },
|
|
19554
|
+
Picapt: { ...transformFromFactor(PICAPT2M), category: "distance" },
|
|
19555
|
+
pica: { ...transformFromFactor(IN2M / 6), category: "distance" },
|
|
19556
|
+
in: { ...transformFromFactor(IN2M), category: "distance" },
|
|
19557
|
+
ft: { ...transformFromFactor(FT2M), category: "distance" },
|
|
19558
|
+
yd: { ...transformFromFactor(YD2M), category: "distance" },
|
|
19559
|
+
ell: { ...transformFromFactor(1.143), category: "distance" },
|
|
19560
|
+
mi: { ...transformFromFactor(MI2M), category: "distance" },
|
|
19561
|
+
survey_mi: { ...transformFromFactor(1609.34), category: "distance" },
|
|
19562
|
+
Nmi: { ...transformFromFactor(NMI2M), category: "distance" },
|
|
19563
|
+
ly: { ...transformFromFactor(LY2M), category: "distance" },
|
|
19564
|
+
parsec: { ...transformFromFactor(3.0856775814914e16), category: "distance" },
|
|
19565
|
+
// TIME UNITS : Standard = second
|
|
19566
|
+
sec: { ...standard, category: "time" },
|
|
19567
|
+
min: { ...transformFromFactor(60), category: "time" },
|
|
19568
|
+
hr: { ...transformFromFactor(3600), category: "time" },
|
|
19569
|
+
day: { ...transformFromFactor(86400), category: "time" },
|
|
19570
|
+
yr: { ...transformFromFactor(31556952), category: "time" },
|
|
19571
|
+
// PRESSURE UNITS : Standard = Pascal
|
|
19572
|
+
Pa: { ...standard, category: "pressure" },
|
|
19573
|
+
bar: { ...transformFromFactor(100000), category: "pressure" },
|
|
19574
|
+
mmHg: { ...transformFromFactor(133.322), category: "pressure" },
|
|
19575
|
+
Torr: { ...transformFromFactor(133.322), category: "pressure" },
|
|
19576
|
+
psi: { ...transformFromFactor(6894.76), category: "pressure" },
|
|
19577
|
+
atm: { ...transformFromFactor(101325), category: "pressure" },
|
|
19578
|
+
// FORCE UNITS : Standard = Newton
|
|
19579
|
+
N: { ...standard, category: "force" },
|
|
19580
|
+
dyn: { ...transformFromFactor(1e-5), category: "force" },
|
|
19581
|
+
pond: { ...transformFromFactor(0.00980665), category: "force" },
|
|
19582
|
+
lbf: { ...transformFromFactor(4.44822), category: "force" },
|
|
19583
|
+
// ENERGY UNITS : Standard = Joule
|
|
19584
|
+
J: { ...standard, category: "energy" },
|
|
19585
|
+
eV: { ...transformFromFactor(1.60218e-19), category: "energy" },
|
|
19586
|
+
e: { ...transformFromFactor(1e-7), category: "energy" },
|
|
19587
|
+
flb: { ...transformFromFactor(1.3558179483), category: "energy" },
|
|
19588
|
+
c: { ...transformFromFactor(4.184), category: "energy" },
|
|
19589
|
+
cal: { ...transformFromFactor(4.1868), category: "energy" },
|
|
19590
|
+
BTU: { ...transformFromFactor(1055.06), category: "energy" },
|
|
19591
|
+
Wh: { ...transformFromFactor(3600), category: "energy" },
|
|
19592
|
+
HPh: { ...transformFromFactor(2684520), category: "energy" },
|
|
19593
|
+
// POWER UNITS : Standard = Watt
|
|
19594
|
+
W: { ...standard, category: "power" },
|
|
19595
|
+
PS: { ...transformFromFactor(735.499), category: "power" },
|
|
19596
|
+
HP: { ...transformFromFactor(745.7), category: "power" },
|
|
19597
|
+
// MAGNETISM UNITS : Standard = Tesla
|
|
19598
|
+
T: { ...standard, category: "magnetism" },
|
|
19599
|
+
ga: { ...transformFromFactor(1e-4), category: "magnetism" },
|
|
19600
|
+
// TEMPERATURE UNITS : Standard = Kelvin
|
|
19601
|
+
K: { ...standard, category: "temperature" },
|
|
19602
|
+
C: {
|
|
19603
|
+
transform: (T) => T + 273.15,
|
|
19604
|
+
inverseTransform: (T) => T - 273.15,
|
|
19605
|
+
category: "temperature",
|
|
19606
|
+
},
|
|
19607
|
+
F: {
|
|
19608
|
+
transform: (T) => ((T - 32) * 5) / 9 + 273.15,
|
|
19609
|
+
inverseTransform: (T) => ((T - 273.15) * 9) / 5 + 32,
|
|
19610
|
+
category: "temperature",
|
|
19611
|
+
},
|
|
19612
|
+
Rank: { ...transformFromFactor(5 / 9), category: "temperature" },
|
|
19613
|
+
Reau: {
|
|
19614
|
+
transform: (T) => T * 1.25 + 273.15,
|
|
19615
|
+
inverseTransform: (T) => (T - 273.15) / 1.25,
|
|
19616
|
+
category: "temperature",
|
|
19617
|
+
},
|
|
19618
|
+
// VOLUME UNITS : Standard = cubic meter
|
|
19619
|
+
"m^3": { ...standard, category: "volume", order: 3 },
|
|
19620
|
+
"ang^3": { ...transformFromFactor(Math.pow(ANG2M, 3)), category: "volume", order: 3 },
|
|
19621
|
+
"Picapt^3": { ...transformFromFactor(Math.pow(PICAPT2M, 3)), category: "volume", order: 3 },
|
|
19622
|
+
tsp: { ...transformFromFactor(4.92892e-6), category: "volume" },
|
|
19623
|
+
tspm: { ...transformFromFactor(5e-6), category: "volume" },
|
|
19624
|
+
tbs: { ...transformFromFactor(1.4786764825785619e-5), category: "volume" },
|
|
19625
|
+
"in^3": { ...transformFromFactor(Math.pow(IN2M, 3)), category: "volume", order: 3 },
|
|
19626
|
+
oz: { ...transformFromFactor(2.95735295625e-5), category: "volume" },
|
|
19627
|
+
cup: { ...transformFromFactor(0.000237), category: "volume" },
|
|
19628
|
+
pt: { ...transformFromFactor(0.0004731765), category: "volume" },
|
|
19629
|
+
uk_pt: { ...transformFromFactor(0.000568261), category: "volume" },
|
|
19630
|
+
qt: { ...transformFromFactor(0.0009463529), category: "volume" },
|
|
19631
|
+
l: { ...transformFromFactor(1e-3), category: "volume" },
|
|
19632
|
+
uk_qt: { ...transformFromFactor(0.0011365225), category: "volume" },
|
|
19633
|
+
gal: { ...transformFromFactor(0.0037854118), category: "volume" },
|
|
19634
|
+
uk_gal: { ...transformFromFactor(0.00454609), category: "volume" },
|
|
19635
|
+
"ft^3": { ...transformFromFactor(Math.pow(FT2M, 3)), category: "volume", order: 3 },
|
|
19636
|
+
bushel: { ...transformFromFactor(0.0352390704), category: "volume" },
|
|
19637
|
+
barrel: { ...transformFromFactor(0.158987295), category: "volume" },
|
|
19638
|
+
"yd^3": { ...transformFromFactor(Math.pow(YD2M, 3)), category: "volume", order: 3 },
|
|
19639
|
+
MTON: { ...transformFromFactor(1.13267386368), category: "volume" },
|
|
19640
|
+
GRT: { ...transformFromFactor(2.83168), category: "volume" },
|
|
19641
|
+
"mi^3": { ...transformFromFactor(Math.pow(MI2M, 3)), category: "volume", order: 3 },
|
|
19642
|
+
"Nmi^3": { ...transformFromFactor(Math.pow(NMI2M, 3)), category: "volume", order: 3 },
|
|
19643
|
+
"ly^3": { ...transformFromFactor(Math.pow(LY2M, 3)), category: "volume", order: 3 },
|
|
19644
|
+
// AREA UNITS : Standard = square meter
|
|
19645
|
+
"m^2": { ...standard, category: "area", order: 2 },
|
|
19646
|
+
"ang^2": { ...transformFromFactor(Math.pow(ANG2M, 2)), category: "area", order: 2 },
|
|
19647
|
+
"Picapt^2": { ...transformFromFactor(Math.pow(PICAPT2M, 2)), category: "area", order: 2 },
|
|
19648
|
+
"in^2": { ...transformFromFactor(Math.pow(IN2M, 2)), category: "area", order: 2 },
|
|
19649
|
+
"ft^2": { ...transformFromFactor(Math.pow(FT2M, 2)), category: "area", order: 2 },
|
|
19650
|
+
"yd^2": { ...transformFromFactor(Math.pow(YD2M, 2)), category: "area", order: 2 },
|
|
19651
|
+
ar: { ...transformFromFactor(100), category: "area" },
|
|
19652
|
+
Morgen: { ...transformFromFactor(2500), category: "area" },
|
|
19653
|
+
uk_acre: { ...transformFromFactor(4046.8564224), category: "area" },
|
|
19654
|
+
us_acre: { ...transformFromFactor(4046.8726098743), category: "area" },
|
|
19655
|
+
ha: { ...transformFromFactor(1e4), category: "area" },
|
|
19656
|
+
"mi^2": { ...transformFromFactor(Math.pow(MI2M, 2)), category: "area", order: 2 },
|
|
19657
|
+
"Nmi^2": { ...transformFromFactor(Math.pow(NMI2M, 2)), category: "area", order: 2 },
|
|
19658
|
+
"ly^2": { ...transformFromFactor(Math.pow(LY2M, 2)), category: "area", order: 2 },
|
|
19659
|
+
// INFORMATION UNITS : Standard = bit
|
|
19660
|
+
bit: { ...standard, category: "information" },
|
|
19661
|
+
byte: { ...transformFromFactor(8), category: "information" },
|
|
19662
|
+
// SPEED UNITS : Standard = m/s
|
|
19663
|
+
"m/s": { ...standard, category: "speed" },
|
|
19664
|
+
"m/hr": { ...transformFromFactor(1 / 3600), category: "speed" },
|
|
19665
|
+
"km/hr": { ...transformFromFactor(1 / 3.6), category: "speed" },
|
|
19666
|
+
mph: { ...transformFromFactor(0.44704), category: "speed" },
|
|
19667
|
+
kn: { ...transformFromFactor(0.5144444444), category: "speed" },
|
|
19668
|
+
admkn: { ...transformFromFactor(0.5147733333), category: "speed" },
|
|
19669
|
+
};
|
|
19670
|
+
const UNITS_ALIASES = {
|
|
19671
|
+
shweight: "cwt",
|
|
19672
|
+
lcwt: "uk_cwt",
|
|
19673
|
+
hweight: "uk_cwt",
|
|
19674
|
+
LTON: "uk_ton",
|
|
19675
|
+
brton: "uk_ton",
|
|
19676
|
+
pc: "parsec",
|
|
19677
|
+
Pica: "Picapt",
|
|
19678
|
+
d: "day",
|
|
19679
|
+
mn: "min",
|
|
19680
|
+
s: "sec",
|
|
19681
|
+
p: "Pa",
|
|
19682
|
+
at: "atm",
|
|
19683
|
+
dy: "dyn",
|
|
19684
|
+
ev: "eV",
|
|
19685
|
+
hh: "HPh",
|
|
19686
|
+
wh: "Wh",
|
|
19687
|
+
btu: "BTU",
|
|
19688
|
+
h: "HP",
|
|
19689
|
+
cel: "C",
|
|
19690
|
+
fah: "F",
|
|
19691
|
+
kel: "K",
|
|
19692
|
+
us_pt: "pt",
|
|
19693
|
+
L: "l",
|
|
19694
|
+
lt: "l",
|
|
19695
|
+
ang3: "ang^3",
|
|
19696
|
+
ft3: "ft^3",
|
|
19697
|
+
in3: "in^3",
|
|
19698
|
+
ly3: "ly^3",
|
|
19699
|
+
m3: "m^3",
|
|
19700
|
+
mi3: "mi^3",
|
|
19701
|
+
yd3: "yd^3",
|
|
19702
|
+
Nmi3: "Nmi^3",
|
|
19703
|
+
Picapt3: "Picapt^3",
|
|
19704
|
+
"Pica^3": "Picapt^3",
|
|
19705
|
+
Pica3: "Picapt^3",
|
|
19706
|
+
regton: "GRT",
|
|
19707
|
+
ang2: "ang^2",
|
|
19708
|
+
ft2: "ft^2",
|
|
19709
|
+
in2: "in^2",
|
|
19710
|
+
ly2: "ly^2",
|
|
19711
|
+
m2: "m^2",
|
|
19712
|
+
mi2: "mi^2",
|
|
19713
|
+
Nmi2: "Nmi^2",
|
|
19714
|
+
Picapt2: "Picapt^2",
|
|
19715
|
+
"Pica^2": "Picapt^2",
|
|
19716
|
+
Pica2: "Picapt^2",
|
|
19717
|
+
yd2: "yd^2",
|
|
19718
|
+
"m/h": "m/hr",
|
|
19719
|
+
"m/sec": "m/s",
|
|
19720
|
+
};
|
|
19721
|
+
const UNIT_PREFIXES = {
|
|
19722
|
+
"": 1,
|
|
19723
|
+
Y: 1e24,
|
|
19724
|
+
Z: 1e21,
|
|
19725
|
+
E: 1e18,
|
|
19726
|
+
P: 1e15,
|
|
19727
|
+
T: 1e12,
|
|
19728
|
+
G: 1e9,
|
|
19729
|
+
M: 1e6,
|
|
19730
|
+
k: 1e3,
|
|
19731
|
+
h: 1e2,
|
|
19732
|
+
da: 1e1,
|
|
19733
|
+
e: 1e1,
|
|
19734
|
+
d: 1e-1,
|
|
19735
|
+
c: 1e-2,
|
|
19736
|
+
m: 1e-3,
|
|
19737
|
+
u: 1e-6,
|
|
19738
|
+
n: 1e-9,
|
|
19739
|
+
p: 1e-12,
|
|
19740
|
+
f: 1e-15,
|
|
19741
|
+
a: 1e-18,
|
|
19742
|
+
z: 1e-21,
|
|
19743
|
+
y: 1e-21,
|
|
19744
|
+
Yi: Math.pow(2, 80),
|
|
19745
|
+
Zi: Math.pow(2, 70),
|
|
19746
|
+
Ei: Math.pow(2, 60),
|
|
19747
|
+
Pi: Math.pow(2, 50),
|
|
19748
|
+
Ti: Math.pow(2, 40),
|
|
19749
|
+
Gi: Math.pow(2, 30),
|
|
19750
|
+
Mi: Math.pow(2, 20),
|
|
19751
|
+
ki: Math.pow(2, 10),
|
|
19752
|
+
};
|
|
19753
|
+
const TRANSLATED_CATEGORIES = {
|
|
19754
|
+
weight: _t("Weight"),
|
|
19755
|
+
distance: _t("Distance"),
|
|
19756
|
+
time: _t("Time"),
|
|
19757
|
+
pressure: _t("Pressure"),
|
|
19758
|
+
force: _t("Force"),
|
|
19759
|
+
energy: _t("Energy"),
|
|
19760
|
+
power: _t("Power"),
|
|
19761
|
+
magnetism: _t("Magnetism"),
|
|
19762
|
+
temperature: _t("Temperature"),
|
|
19763
|
+
volume: _t("Volume"),
|
|
19764
|
+
area: _t("Area"),
|
|
19765
|
+
information: _t("Information"),
|
|
19766
|
+
speed: _t("Speed"),
|
|
19767
|
+
};
|
|
19768
|
+
function getTranslatedCategory(key) {
|
|
19769
|
+
return TRANSLATED_CATEGORIES[key] ?? "";
|
|
19770
|
+
}
|
|
19771
|
+
function getTransformation(key) {
|
|
19772
|
+
for (const [prefix, value] of Object.entries(UNIT_PREFIXES)) {
|
|
19773
|
+
if (prefix && !key.startsWith(prefix))
|
|
19774
|
+
continue;
|
|
19775
|
+
const _key = key.slice(prefix.length);
|
|
19776
|
+
let conversion = UNITS[_key];
|
|
19777
|
+
if (!conversion && UNITS_ALIASES[_key]) {
|
|
19778
|
+
conversion = UNITS[UNITS_ALIASES[_key]];
|
|
19779
|
+
}
|
|
19780
|
+
if (conversion) {
|
|
19781
|
+
return {
|
|
19782
|
+
...conversion,
|
|
19783
|
+
factor: conversion.order ? Math.pow(value, conversion.order) : value,
|
|
19784
|
+
};
|
|
19785
|
+
}
|
|
19786
|
+
}
|
|
19787
|
+
return;
|
|
19788
|
+
}
|
|
19789
|
+
|
|
19790
|
+
// -----------------------------------------------------------------------------
|
|
19791
|
+
// CONVERT
|
|
19792
|
+
// -----------------------------------------------------------------------------
|
|
19793
|
+
const CONVERT = {
|
|
19794
|
+
description: _t("Converts a numeric value to a different unit of measure."),
|
|
19795
|
+
args: [
|
|
19796
|
+
arg("value (number)", _t("the numeric value in start_unit to convert to end_unit")),
|
|
19797
|
+
arg("start_unit (string)", _t("The starting unit, the unit currently assigned to value")),
|
|
19798
|
+
arg("end_unit (string)", _t("The unit of measure into which to convert value")),
|
|
19799
|
+
],
|
|
19800
|
+
compute: function (value, startUnit, endUnit) {
|
|
19801
|
+
const _value = toNumber(value, this.locale);
|
|
19802
|
+
const _startUnit = toString(startUnit);
|
|
19803
|
+
const _endUnit = toString(endUnit);
|
|
19804
|
+
const startConversion = getTransformation(_startUnit);
|
|
19805
|
+
const endConversion = getTransformation(_endUnit);
|
|
19806
|
+
if (!startConversion) {
|
|
19807
|
+
return {
|
|
19808
|
+
value: CellErrorType.GenericError,
|
|
19809
|
+
message: _t("Invalid units of measure ('%s')", _startUnit),
|
|
19810
|
+
};
|
|
19811
|
+
}
|
|
19812
|
+
if (!endConversion) {
|
|
19813
|
+
return {
|
|
19814
|
+
value: CellErrorType.GenericError,
|
|
19815
|
+
message: _t("Invalid units of measure ('%s')", _endUnit),
|
|
19816
|
+
};
|
|
19817
|
+
}
|
|
19818
|
+
if (startConversion.category !== endConversion.category) {
|
|
19819
|
+
return {
|
|
19820
|
+
value: CellErrorType.GenericError,
|
|
19821
|
+
message: _t("Incompatible units of measure ('%s' vs '%s')", getTranslatedCategory(startConversion.category), getTranslatedCategory(endConversion.category)),
|
|
19822
|
+
};
|
|
19823
|
+
}
|
|
19824
|
+
return {
|
|
19825
|
+
value: endConversion.inverseTransform(startConversion.factor * startConversion.transform(_value)) /
|
|
19826
|
+
endConversion.factor,
|
|
19827
|
+
format: value?.format,
|
|
19828
|
+
};
|
|
19829
|
+
},
|
|
19830
|
+
isExported: true,
|
|
19831
|
+
};
|
|
19832
|
+
|
|
19833
|
+
var parser = /*#__PURE__*/Object.freeze({
|
|
19834
|
+
__proto__: null,
|
|
19835
|
+
CONVERT: CONVERT
|
|
19836
|
+
});
|
|
19837
|
+
|
|
19521
19838
|
const DEFAULT_STARTING_AT = 1;
|
|
19522
19839
|
/** Regex matching all the words in a string */
|
|
19523
19840
|
const wordRegex = /[A-Za-zÀ-ÖØ-öø-ÿ]+/g;
|
|
@@ -19935,6 +20252,7 @@ const categories = [
|
|
|
19935
20252
|
{ name: _t("Text"), functions: text },
|
|
19936
20253
|
{ name: _t("Engineering"), functions: engineering },
|
|
19937
20254
|
{ name: _t("Web"), functions: web },
|
|
20255
|
+
{ name: _t("Parser"), functions: parser },
|
|
19938
20256
|
];
|
|
19939
20257
|
const functionNameRegex = /^[A-Z0-9\_\.]+$/;
|
|
19940
20258
|
class FunctionRegistry extends Registry {
|
|
@@ -19946,41 +20264,127 @@ class FunctionRegistry extends Registry {
|
|
|
19946
20264
|
}
|
|
19947
20265
|
const descr = addMetaInfoFromArg(addDescr);
|
|
19948
20266
|
validateArguments(descr.args);
|
|
19949
|
-
this.mapping[name] =
|
|
20267
|
+
this.mapping[name] = createComputeFunction(descr, name);
|
|
19950
20268
|
super.add(name, descr);
|
|
19951
20269
|
return this;
|
|
19952
20270
|
}
|
|
19953
20271
|
}
|
|
19954
|
-
|
|
19955
|
-
|
|
20272
|
+
const functionRegistry = new FunctionRegistry();
|
|
20273
|
+
for (let category of categories) {
|
|
20274
|
+
const fns = category.functions;
|
|
20275
|
+
for (let name in fns) {
|
|
20276
|
+
const addDescr = fns[name];
|
|
20277
|
+
addDescr.category = addDescr.category || category.name;
|
|
20278
|
+
name = name.replace(/_/g, ".");
|
|
20279
|
+
functionRegistry.add(name, { isExported: false, ...addDescr });
|
|
20280
|
+
}
|
|
20281
|
+
}
|
|
20282
|
+
const notAvailableError = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
|
|
20283
|
+
function createComputeFunction(descr, functionName) {
|
|
20284
|
+
function runtimeCompute(...args) {
|
|
20285
|
+
try {
|
|
20286
|
+
return vectorizedCompute.apply(this, args);
|
|
20287
|
+
}
|
|
20288
|
+
catch (e) {
|
|
20289
|
+
return handleError(e, functionName);
|
|
20290
|
+
}
|
|
20291
|
+
}
|
|
20292
|
+
function vectorizedCompute(...args) {
|
|
20293
|
+
let countVectorizableCol = 1;
|
|
20294
|
+
let countVectorizableRow = 1;
|
|
20295
|
+
let vectorizableColLimit = Infinity;
|
|
20296
|
+
let vectorizableRowLimit = Infinity;
|
|
20297
|
+
let vectorArgsType = undefined;
|
|
20298
|
+
//#region Compute vectorisation limits
|
|
19956
20299
|
for (let i = 0; i < args.length; i++) {
|
|
19957
20300
|
const argDefinition = descr.args[descr.getArgToFocus(i + 1) - 1];
|
|
19958
20301
|
const arg = args[i];
|
|
19959
20302
|
if (isMatrix(arg) && !argDefinition.acceptMatrix) {
|
|
19960
|
-
if
|
|
19961
|
-
|
|
20303
|
+
// if argDefinition does not accept a matrix but arg is still a matrix
|
|
20304
|
+
// --> triggers the arguments vectorization
|
|
20305
|
+
const nColumns = arg.length;
|
|
20306
|
+
const nRows = arg[0].length;
|
|
20307
|
+
if (nColumns !== 1 || nRows !== 1) {
|
|
20308
|
+
vectorArgsType ??= new Array(args.length);
|
|
20309
|
+
if (nColumns !== 1 && nRows !== 1) {
|
|
20310
|
+
vectorArgsType[i] = "matrix";
|
|
20311
|
+
countVectorizableCol = Math.max(countVectorizableCol, nColumns);
|
|
20312
|
+
countVectorizableRow = Math.max(countVectorizableRow, nRows);
|
|
20313
|
+
vectorizableColLimit = Math.min(vectorizableColLimit, nColumns);
|
|
20314
|
+
vectorizableRowLimit = Math.min(vectorizableRowLimit, nRows);
|
|
20315
|
+
}
|
|
20316
|
+
else if (nColumns !== 1) {
|
|
20317
|
+
vectorArgsType[i] = "horizontal";
|
|
20318
|
+
countVectorizableCol = Math.max(countVectorizableCol, nColumns);
|
|
20319
|
+
vectorizableColLimit = Math.min(vectorizableColLimit, nColumns);
|
|
20320
|
+
}
|
|
20321
|
+
else if (nRows !== 1) {
|
|
20322
|
+
vectorArgsType[i] = "vertical";
|
|
20323
|
+
countVectorizableRow = Math.max(countVectorizableRow, nRows);
|
|
20324
|
+
vectorizableRowLimit = Math.min(vectorizableRowLimit, nRows);
|
|
20325
|
+
}
|
|
20326
|
+
}
|
|
20327
|
+
else {
|
|
20328
|
+
args[i] = arg[0][0];
|
|
19962
20329
|
}
|
|
19963
|
-
args[i] = arg[0][0];
|
|
19964
20330
|
}
|
|
19965
20331
|
if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
|
|
19966
20332
|
throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
|
|
19967
20333
|
}
|
|
19968
20334
|
}
|
|
19969
|
-
|
|
20335
|
+
//#endregion
|
|
20336
|
+
if (countVectorizableCol === 1 && countVectorizableRow === 1) {
|
|
20337
|
+
// either this function is not vectorized or it ends up with a 1x1 dimension
|
|
20338
|
+
return computeFunctionToObject.apply(this, args);
|
|
20339
|
+
}
|
|
20340
|
+
const getArgOffset = (i, j) => args.map((arg, index) => {
|
|
20341
|
+
switch (vectorArgsType?.[index]) {
|
|
20342
|
+
case "matrix":
|
|
20343
|
+
return arg[i][j];
|
|
20344
|
+
case "horizontal":
|
|
20345
|
+
return arg[i][0];
|
|
20346
|
+
case "vertical":
|
|
20347
|
+
return arg[0][j];
|
|
20348
|
+
case undefined:
|
|
20349
|
+
return arg;
|
|
20350
|
+
}
|
|
20351
|
+
});
|
|
20352
|
+
return generateMatrix(countVectorizableCol, countVectorizableRow, (col, row) => {
|
|
20353
|
+
if (col > vectorizableColLimit - 1 || row > vectorizableRowLimit - 1) {
|
|
20354
|
+
return notAvailableError;
|
|
20355
|
+
}
|
|
20356
|
+
const singleCellComputeResult = computeFunctionToObject.apply(this, getArgOffset(col, row));
|
|
20357
|
+
// In the case where the user tries to vectorize arguments of an array formula, we will get an
|
|
20358
|
+
// array for every combination of the vectorized arguments, which will lead to a 3D matrix and
|
|
20359
|
+
// we won't be able to return the values.
|
|
20360
|
+
// In this case, we keep the first element of each spreading part, just as Excel does, and
|
|
20361
|
+
// create an array with these parts.
|
|
20362
|
+
// For exemple, we have MUNIT(x) that return an unitary matrix of x*x. If we use it with a
|
|
20363
|
+
// range, like MUNIT(A1:A2), we will get two unitary matrices (one for the value in A1 and one
|
|
20364
|
+
// for the value in A2). In this case, we will simply take the first value of each matrix and
|
|
20365
|
+
// return the array [First value of MUNIT(A1), First value of MUNIT(A2)].
|
|
20366
|
+
return isMatrix(singleCellComputeResult)
|
|
20367
|
+
? singleCellComputeResult[0][0]
|
|
20368
|
+
: singleCellComputeResult;
|
|
20369
|
+
});
|
|
19970
20370
|
}
|
|
19971
|
-
|
|
19972
|
-
|
|
19973
|
-
|
|
19974
|
-
|
|
19975
|
-
|
|
19976
|
-
|
|
20371
|
+
function computeFunctionToObject(...args) {
|
|
20372
|
+
const result = descr.compute.apply(this, args);
|
|
20373
|
+
if (!isMatrix(result)) {
|
|
20374
|
+
if (typeof result === "object" && result !== null && "value" in result) {
|
|
20375
|
+
replaceFunctionNamePlaceholder(result, functionName);
|
|
20376
|
+
return result;
|
|
20377
|
+
}
|
|
20378
|
+
return { value: result };
|
|
19977
20379
|
}
|
|
19978
|
-
|
|
19979
|
-
|
|
20380
|
+
if (typeof result[0][0] === "object" && result[0][0] !== null && "value" in result[0][0]) {
|
|
20381
|
+
matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, functionName));
|
|
20382
|
+
return result;
|
|
19980
20383
|
}
|
|
19981
|
-
|
|
20384
|
+
return matrixMap(result, (row) => ({ value: row }));
|
|
20385
|
+
}
|
|
20386
|
+
return runtimeCompute;
|
|
19982
20387
|
}
|
|
19983
|
-
const implementationErrorMessage = _t("An unexpected error occurred. Submit a support ticket at odoo.com/help.");
|
|
19984
20388
|
function handleError(e, functionName) {
|
|
19985
20389
|
// the error could be an user error (instance of EvaluationError)
|
|
19986
20390
|
// or a javascript error (instance of Error)
|
|
@@ -19999,42 +20403,16 @@ function hasStringValue(obj) {
|
|
|
19999
20403
|
return (obj?.value !== undefined &&
|
|
20000
20404
|
typeof obj.value === "string");
|
|
20001
20405
|
}
|
|
20002
|
-
function
|
|
20003
|
-
return (obj?.message !== undefined &&
|
|
20004
|
-
typeof obj.message === "string");
|
|
20005
|
-
}
|
|
20006
|
-
function addResultHandling(compute, functionName) {
|
|
20007
|
-
return function computeWithResultHandling(...args) {
|
|
20008
|
-
const result = compute.apply(this, args);
|
|
20009
|
-
if (!isMatrix(result)) {
|
|
20010
|
-
if (typeof result === "object" && result !== null && "value" in result) {
|
|
20011
|
-
replaceFunctionNamePlaceholder(result, functionName);
|
|
20012
|
-
return result;
|
|
20013
|
-
}
|
|
20014
|
-
return { value: result };
|
|
20015
|
-
}
|
|
20016
|
-
if (typeof result[0][0] === "object" && result[0][0] !== null && "value" in result[0][0]) {
|
|
20017
|
-
matrixForEach(result, (result) => replaceFunctionNamePlaceholder(result, functionName));
|
|
20018
|
-
return result;
|
|
20019
|
-
}
|
|
20020
|
-
return matrixMap(result, (row) => ({ value: row }));
|
|
20021
|
-
};
|
|
20022
|
-
}
|
|
20023
|
-
function replaceFunctionNamePlaceholder(fPayload, functionName) {
|
|
20406
|
+
function replaceFunctionNamePlaceholder(functionResult, functionName) {
|
|
20024
20407
|
// for performance reasons: change in place and only if needed
|
|
20025
|
-
if (
|
|
20026
|
-
|
|
20408
|
+
if (functionResult.message?.includes("[[FUNCTION_NAME]]")) {
|
|
20409
|
+
functionResult.message = functionResult.message.replace("[[FUNCTION_NAME]]", functionName);
|
|
20027
20410
|
}
|
|
20028
20411
|
}
|
|
20029
|
-
const
|
|
20030
|
-
|
|
20031
|
-
|
|
20032
|
-
|
|
20033
|
-
const addDescr = fns[name];
|
|
20034
|
-
addDescr.category = addDescr.category || category.name;
|
|
20035
|
-
name = name.replace(/_/g, ".");
|
|
20036
|
-
functionRegistry.add(name, { isExported: false, ...addDescr });
|
|
20037
|
-
}
|
|
20412
|
+
const implementationErrorMessage = _t("An unexpected error occurred. Submit a support ticket at odoo.com/help.");
|
|
20413
|
+
function hasStringMessage(obj) {
|
|
20414
|
+
return (obj?.message !== undefined &&
|
|
20415
|
+
typeof obj.message === "string");
|
|
20038
20416
|
}
|
|
20039
20417
|
|
|
20040
20418
|
autoCompleteProviders.add("functions", {
|
|
@@ -21483,6 +21861,7 @@ function indentCode(code) {
|
|
|
21483
21861
|
|
|
21484
21862
|
const functions$1 = functionRegistry.content;
|
|
21485
21863
|
const OPERATOR_MAP = {
|
|
21864
|
+
// export for test
|
|
21486
21865
|
"=": "EQ",
|
|
21487
21866
|
"+": "ADD",
|
|
21488
21867
|
"-": "MINUS",
|
|
@@ -21497,6 +21876,7 @@ const OPERATOR_MAP = {
|
|
|
21497
21876
|
"&": "CONCATENATE",
|
|
21498
21877
|
};
|
|
21499
21878
|
const UNARY_OPERATOR_MAP = {
|
|
21879
|
+
// export for test
|
|
21500
21880
|
"-": "UMINUS",
|
|
21501
21881
|
"+": "UPLUS",
|
|
21502
21882
|
"%": "UNARY.PERCENT",
|
|
@@ -22785,8 +23165,7 @@ function truncateLabel(label) {
|
|
|
22785
23165
|
/**
|
|
22786
23166
|
* Get a default chart js configuration
|
|
22787
23167
|
*/
|
|
22788
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor,
|
|
22789
|
-
const { format, locale, truncateLabels, horizontalChart } = args;
|
|
23168
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true, horizontalChart, }) {
|
|
22790
23169
|
const chartTitle = chart.title.text ? chart.title : { ...chart.title, content: "" };
|
|
22791
23170
|
const options = {
|
|
22792
23171
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
@@ -22962,7 +23341,6 @@ function chartToImage(runtime, figure, type) {
|
|
|
22962
23341
|
if ("chartJsConfig" in runtime) {
|
|
22963
23342
|
const config = deepCopy(runtime.chartJsConfig);
|
|
22964
23343
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
22965
|
-
// @ts-ignore
|
|
22966
23344
|
const chart = new window.Chart(canvas, config);
|
|
22967
23345
|
const imgContent = chart.toBase64Image();
|
|
22968
23346
|
chart.destroy();
|
|
@@ -23883,13 +24261,11 @@ function canBeLinearChart(labelRange, getters) {
|
|
|
23883
24261
|
}
|
|
23884
24262
|
let missingTimeAdapterAlreadyWarned = false;
|
|
23885
24263
|
function isLuxonTimeAdapterInstalled() {
|
|
23886
|
-
// @ts-ignore
|
|
23887
24264
|
if (!window.Chart) {
|
|
23888
24265
|
return false;
|
|
23889
24266
|
}
|
|
23890
24267
|
// @ts-ignore
|
|
23891
24268
|
const adapter = new window.Chart._adapters._date({});
|
|
23892
|
-
// @ts-ignore
|
|
23893
24269
|
const isInstalled = adapter._id === "luxon";
|
|
23894
24270
|
if (!isInstalled && !missingTimeAdapterAlreadyWarned) {
|
|
23895
24271
|
missingTimeAdapterAlreadyWarned = true;
|
|
@@ -23906,9 +24282,7 @@ function getLineOrScatterConfiguration(chart, labels, options) {
|
|
|
23906
24282
|
generateLabels(chart) {
|
|
23907
24283
|
// color the legend labels with the dataset color, without any transparency
|
|
23908
24284
|
const { data } = chart;
|
|
23909
|
-
|
|
23910
|
-
const labels = window.Chart.defaults.plugins.legend.labels
|
|
23911
|
-
.generateLabels(chart);
|
|
24285
|
+
const labels = window.Chart.defaults.plugins.legend.labels.generateLabels(chart);
|
|
23912
24286
|
for (const [index, label] of labels.entries()) {
|
|
23913
24287
|
label.fillStyle = data.datasets[index].borderColor;
|
|
23914
24288
|
}
|
|
@@ -24025,10 +24399,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
24025
24399
|
const colors = new ColorGenerator();
|
|
24026
24400
|
const definition = chart.getDefinition();
|
|
24027
24401
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
24028
|
-
if (["linear", "time"].includes(axisType)) {
|
|
24029
|
-
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
24030
|
-
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
24031
|
-
}
|
|
24032
24402
|
const color = colors.next();
|
|
24033
24403
|
let backgroundRGBA = colorToRGBA(color);
|
|
24034
24404
|
if (areaChart) {
|
|
@@ -24044,6 +24414,10 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
24044
24414
|
return value;
|
|
24045
24415
|
});
|
|
24046
24416
|
}
|
|
24417
|
+
if (["linear", "time"].includes(axisType)) {
|
|
24418
|
+
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
24419
|
+
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
24420
|
+
}
|
|
24047
24421
|
const backgroundColor = rgbaToHex(backgroundRGBA);
|
|
24048
24422
|
const dataset = {
|
|
24049
24423
|
label,
|
|
@@ -33150,21 +33524,25 @@ function useHoveredElement(ref) {
|
|
|
33150
33524
|
|
|
33151
33525
|
function useHighlightsOnHover(ref, highlightProvider) {
|
|
33152
33526
|
const hoverState = useHoveredElement(ref);
|
|
33153
|
-
const stores = useStoreProvider();
|
|
33154
33527
|
useHighlights({
|
|
33155
33528
|
get highlights() {
|
|
33156
33529
|
return hoverState.hovered ? highlightProvider.highlights : [];
|
|
33157
33530
|
},
|
|
33158
33531
|
});
|
|
33159
|
-
useEffect(() => {
|
|
33160
|
-
stores.trigger("store-updated");
|
|
33161
|
-
}, () => [hoverState.hovered]);
|
|
33162
33532
|
}
|
|
33163
33533
|
function useHighlights(highlightProvider) {
|
|
33534
|
+
const stores = useStoreProvider();
|
|
33164
33535
|
const store = useLocalStore(HighlightStore);
|
|
33165
33536
|
onMounted(() => {
|
|
33166
33537
|
store.register(highlightProvider);
|
|
33167
33538
|
});
|
|
33539
|
+
let currentHighlights = highlightProvider.highlights;
|
|
33540
|
+
useEffect((highlights) => {
|
|
33541
|
+
if (!deepEquals(highlights, currentHighlights)) {
|
|
33542
|
+
currentHighlights = highlights;
|
|
33543
|
+
stores.trigger("store-updated");
|
|
33544
|
+
}
|
|
33545
|
+
}, () => [highlightProvider.highlights]);
|
|
33168
33546
|
}
|
|
33169
33547
|
|
|
33170
33548
|
css /* scss */ `
|
|
@@ -34636,6 +35014,8 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
34636
35014
|
isSearchDirty = false;
|
|
34637
35015
|
initialShowFormulaState;
|
|
34638
35016
|
preserveSelectedMatchIndex = false;
|
|
35017
|
+
irreplaceableMatchCount = 0;
|
|
35018
|
+
notificationStore = this.get(NotificationStore);
|
|
34639
35019
|
// fixme: why do we make selectedMatchIndex on top of a selected
|
|
34640
35020
|
// property in the matches?
|
|
34641
35021
|
selectedMatchIndex = null;
|
|
@@ -34712,6 +35092,11 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
34712
35092
|
for (const match of cmd.matches) {
|
|
34713
35093
|
this.replaceMatch(match, cmd.searchString, cmd.replaceWith, cmd.searchOptions);
|
|
34714
35094
|
}
|
|
35095
|
+
if (this.irreplaceableMatchCount > 0) {
|
|
35096
|
+
this.showReplaceWarningMessage(cmd.matches.length, this.irreplaceableMatchCount);
|
|
35097
|
+
}
|
|
35098
|
+
this.irreplaceableMatchCount = 0;
|
|
35099
|
+
break;
|
|
34715
35100
|
}
|
|
34716
35101
|
}
|
|
34717
35102
|
finalize() {
|
|
@@ -34893,12 +35278,36 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
34893
35278
|
searchOptions: this.searchOptions,
|
|
34894
35279
|
});
|
|
34895
35280
|
}
|
|
35281
|
+
/**
|
|
35282
|
+
* Show a warning message based on the number of matches replaced and irreplaceable.
|
|
35283
|
+
*/
|
|
35284
|
+
showReplaceWarningMessage(totalMatches, irreplaceableMatches) {
|
|
35285
|
+
const replaceableMatches = totalMatches - irreplaceableMatches;
|
|
35286
|
+
if (replaceableMatches === 0) {
|
|
35287
|
+
this.notificationStore.notifyUser({
|
|
35288
|
+
type: "warning",
|
|
35289
|
+
sticky: false,
|
|
35290
|
+
text: _t("Match(es) cannot be replaced as they are part of a formula."),
|
|
35291
|
+
});
|
|
35292
|
+
}
|
|
35293
|
+
else {
|
|
35294
|
+
this.notificationStore.notifyUser({
|
|
35295
|
+
type: "warning",
|
|
35296
|
+
sticky: false,
|
|
35297
|
+
text: _t("%(replaceable_count)s match(es) replaced. %(irreplaceable_count)s match(es) cannot be replaced as they are part of a formula.", {
|
|
35298
|
+
replaceable_count: replaceableMatches,
|
|
35299
|
+
irreplaceable_count: irreplaceableMatches,
|
|
35300
|
+
}),
|
|
35301
|
+
});
|
|
35302
|
+
}
|
|
35303
|
+
}
|
|
34896
35304
|
replaceMatch(selectedMatch, searchString, replaceWith, searchOptions) {
|
|
34897
35305
|
const cell = this.getters.getCell(selectedMatch);
|
|
34898
35306
|
if (!cell?.content) {
|
|
34899
35307
|
return;
|
|
34900
35308
|
}
|
|
34901
35309
|
if (cell?.isFormula && !searchOptions.searchFormulas) {
|
|
35310
|
+
this.irreplaceableMatchCount++;
|
|
34902
35311
|
return;
|
|
34903
35312
|
}
|
|
34904
35313
|
const searchRegex = getSearchRegex(searchString, searchOptions);
|
|
@@ -36964,7 +37373,13 @@ class SettingsPanel extends Component {
|
|
|
36964
37373
|
}
|
|
36965
37374
|
async loadLocales() {
|
|
36966
37375
|
this.loadedLocales = (await this.env.loadLocales())
|
|
36967
|
-
.filter(
|
|
37376
|
+
.filter((locale) => {
|
|
37377
|
+
const isValid = isValidLocale(locale);
|
|
37378
|
+
if (!isValid) {
|
|
37379
|
+
console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
|
|
37380
|
+
}
|
|
37381
|
+
return isValid;
|
|
37382
|
+
})
|
|
36968
37383
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
36969
37384
|
}
|
|
36970
37385
|
get numberFormatPreview() {
|
|
@@ -38023,6 +38438,9 @@ class TopBarComponentRegistry extends Registry {
|
|
|
38023
38438
|
const component = { ...value, id: this.uuidGenerator.uuidv4() };
|
|
38024
38439
|
return super.add(name, component);
|
|
38025
38440
|
}
|
|
38441
|
+
getAllOrdered() {
|
|
38442
|
+
return this.getAll().sort((a, b) => a.sequence - b.sequence);
|
|
38443
|
+
}
|
|
38026
38444
|
}
|
|
38027
38445
|
const topbarComponentRegistry = new TopBarComponentRegistry();
|
|
38028
38446
|
|
|
@@ -42133,6 +42551,7 @@ class Grid extends Component {
|
|
|
42133
42551
|
return;
|
|
42134
42552
|
}
|
|
42135
42553
|
if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
|
|
42554
|
+
ev.preventDefault();
|
|
42136
42555
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
42137
42556
|
const target = this.env.model.getters.getSelectedZones();
|
|
42138
42557
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
@@ -45717,7 +46136,7 @@ function getRelationFile(file, xmls) {
|
|
|
45717
46136
|
return relsFile;
|
|
45718
46137
|
}
|
|
45719
46138
|
|
|
45720
|
-
const EXCEL_IMPORT_VERSION =
|
|
46139
|
+
const EXCEL_IMPORT_VERSION = 17;
|
|
45721
46140
|
class XlsxReader {
|
|
45722
46141
|
warningManager;
|
|
45723
46142
|
xmls;
|
|
@@ -45849,7 +46268,7 @@ function normalizeV9(formula) {
|
|
|
45849
46268
|
* a breaking change is made in the way the state is handled, and an upgrade
|
|
45850
46269
|
* function should be defined
|
|
45851
46270
|
*/
|
|
45852
|
-
const CURRENT_VERSION =
|
|
46271
|
+
const CURRENT_VERSION = 17;
|
|
45853
46272
|
const INITIAL_SHEET_ID = "Sheet1";
|
|
45854
46273
|
/**
|
|
45855
46274
|
* This function tries to load anything that could look like a valid
|
|
@@ -46796,6 +47215,21 @@ class BordersPlugin extends CorePlugin {
|
|
|
46796
47215
|
return [];
|
|
46797
47216
|
return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
|
|
46798
47217
|
}
|
|
47218
|
+
/**
|
|
47219
|
+
* Get all the rows which contains at least a border
|
|
47220
|
+
*/
|
|
47221
|
+
getRowsWithBorders(sheetId) {
|
|
47222
|
+
const sheetBorders = this.borders[sheetId]?.filter(isDefined);
|
|
47223
|
+
if (!sheetBorders)
|
|
47224
|
+
return [];
|
|
47225
|
+
const rowsWithBorders = new Set();
|
|
47226
|
+
for (const rowBorders of sheetBorders) {
|
|
47227
|
+
for (const rowBorder in rowBorders) {
|
|
47228
|
+
rowsWithBorders.add(parseInt(rowBorder, 10));
|
|
47229
|
+
}
|
|
47230
|
+
}
|
|
47231
|
+
return Array.from(rowsWithBorders);
|
|
47232
|
+
}
|
|
46799
47233
|
/**
|
|
46800
47234
|
* Get the range of all the rows in the sheet
|
|
46801
47235
|
*/
|
|
@@ -46845,7 +47279,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
46845
47279
|
destructive: false,
|
|
46846
47280
|
});
|
|
46847
47281
|
}
|
|
46848
|
-
this.
|
|
47282
|
+
this.getRowsWithBorders(sheetId)
|
|
46849
47283
|
.filter((row) => row >= start)
|
|
46850
47284
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
46851
47285
|
.forEach((row) => {
|
|
@@ -49171,10 +49605,12 @@ class MergePlugin extends CorePlugin {
|
|
|
49171
49605
|
if (!sheetMap)
|
|
49172
49606
|
return [];
|
|
49173
49607
|
const mergeIds = new Set();
|
|
49174
|
-
for (
|
|
49175
|
-
|
|
49176
|
-
|
|
49177
|
-
|
|
49608
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
49609
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
49610
|
+
const mergeId = sheetMap[col]?.[row];
|
|
49611
|
+
if (mergeId) {
|
|
49612
|
+
mergeIds.add(mergeId);
|
|
49613
|
+
}
|
|
49178
49614
|
}
|
|
49179
49615
|
}
|
|
49180
49616
|
return Array.from(mergeIds)
|
|
@@ -53042,7 +53478,13 @@ class FormulaDependencyGraph {
|
|
|
53042
53478
|
const queue = Array.from(ranges).reverse();
|
|
53043
53479
|
while (queue.length > 0) {
|
|
53044
53480
|
const range = queue.pop();
|
|
53045
|
-
|
|
53481
|
+
const zone = range.zone;
|
|
53482
|
+
const sheetId = range.sheetId;
|
|
53483
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
53484
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
53485
|
+
visited.add({ sheetId, col, row });
|
|
53486
|
+
}
|
|
53487
|
+
}
|
|
53046
53488
|
const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
|
|
53047
53489
|
const nextInQueue = {};
|
|
53048
53490
|
for (const position of impactedPositions) {
|
|
@@ -53058,7 +53500,16 @@ class FormulaDependencyGraph {
|
|
|
53058
53500
|
queue.push(...zones.map((zone) => ({ sheetId, zone })));
|
|
53059
53501
|
}
|
|
53060
53502
|
}
|
|
53061
|
-
|
|
53503
|
+
// remove initial ranges
|
|
53504
|
+
for (const range of ranges) {
|
|
53505
|
+
const zone = range.zone;
|
|
53506
|
+
const sheetId = range.sheetId;
|
|
53507
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
53508
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
53509
|
+
visited.delete({ sheetId, col, row });
|
|
53510
|
+
}
|
|
53511
|
+
}
|
|
53512
|
+
}
|
|
53062
53513
|
return visited;
|
|
53063
53514
|
}
|
|
53064
53515
|
}
|
|
@@ -53189,7 +53640,7 @@ class PositionSet {
|
|
|
53189
53640
|
return this.sheets[position.sheetId].getValue(position) === 1;
|
|
53190
53641
|
}
|
|
53191
53642
|
clear() {
|
|
53192
|
-
const insertions = this
|
|
53643
|
+
const insertions = [...this];
|
|
53193
53644
|
this.insertions = [];
|
|
53194
53645
|
for (const sheetId in this.sheets) {
|
|
53195
53646
|
this.sheets[sheetId].clear();
|
|
@@ -53533,6 +53984,7 @@ class Evaluator {
|
|
|
53533
53984
|
}
|
|
53534
53985
|
finally {
|
|
53535
53986
|
this.cellsBeingComputed.delete(cellId);
|
|
53987
|
+
this.nextPositionsToUpdate.delete(position);
|
|
53536
53988
|
}
|
|
53537
53989
|
}
|
|
53538
53990
|
computeAndSave(position) {
|
|
@@ -53559,8 +54011,33 @@ class Evaluator {
|
|
|
53559
54011
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
53560
54012
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
53561
54013
|
this.spreadValues(formulaPosition, formulaReturn));
|
|
54014
|
+
this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
|
|
53562
54015
|
return createEvaluatedCell(nullValueToZeroValue(formulaReturn[0][0]), this.getters.getLocale(), cellData);
|
|
53563
54016
|
}
|
|
54017
|
+
invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
|
|
54018
|
+
// the result matrix is split in 2 zones to exclude the array formula position
|
|
54019
|
+
const top = arrayFormulaPosition.row;
|
|
54020
|
+
const left = arrayFormulaPosition.col;
|
|
54021
|
+
const bottom = top + nbRows - 1;
|
|
54022
|
+
const leftColumnZone = {
|
|
54023
|
+
top: top + 1,
|
|
54024
|
+
bottom,
|
|
54025
|
+
left,
|
|
54026
|
+
right: left,
|
|
54027
|
+
};
|
|
54028
|
+
const rightPartZone = {
|
|
54029
|
+
top,
|
|
54030
|
+
bottom,
|
|
54031
|
+
left: left + 1,
|
|
54032
|
+
right: left + nbColumns - 1,
|
|
54033
|
+
};
|
|
54034
|
+
const sheetId = arrayFormulaPosition.sheetId;
|
|
54035
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
|
|
54036
|
+
{ sheetId, zone: rightPartZone },
|
|
54037
|
+
{ sheetId, zone: leftColumnZone },
|
|
54038
|
+
]);
|
|
54039
|
+
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
54040
|
+
}
|
|
53564
54041
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
53565
54042
|
const numberOfCols = this.getters.getNumberCols(sheetId);
|
|
53566
54043
|
const numberOfRows = this.getters.getNumberRows(sheetId);
|
|
@@ -53591,14 +54068,15 @@ class Evaluator {
|
|
|
53591
54068
|
}
|
|
53592
54069
|
updateSpreadRelation({ sheetId, col, row, }) {
|
|
53593
54070
|
const arrayFormulaPosition = { sheetId, col, row };
|
|
53594
|
-
|
|
54071
|
+
const updateSpreadRelation = (i, j) => {
|
|
53595
54072
|
const position = { sheetId, col: i + col, row: j + row };
|
|
53596
54073
|
this.spreadingRelations.addRelation({ resultPosition: position, arrayFormulaPosition });
|
|
53597
54074
|
};
|
|
54075
|
+
return updateSpreadRelation;
|
|
53598
54076
|
}
|
|
53599
54077
|
checkCollision(formulaPosition) {
|
|
53600
54078
|
const { sheetId, col, row } = formulaPosition;
|
|
53601
|
-
|
|
54079
|
+
const checkCollision = (i, j) => {
|
|
53602
54080
|
const position = { sheetId: sheetId, col: i + col, row: j + row };
|
|
53603
54081
|
const rawCell = this.getters.getCell(position);
|
|
53604
54082
|
if (rawCell?.content ||
|
|
@@ -53608,17 +54086,16 @@ class Evaluator {
|
|
|
53608
54086
|
}
|
|
53609
54087
|
this.blockedArrayFormulas.delete(formulaPosition);
|
|
53610
54088
|
};
|
|
54089
|
+
return checkCollision;
|
|
53611
54090
|
}
|
|
53612
54091
|
spreadValues({ sheetId, col, row }, matrixResult) {
|
|
53613
|
-
|
|
54092
|
+
const spreadValues = (i, j) => {
|
|
53614
54093
|
const position = { sheetId, col: i + col, row: j + row };
|
|
53615
54094
|
const cell = this.getters.getCell(position);
|
|
53616
54095
|
const evaluatedCell = createEvaluatedCell(nullValueToZeroValue(matrixResult[i][j]), this.getters.getLocale(), cell);
|
|
53617
54096
|
this.evaluatedCells.set(position, evaluatedCell);
|
|
53618
|
-
// check if formula dependencies present in the spread zone
|
|
53619
|
-
// if so, they need to be recomputed
|
|
53620
|
-
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([position]));
|
|
53621
54097
|
};
|
|
54098
|
+
return spreadValues;
|
|
53622
54099
|
}
|
|
53623
54100
|
invalidateSpreading(position) {
|
|
53624
54101
|
if (!this.spreadingRelations.isArrayFormula(position)) {
|
|
@@ -53673,12 +54150,12 @@ function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
|
|
|
53673
54150
|
* rather than appearing empty. This indicates that the
|
|
53674
54151
|
* cell is the result of a non-empty content.
|
|
53675
54152
|
*/
|
|
53676
|
-
function nullValueToZeroValue(
|
|
53677
|
-
if (
|
|
53678
|
-
// '
|
|
53679
|
-
return { ...
|
|
54153
|
+
function nullValueToZeroValue(functionResult) {
|
|
54154
|
+
if (functionResult.value === null || functionResult.value === undefined) {
|
|
54155
|
+
// 'functionResult.value === undefined' is supposed to never happen, it's a safety net for javascript use
|
|
54156
|
+
return { ...functionResult, value: 0 };
|
|
53680
54157
|
}
|
|
53681
|
-
return
|
|
54158
|
+
return functionResult;
|
|
53682
54159
|
}
|
|
53683
54160
|
function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
|
|
53684
54161
|
compilationParams.evalContext.__originCellXC = lazy(() => {
|
|
@@ -63138,7 +63615,7 @@ class TopBar extends Component {
|
|
|
63138
63615
|
}
|
|
63139
63616
|
get topbarComponents() {
|
|
63140
63617
|
return topbarComponentRegistry
|
|
63141
|
-
.
|
|
63618
|
+
.getAllOrdered()
|
|
63142
63619
|
.filter((item) => !item.isVisible || item.isVisible(this.env));
|
|
63143
63620
|
}
|
|
63144
63621
|
onExternalClick(ev) {
|
|
@@ -67726,6 +68203,6 @@ const constants = {
|
|
|
67726
68203
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, 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 };
|
|
67727
68204
|
|
|
67728
68205
|
|
|
67729
|
-
__info__.version = "17.4.0-alpha.
|
|
67730
|
-
__info__.date = "2024-07-
|
|
67731
|
-
__info__.hash = "
|
|
68206
|
+
__info__.version = "17.4.0-alpha.13";
|
|
68207
|
+
__info__.date = "2024-07-11T06:36:58.556Z";
|
|
68208
|
+
__info__.hash = "e0f506b";
|