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