@odoo/o-spreadsheet 17.3.7 → 17.3.9
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 +235 -193
- package/dist/o-spreadsheet.d.ts +6 -3
- package/dist/o-spreadsheet.esm.js +235 -193
- package/dist/o-spreadsheet.iife.js +235 -193
- package/dist/o-spreadsheet.iife.min.js +7 -7
- package/dist/o_spreadsheet.xml +4 -4
- package/package.json +1 -1
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.3.
|
|
7
|
-
* @date 2024-07-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.3.9
|
|
7
|
+
* @date 2024-07-11T06:37:05.603Z
|
|
8
|
+
* @hash 2346a16
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
@@ -593,7 +593,7 @@ function getAddHeaderStartIndex(position, base) {
|
|
|
593
593
|
/**
|
|
594
594
|
* Compares two objects.
|
|
595
595
|
*/
|
|
596
|
-
function deepEquals(o1, o2
|
|
596
|
+
function deepEquals(o1, o2) {
|
|
597
597
|
if (o1 === o2)
|
|
598
598
|
return true;
|
|
599
599
|
if ((o1 && !o2) || (o2 && !o1))
|
|
@@ -609,17 +609,13 @@ function deepEquals(o1, o2, ignoreFunctions) {
|
|
|
609
609
|
}
|
|
610
610
|
}
|
|
611
611
|
for (const key in o1) {
|
|
612
|
-
|
|
613
|
-
if (typeOfO1Key !== typeof o2[key])
|
|
612
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
614
613
|
return false;
|
|
615
|
-
if (
|
|
616
|
-
if (!deepEquals(o1[key], o2[key]
|
|
614
|
+
if (typeof o1[key] === "object") {
|
|
615
|
+
if (!deepEquals(o1[key], o2[key]))
|
|
617
616
|
return false;
|
|
618
617
|
}
|
|
619
618
|
else {
|
|
620
|
-
if (ignoreFunctions && typeOfO1Key === "function") {
|
|
621
|
-
continue;
|
|
622
|
-
}
|
|
623
619
|
if (o1[key] !== o2[key])
|
|
624
620
|
return false;
|
|
625
621
|
}
|
|
@@ -1832,7 +1828,7 @@ const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSepa
|
|
|
1832
1828
|
});
|
|
1833
1829
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
1834
1830
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
1835
|
-
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
|
|
1831
|
+
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
|
|
1836
1832
|
const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
|
|
1837
1833
|
const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
|
|
1838
1834
|
const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -1859,7 +1855,7 @@ function isNumber(value, locale) {
|
|
|
1859
1855
|
return getNumberRegex(locale).test(value.trim());
|
|
1860
1856
|
}
|
|
1861
1857
|
const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
|
|
1862
|
-
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
|
|
1858
|
+
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
|
|
1863
1859
|
});
|
|
1864
1860
|
/**
|
|
1865
1861
|
* Convert a string into a number. It assumes that the string actually represents
|
|
@@ -2766,6 +2762,9 @@ function getPredicate(descr, locale) {
|
|
|
2766
2762
|
* If the character is a special regular expression character, it is escaped with "\\".
|
|
2767
2763
|
*/
|
|
2768
2764
|
const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
|
|
2765
|
+
if (operand === "*") {
|
|
2766
|
+
return /.+/;
|
|
2767
|
+
}
|
|
2769
2768
|
let exp = "";
|
|
2770
2769
|
let predecessor = "";
|
|
2771
2770
|
for (let char of operand) {
|
|
@@ -2789,9 +2788,9 @@ const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
|
|
|
2789
2788
|
}
|
|
2790
2789
|
return new RegExp("^" + exp + "$", "i");
|
|
2791
2790
|
});
|
|
2792
|
-
function evaluatePredicate(value, criterion) {
|
|
2791
|
+
function evaluatePredicate(value = "", criterion) {
|
|
2793
2792
|
const { operator, operand } = criterion;
|
|
2794
|
-
if (
|
|
2793
|
+
if (operand === undefined || value === null || operand === null) {
|
|
2795
2794
|
return false;
|
|
2796
2795
|
}
|
|
2797
2796
|
if (typeof operand === "number" && operator === "=") {
|
|
@@ -5896,19 +5895,22 @@ class TokenizingChars {
|
|
|
5896
5895
|
}
|
|
5897
5896
|
|
|
5898
5897
|
function isValidLocale(locale) {
|
|
5899
|
-
if (!
|
|
5900
|
-
typeof locale
|
|
5901
|
-
typeof locale.
|
|
5902
|
-
typeof locale.code === "string" &&
|
|
5903
|
-
typeof locale.thousandsSeparator === "string" &&
|
|
5904
|
-
typeof locale.decimalSeparator === "string" &&
|
|
5905
|
-
typeof locale.dateFormat === "string" &&
|
|
5906
|
-
typeof locale.timeFormat === "string" &&
|
|
5907
|
-
typeof locale.formulaArgSeparator === "string")) {
|
|
5898
|
+
if (!locale ||
|
|
5899
|
+
typeof locale !== "object" ||
|
|
5900
|
+
!(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
|
|
5908
5901
|
return false;
|
|
5909
5902
|
}
|
|
5910
|
-
|
|
5911
|
-
|
|
5903
|
+
for (const property of [
|
|
5904
|
+
"code",
|
|
5905
|
+
"name",
|
|
5906
|
+
"decimalSeparator",
|
|
5907
|
+
"dateFormat",
|
|
5908
|
+
"timeFormat",
|
|
5909
|
+
"formulaArgSeparator",
|
|
5910
|
+
]) {
|
|
5911
|
+
if (!locale[property] || typeof locale[property] !== "string") {
|
|
5912
|
+
return false;
|
|
5913
|
+
}
|
|
5912
5914
|
}
|
|
5913
5915
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
5914
5916
|
return false;
|
|
@@ -6006,7 +6008,10 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
6006
6008
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
6007
6009
|
return content;
|
|
6008
6010
|
}
|
|
6009
|
-
|
|
6011
|
+
if (locale.thousandsSeparator) {
|
|
6012
|
+
content = content.replaceAll(locale.thousandsSeparator, "");
|
|
6013
|
+
}
|
|
6014
|
+
return content.replace(locale.decimalSeparator, ".");
|
|
6010
6015
|
}
|
|
6011
6016
|
/**
|
|
6012
6017
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -6995,6 +7000,146 @@ function transformRangeData(range, executed) {
|
|
|
6995
7000
|
return undefined;
|
|
6996
7001
|
}
|
|
6997
7002
|
|
|
7003
|
+
var State;
|
|
7004
|
+
(function (State) {
|
|
7005
|
+
/**
|
|
7006
|
+
* Initial state.
|
|
7007
|
+
* Expecting any reference for the left part of a range
|
|
7008
|
+
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7009
|
+
*/
|
|
7010
|
+
State[State["LeftRef"] = 0] = "LeftRef";
|
|
7011
|
+
/**
|
|
7012
|
+
* Expecting any reference for the right part of a range
|
|
7013
|
+
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7014
|
+
*/
|
|
7015
|
+
State[State["RightRef"] = 1] = "RightRef";
|
|
7016
|
+
/**
|
|
7017
|
+
* Expecting the separator without any constraint on the right part
|
|
7018
|
+
*/
|
|
7019
|
+
State[State["Separator"] = 2] = "Separator";
|
|
7020
|
+
/**
|
|
7021
|
+
* Expecting the separator for a full column range
|
|
7022
|
+
*/
|
|
7023
|
+
State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
|
|
7024
|
+
/**
|
|
7025
|
+
* Expecting the separator for a full row range
|
|
7026
|
+
*/
|
|
7027
|
+
State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
|
|
7028
|
+
/**
|
|
7029
|
+
* Expecting the right part of a full column range
|
|
7030
|
+
* e.g. "1", "A1"
|
|
7031
|
+
*/
|
|
7032
|
+
State[State["RightColumnRef"] = 5] = "RightColumnRef";
|
|
7033
|
+
/**
|
|
7034
|
+
* Expecting the right part of a full row range
|
|
7035
|
+
* e.g. "A", "A1"
|
|
7036
|
+
*/
|
|
7037
|
+
State[State["RightRowRef"] = 6] = "RightRowRef";
|
|
7038
|
+
/**
|
|
7039
|
+
* Final state. A range has been matched
|
|
7040
|
+
*/
|
|
7041
|
+
State[State["Found"] = 7] = "Found";
|
|
7042
|
+
})(State || (State = {}));
|
|
7043
|
+
const goTo = (state, guard = () => true) => [
|
|
7044
|
+
{
|
|
7045
|
+
goTo: state,
|
|
7046
|
+
guard,
|
|
7047
|
+
},
|
|
7048
|
+
];
|
|
7049
|
+
const goToMulti = (state, guard = () => true) => ({
|
|
7050
|
+
goTo: state,
|
|
7051
|
+
guard,
|
|
7052
|
+
});
|
|
7053
|
+
const machine = {
|
|
7054
|
+
[State.LeftRef]: {
|
|
7055
|
+
REFERENCE: goTo(State.Separator),
|
|
7056
|
+
NUMBER: goTo(State.FullRowSeparator),
|
|
7057
|
+
SYMBOL: [
|
|
7058
|
+
goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
|
|
7059
|
+
goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
|
|
7060
|
+
],
|
|
7061
|
+
},
|
|
7062
|
+
[State.FullColumnSeparator]: {
|
|
7063
|
+
SPACE: goTo(State.FullColumnSeparator),
|
|
7064
|
+
OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
|
|
7065
|
+
},
|
|
7066
|
+
[State.FullRowSeparator]: {
|
|
7067
|
+
SPACE: goTo(State.FullRowSeparator),
|
|
7068
|
+
OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
|
|
7069
|
+
},
|
|
7070
|
+
[State.Separator]: {
|
|
7071
|
+
SPACE: goTo(State.Separator),
|
|
7072
|
+
OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
|
|
7073
|
+
},
|
|
7074
|
+
[State.RightRef]: {
|
|
7075
|
+
SPACE: goTo(State.RightRef),
|
|
7076
|
+
NUMBER: goTo(State.Found),
|
|
7077
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7078
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
7079
|
+
},
|
|
7080
|
+
[State.RightColumnRef]: {
|
|
7081
|
+
SPACE: goTo(State.RightColumnRef),
|
|
7082
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
7083
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7084
|
+
},
|
|
7085
|
+
[State.RightRowRef]: {
|
|
7086
|
+
SPACE: goTo(State.RightRowRef),
|
|
7087
|
+
NUMBER: goTo(State.Found),
|
|
7088
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7089
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
7090
|
+
},
|
|
7091
|
+
[State.Found]: {},
|
|
7092
|
+
};
|
|
7093
|
+
/**
|
|
7094
|
+
* Check if the list of tokens starts with a sequence of tokens representing
|
|
7095
|
+
* a range.
|
|
7096
|
+
* If a range is found, the sequence is removed from the list and is returned
|
|
7097
|
+
* as a single token.
|
|
7098
|
+
*/
|
|
7099
|
+
function matchReference(tokens) {
|
|
7100
|
+
let head = 0;
|
|
7101
|
+
let transitions = machine[State.LeftRef];
|
|
7102
|
+
let matchedTokens = "";
|
|
7103
|
+
while (transitions !== undefined) {
|
|
7104
|
+
const token = tokens[head++];
|
|
7105
|
+
if (!token) {
|
|
7106
|
+
return null;
|
|
7107
|
+
}
|
|
7108
|
+
const transition = transitions[token.type]?.find((transition) => transition.guard(token));
|
|
7109
|
+
const nextState = transition ? transition.goTo : undefined;
|
|
7110
|
+
switch (nextState) {
|
|
7111
|
+
case undefined:
|
|
7112
|
+
return null;
|
|
7113
|
+
case State.Found:
|
|
7114
|
+
matchedTokens += token.value;
|
|
7115
|
+
tokens.splice(0, head);
|
|
7116
|
+
return {
|
|
7117
|
+
type: "REFERENCE",
|
|
7118
|
+
value: matchedTokens,
|
|
7119
|
+
};
|
|
7120
|
+
default:
|
|
7121
|
+
transitions = machine[nextState];
|
|
7122
|
+
matchedTokens += token.value;
|
|
7123
|
+
break;
|
|
7124
|
+
}
|
|
7125
|
+
}
|
|
7126
|
+
return null;
|
|
7127
|
+
}
|
|
7128
|
+
/**
|
|
7129
|
+
* Take the result of the tokenizer and transform it to be usable in the
|
|
7130
|
+
* manipulations of range
|
|
7131
|
+
*
|
|
7132
|
+
* @param formula
|
|
7133
|
+
*/
|
|
7134
|
+
function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
|
|
7135
|
+
const tokens = tokenize(formula, locale);
|
|
7136
|
+
const result = [];
|
|
7137
|
+
while (tokens.length) {
|
|
7138
|
+
result.push(matchReference(tokens) || tokens.shift());
|
|
7139
|
+
}
|
|
7140
|
+
return result;
|
|
7141
|
+
}
|
|
7142
|
+
|
|
6998
7143
|
const functionRegex = /[a-zA-Z0-9\_]+(\.[a-zA-Z0-9\_]+)*/;
|
|
6999
7144
|
const UNARY_OPERATORS_PREFIX = ["-", "+"];
|
|
7000
7145
|
const UNARY_OPERATORS_POSTFIX = ["%"];
|
|
@@ -7143,7 +7288,7 @@ function parseExpression(tokens, parent_priority = 0) {
|
|
|
7143
7288
|
* Parse an expression (as a string) into an AST.
|
|
7144
7289
|
*/
|
|
7145
7290
|
function parse(str) {
|
|
7146
|
-
return parseTokens(
|
|
7291
|
+
return parseTokens(rangeTokenize(str));
|
|
7147
7292
|
}
|
|
7148
7293
|
function parseTokens(tokens) {
|
|
7149
7294
|
tokens = tokens.filter((x) => x.type !== "SPACE");
|
|
@@ -7279,146 +7424,6 @@ function rightOperandToFormula(operationAST) {
|
|
|
7279
7424
|
return needParenthesis ? `(${astToFormula(rightOperation)})` : astToFormula(rightOperation);
|
|
7280
7425
|
}
|
|
7281
7426
|
|
|
7282
|
-
var State;
|
|
7283
|
-
(function (State) {
|
|
7284
|
-
/**
|
|
7285
|
-
* Initial state.
|
|
7286
|
-
* Expecting any reference for the left part of a range
|
|
7287
|
-
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7288
|
-
*/
|
|
7289
|
-
State[State["LeftRef"] = 0] = "LeftRef";
|
|
7290
|
-
/**
|
|
7291
|
-
* Expecting any reference for the right part of a range
|
|
7292
|
-
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
7293
|
-
*/
|
|
7294
|
-
State[State["RightRef"] = 1] = "RightRef";
|
|
7295
|
-
/**
|
|
7296
|
-
* Expecting the separator without any constraint on the right part
|
|
7297
|
-
*/
|
|
7298
|
-
State[State["Separator"] = 2] = "Separator";
|
|
7299
|
-
/**
|
|
7300
|
-
* Expecting the separator for a full column range
|
|
7301
|
-
*/
|
|
7302
|
-
State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
|
|
7303
|
-
/**
|
|
7304
|
-
* Expecting the separator for a full row range
|
|
7305
|
-
*/
|
|
7306
|
-
State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
|
|
7307
|
-
/**
|
|
7308
|
-
* Expecting the right part of a full column range
|
|
7309
|
-
* e.g. "1", "A1"
|
|
7310
|
-
*/
|
|
7311
|
-
State[State["RightColumnRef"] = 5] = "RightColumnRef";
|
|
7312
|
-
/**
|
|
7313
|
-
* Expecting the right part of a full row range
|
|
7314
|
-
* e.g. "A", "A1"
|
|
7315
|
-
*/
|
|
7316
|
-
State[State["RightRowRef"] = 6] = "RightRowRef";
|
|
7317
|
-
/**
|
|
7318
|
-
* Final state. A range has been matched
|
|
7319
|
-
*/
|
|
7320
|
-
State[State["Found"] = 7] = "Found";
|
|
7321
|
-
})(State || (State = {}));
|
|
7322
|
-
const goTo = (state, guard = () => true) => [
|
|
7323
|
-
{
|
|
7324
|
-
goTo: state,
|
|
7325
|
-
guard,
|
|
7326
|
-
},
|
|
7327
|
-
];
|
|
7328
|
-
const goToMulti = (state, guard = () => true) => ({
|
|
7329
|
-
goTo: state,
|
|
7330
|
-
guard,
|
|
7331
|
-
});
|
|
7332
|
-
const machine = {
|
|
7333
|
-
[State.LeftRef]: {
|
|
7334
|
-
REFERENCE: goTo(State.Separator),
|
|
7335
|
-
NUMBER: goTo(State.FullRowSeparator),
|
|
7336
|
-
SYMBOL: [
|
|
7337
|
-
goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
|
|
7338
|
-
goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
|
|
7339
|
-
],
|
|
7340
|
-
},
|
|
7341
|
-
[State.FullColumnSeparator]: {
|
|
7342
|
-
SPACE: goTo(State.FullColumnSeparator),
|
|
7343
|
-
OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
|
|
7344
|
-
},
|
|
7345
|
-
[State.FullRowSeparator]: {
|
|
7346
|
-
SPACE: goTo(State.FullRowSeparator),
|
|
7347
|
-
OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
|
|
7348
|
-
},
|
|
7349
|
-
[State.Separator]: {
|
|
7350
|
-
SPACE: goTo(State.Separator),
|
|
7351
|
-
OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
|
|
7352
|
-
},
|
|
7353
|
-
[State.RightRef]: {
|
|
7354
|
-
SPACE: goTo(State.RightRef),
|
|
7355
|
-
NUMBER: goTo(State.Found),
|
|
7356
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7357
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
7358
|
-
},
|
|
7359
|
-
[State.RightColumnRef]: {
|
|
7360
|
-
SPACE: goTo(State.RightColumnRef),
|
|
7361
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
7362
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7363
|
-
},
|
|
7364
|
-
[State.RightRowRef]: {
|
|
7365
|
-
SPACE: goTo(State.RightRowRef),
|
|
7366
|
-
NUMBER: goTo(State.Found),
|
|
7367
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
7368
|
-
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
7369
|
-
},
|
|
7370
|
-
[State.Found]: {},
|
|
7371
|
-
};
|
|
7372
|
-
/**
|
|
7373
|
-
* Check if the list of tokens starts with a sequence of tokens representing
|
|
7374
|
-
* a range.
|
|
7375
|
-
* If a range is found, the sequence is removed from the list and is returned
|
|
7376
|
-
* as a single token.
|
|
7377
|
-
*/
|
|
7378
|
-
function matchReference(tokens) {
|
|
7379
|
-
let head = 0;
|
|
7380
|
-
let transitions = machine[State.LeftRef];
|
|
7381
|
-
let matchedTokens = "";
|
|
7382
|
-
while (transitions !== undefined) {
|
|
7383
|
-
const token = tokens[head++];
|
|
7384
|
-
if (!token) {
|
|
7385
|
-
return null;
|
|
7386
|
-
}
|
|
7387
|
-
const transition = transitions[token.type]?.find((transition) => transition.guard(token));
|
|
7388
|
-
const nextState = transition ? transition.goTo : undefined;
|
|
7389
|
-
switch (nextState) {
|
|
7390
|
-
case undefined:
|
|
7391
|
-
return null;
|
|
7392
|
-
case State.Found:
|
|
7393
|
-
matchedTokens += token.value;
|
|
7394
|
-
tokens.splice(0, head);
|
|
7395
|
-
return {
|
|
7396
|
-
type: "REFERENCE",
|
|
7397
|
-
value: matchedTokens,
|
|
7398
|
-
};
|
|
7399
|
-
default:
|
|
7400
|
-
transitions = machine[nextState];
|
|
7401
|
-
matchedTokens += token.value;
|
|
7402
|
-
break;
|
|
7403
|
-
}
|
|
7404
|
-
}
|
|
7405
|
-
return null;
|
|
7406
|
-
}
|
|
7407
|
-
/**
|
|
7408
|
-
* Take the result of the tokenizer and transform it to be usable in the
|
|
7409
|
-
* manipulations of range
|
|
7410
|
-
*
|
|
7411
|
-
* @param formula
|
|
7412
|
-
*/
|
|
7413
|
-
function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
|
|
7414
|
-
const tokens = tokenize(formula, locale);
|
|
7415
|
-
const result = [];
|
|
7416
|
-
while (tokens.length) {
|
|
7417
|
-
result.push(matchReference(tokens) || tokens.shift());
|
|
7418
|
-
}
|
|
7419
|
-
return result;
|
|
7420
|
-
}
|
|
7421
|
-
|
|
7422
7427
|
/**
|
|
7423
7428
|
* Add the following information on tokens:
|
|
7424
7429
|
* - length
|
|
@@ -9836,7 +9841,6 @@ class ChartJsComponent extends owl.Component {
|
|
|
9836
9841
|
};
|
|
9837
9842
|
canvas = owl.useRef("graphContainer");
|
|
9838
9843
|
chart;
|
|
9839
|
-
currentRuntime;
|
|
9840
9844
|
get background() {
|
|
9841
9845
|
return this.chartRuntime.background;
|
|
9842
9846
|
}
|
|
@@ -9853,18 +9857,11 @@ class ChartJsComponent extends owl.Component {
|
|
|
9853
9857
|
setup() {
|
|
9854
9858
|
owl.onMounted(() => {
|
|
9855
9859
|
const runtime = this.chartRuntime;
|
|
9856
|
-
this.currentRuntime = runtime;
|
|
9857
9860
|
// Note: chartJS modify the runtime in place, so it's important to give it a copy
|
|
9858
9861
|
this.createChart(deepCopy(runtime.chartJsConfig));
|
|
9859
9862
|
});
|
|
9860
9863
|
owl.onWillUnmount(() => this.chart?.destroy());
|
|
9861
|
-
owl.useEffect(() =>
|
|
9862
|
-
const runtime = this.chartRuntime;
|
|
9863
|
-
if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
|
|
9864
|
-
this.currentRuntime = runtime;
|
|
9865
|
-
this.updateChartJs(deepCopy(runtime));
|
|
9866
|
-
}
|
|
9867
|
-
});
|
|
9864
|
+
owl.useEffect(() => this.updateChartJs(deepCopy(this.chartRuntime)), () => [this.chartRuntime]);
|
|
9868
9865
|
}
|
|
9869
9866
|
createChart(chartData) {
|
|
9870
9867
|
const canvas = this.canvas.el;
|
|
@@ -22698,7 +22695,7 @@ function truncateLabel(label) {
|
|
|
22698
22695
|
/**
|
|
22699
22696
|
* Get a default chart js configuration
|
|
22700
22697
|
*/
|
|
22701
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
|
|
22698
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
|
|
22702
22699
|
const chartTitle = chart.title.text ? chart.title : { ...chart.title, content: "" };
|
|
22703
22700
|
const options = {
|
|
22704
22701
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
@@ -23927,10 +23924,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
23927
23924
|
const colors = new ColorGenerator();
|
|
23928
23925
|
const definition = chart.getDefinition();
|
|
23929
23926
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
23930
|
-
if (["linear", "time"].includes(axisType)) {
|
|
23931
|
-
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
23932
|
-
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
23933
|
-
}
|
|
23934
23927
|
const color = colors.next();
|
|
23935
23928
|
let backgroundRGBA = colorToRGBA(color);
|
|
23936
23929
|
if (stacked) {
|
|
@@ -23946,6 +23939,10 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
23946
23939
|
return value;
|
|
23947
23940
|
});
|
|
23948
23941
|
}
|
|
23942
|
+
if (["linear", "time"].includes(axisType)) {
|
|
23943
|
+
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
23944
|
+
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
23945
|
+
}
|
|
23949
23946
|
const backgroundColor = rgbaToHex(backgroundRGBA);
|
|
23950
23947
|
const dataset = {
|
|
23951
23948
|
label,
|
|
@@ -36263,7 +36260,13 @@ class SettingsPanel extends owl.Component {
|
|
|
36263
36260
|
}
|
|
36264
36261
|
async loadLocales() {
|
|
36265
36262
|
this.loadedLocales = (await this.env.loadLocales())
|
|
36266
|
-
.filter(
|
|
36263
|
+
.filter((locale) => {
|
|
36264
|
+
const isValid = isValidLocale(locale);
|
|
36265
|
+
if (!isValid) {
|
|
36266
|
+
console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
|
|
36267
|
+
}
|
|
36268
|
+
return isValid;
|
|
36269
|
+
})
|
|
36267
36270
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
36268
36271
|
}
|
|
36269
36272
|
get numberFormatPreview() {
|
|
@@ -41415,6 +41418,7 @@ class Grid extends owl.Component {
|
|
|
41415
41418
|
return;
|
|
41416
41419
|
}
|
|
41417
41420
|
if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
|
|
41421
|
+
ev.preventDefault();
|
|
41418
41422
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
41419
41423
|
const target = this.env.model.getters.getSelectedZones();
|
|
41420
41424
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
@@ -45126,7 +45130,7 @@ function getRelationFile(file, xmls) {
|
|
|
45126
45130
|
return relsFile;
|
|
45127
45131
|
}
|
|
45128
45132
|
|
|
45129
|
-
const EXCEL_IMPORT_VERSION =
|
|
45133
|
+
const EXCEL_IMPORT_VERSION = 17;
|
|
45130
45134
|
class XlsxReader {
|
|
45131
45135
|
warningManager;
|
|
45132
45136
|
xmls;
|
|
@@ -45258,7 +45262,7 @@ function normalizeV9(formula) {
|
|
|
45258
45262
|
* a breaking change is made in the way the state is handled, and an upgrade
|
|
45259
45263
|
* function should be defined
|
|
45260
45264
|
*/
|
|
45261
|
-
const CURRENT_VERSION =
|
|
45265
|
+
const CURRENT_VERSION = 17;
|
|
45262
45266
|
const INITIAL_SHEET_ID = "Sheet1";
|
|
45263
45267
|
/**
|
|
45264
45268
|
* This function tries to load anything that could look like a valid
|
|
@@ -46205,6 +46209,21 @@ class BordersPlugin extends CorePlugin {
|
|
|
46205
46209
|
return [];
|
|
46206
46210
|
return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
|
|
46207
46211
|
}
|
|
46212
|
+
/**
|
|
46213
|
+
* Get all the rows which contains at least a border
|
|
46214
|
+
*/
|
|
46215
|
+
getRowsWithBorders(sheetId) {
|
|
46216
|
+
const sheetBorders = this.borders[sheetId]?.filter(isDefined);
|
|
46217
|
+
if (!sheetBorders)
|
|
46218
|
+
return [];
|
|
46219
|
+
const rowsWithBorders = new Set();
|
|
46220
|
+
for (const rowBorders of sheetBorders) {
|
|
46221
|
+
for (const rowBorder in rowBorders) {
|
|
46222
|
+
rowsWithBorders.add(parseInt(rowBorder, 10));
|
|
46223
|
+
}
|
|
46224
|
+
}
|
|
46225
|
+
return Array.from(rowsWithBorders);
|
|
46226
|
+
}
|
|
46208
46227
|
/**
|
|
46209
46228
|
* Get the range of all the rows in the sheet
|
|
46210
46229
|
*/
|
|
@@ -46254,7 +46273,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
46254
46273
|
destructive: false,
|
|
46255
46274
|
});
|
|
46256
46275
|
}
|
|
46257
|
-
this.
|
|
46276
|
+
this.getRowsWithBorders(sheetId)
|
|
46258
46277
|
.filter((row) => row >= start)
|
|
46259
46278
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
46260
46279
|
.forEach((row) => {
|
|
@@ -52586,7 +52605,7 @@ class PositionSet {
|
|
|
52586
52605
|
return this.sheets[position.sheetId].getValue(position) === 1;
|
|
52587
52606
|
}
|
|
52588
52607
|
clear() {
|
|
52589
|
-
const insertions = this
|
|
52608
|
+
const insertions = [...this];
|
|
52590
52609
|
this.insertions = [];
|
|
52591
52610
|
for (const sheetId in this.sheets) {
|
|
52592
52611
|
this.sheets[sheetId].clear();
|
|
@@ -52924,6 +52943,7 @@ class Evaluator {
|
|
|
52924
52943
|
}
|
|
52925
52944
|
finally {
|
|
52926
52945
|
this.cellsBeingComputed.delete(cellId);
|
|
52946
|
+
this.nextPositionsToUpdate.delete(position);
|
|
52927
52947
|
}
|
|
52928
52948
|
}
|
|
52929
52949
|
computeAndSave(position) {
|
|
@@ -52950,8 +52970,33 @@ class Evaluator {
|
|
|
52950
52970
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
52951
52971
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
52952
52972
|
this.spreadValues(formulaPosition, formulaReturn));
|
|
52973
|
+
this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
|
|
52953
52974
|
return createEvaluatedCell(nullValueToZeroValue(formulaReturn[0][0]), this.getters.getLocale(), cellData);
|
|
52954
52975
|
}
|
|
52976
|
+
invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
|
|
52977
|
+
// the result matrix is split in 2 zones to exclude the array formula position
|
|
52978
|
+
const top = arrayFormulaPosition.row;
|
|
52979
|
+
const left = arrayFormulaPosition.col;
|
|
52980
|
+
const bottom = top + nbRows - 1;
|
|
52981
|
+
const leftColumnZone = {
|
|
52982
|
+
top: top + 1,
|
|
52983
|
+
bottom,
|
|
52984
|
+
left,
|
|
52985
|
+
right: left,
|
|
52986
|
+
};
|
|
52987
|
+
const rightPartZone = {
|
|
52988
|
+
top,
|
|
52989
|
+
bottom,
|
|
52990
|
+
left: left + 1,
|
|
52991
|
+
right: left + nbColumns - 1,
|
|
52992
|
+
};
|
|
52993
|
+
const sheetId = arrayFormulaPosition.sheetId;
|
|
52994
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
|
|
52995
|
+
{ sheetId, zone: rightPartZone },
|
|
52996
|
+
{ sheetId, zone: leftColumnZone },
|
|
52997
|
+
]);
|
|
52998
|
+
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
52999
|
+
}
|
|
52955
53000
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
52956
53001
|
const numberOfCols = this.getters.getNumberCols(sheetId);
|
|
52957
53002
|
const numberOfRows = this.getters.getNumberRows(sheetId);
|
|
@@ -53006,9 +53051,6 @@ class Evaluator {
|
|
|
53006
53051
|
const cell = this.getters.getCell(position);
|
|
53007
53052
|
const evaluatedCell = createEvaluatedCell(nullValueToZeroValue(matrixResult[i][j]), this.getters.getLocale(), cell);
|
|
53008
53053
|
this.evaluatedCells.set(position, evaluatedCell);
|
|
53009
|
-
// check if formula dependencies present in the spread zone
|
|
53010
|
-
// if so, they need to be recomputed
|
|
53011
|
-
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([position]));
|
|
53012
53054
|
};
|
|
53013
53055
|
}
|
|
53014
53056
|
invalidateSpreading(position) {
|
|
@@ -67046,6 +67088,6 @@ exports.tokenColors = tokenColors;
|
|
|
67046
67088
|
exports.tokenize = tokenize;
|
|
67047
67089
|
|
|
67048
67090
|
|
|
67049
|
-
__info__.version = "17.3.
|
|
67050
|
-
__info__.date = "2024-07-
|
|
67051
|
-
__info__.hash = "
|
|
67091
|
+
__info__.version = "17.3.9";
|
|
67092
|
+
__info__.date = "2024-07-11T06:37:05.603Z";
|
|
67093
|
+
__info__.hash = "2346a16";
|
package/dist/o-spreadsheet.d.ts
CHANGED
|
@@ -1805,7 +1805,7 @@ type LocaleCode = string & Alias;
|
|
|
1805
1805
|
interface Locale {
|
|
1806
1806
|
name: string;
|
|
1807
1807
|
code: LocaleCode;
|
|
1808
|
-
thousandsSeparator
|
|
1808
|
+
thousandsSeparator?: string;
|
|
1809
1809
|
decimalSeparator: string;
|
|
1810
1810
|
dateFormat: string;
|
|
1811
1811
|
timeFormat: string;
|
|
@@ -2555,6 +2555,10 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
|
|
|
2555
2555
|
* Get all the columns which contains at least a border
|
|
2556
2556
|
*/
|
|
2557
2557
|
private getColumnsWithBorders;
|
|
2558
|
+
/**
|
|
2559
|
+
* Get all the rows which contains at least a border
|
|
2560
|
+
*/
|
|
2561
|
+
private getRowsWithBorders;
|
|
2558
2562
|
/**
|
|
2559
2563
|
* Get the range of all the rows in the sheet
|
|
2560
2564
|
*/
|
|
@@ -5513,7 +5517,7 @@ declare function lazy<T>(fn: (() => T) | T): Lazy<T>;
|
|
|
5513
5517
|
/**
|
|
5514
5518
|
* Compares two objects.
|
|
5515
5519
|
*/
|
|
5516
|
-
declare function deepEquals(o1: any, o2: any
|
|
5520
|
+
declare function deepEquals(o1: any, o2: any): boolean;
|
|
5517
5521
|
|
|
5518
5522
|
interface ConstructorArgs {
|
|
5519
5523
|
readonly zone: Readonly<Zone | UnboundedZone>;
|
|
@@ -7792,7 +7796,6 @@ declare class ChartJsComponent extends Component<Props$F, SpreadsheetChildEnv> {
|
|
|
7792
7796
|
};
|
|
7793
7797
|
private canvas;
|
|
7794
7798
|
private chart?;
|
|
7795
|
-
private currentRuntime;
|
|
7796
7799
|
get background(): string;
|
|
7797
7800
|
get canvasStyle(): string;
|
|
7798
7801
|
get chartRuntime(): ChartJSRuntime;
|