@odoo/o-spreadsheet 18.0.20 → 18.0.21
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 +91 -82
- package/dist/o-spreadsheet.esm.js +91 -82
- package/dist/o-spreadsheet.iife.js +91 -82
- package/dist/o-spreadsheet.iife.min.js +58 -56
- package/dist/o_spreadsheet.xml +6 -3
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.0.
|
|
6
|
-
* @date 2025-03-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.0.21
|
|
6
|
+
* @date 2025-03-26T12:49:46.872Z
|
|
7
|
+
* @hash c687e1c
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -1112,7 +1112,10 @@
|
|
|
1112
1112
|
}
|
|
1113
1113
|
else if (stringVals.length === 4) {
|
|
1114
1114
|
const alpha = parseFloat(stringVals.pop() || "1");
|
|
1115
|
-
|
|
1115
|
+
if (isNaN(alpha)) {
|
|
1116
|
+
throw new Error("invalid alpha value");
|
|
1117
|
+
}
|
|
1118
|
+
alphaHex = Math.round(alpha * 255);
|
|
1116
1119
|
}
|
|
1117
1120
|
const vals = stringVals.map((val) => parseInt(val, 10));
|
|
1118
1121
|
if (alphaHex !== 255) {
|
|
@@ -6836,7 +6839,7 @@
|
|
|
6836
6839
|
*/
|
|
6837
6840
|
function canonicalizeNumberContent(content, locale) {
|
|
6838
6841
|
return content.startsWith("=")
|
|
6839
|
-
? canonicalizeFormula
|
|
6842
|
+
? canonicalizeFormula(content, locale)
|
|
6840
6843
|
: canonicalizeNumberLiteral(content, locale);
|
|
6841
6844
|
}
|
|
6842
6845
|
/**
|
|
@@ -6851,7 +6854,7 @@
|
|
|
6851
6854
|
*/
|
|
6852
6855
|
function canonicalizeContent(content, locale) {
|
|
6853
6856
|
return content.startsWith("=")
|
|
6854
|
-
? canonicalizeFormula
|
|
6857
|
+
? canonicalizeFormula(content, locale)
|
|
6855
6858
|
: canonicalizeLiteral(content, locale);
|
|
6856
6859
|
}
|
|
6857
6860
|
/**
|
|
@@ -6867,15 +6870,21 @@
|
|
|
6867
6870
|
? localizeFormula(content, locale)
|
|
6868
6871
|
: localizeLiteral(content, locale);
|
|
6869
6872
|
}
|
|
6873
|
+
/** Change a number string to its canonical form (en_US locale) */
|
|
6874
|
+
function canonicalizeNumberValue(content, locale) {
|
|
6875
|
+
return content.startsWith("=")
|
|
6876
|
+
? canonicalizeFormula(content, locale)
|
|
6877
|
+
: canonicalizeNumberLiteral(content, locale);
|
|
6878
|
+
}
|
|
6870
6879
|
/** Change a formula to its canonical form (en_US locale) */
|
|
6871
|
-
function canonicalizeFormula
|
|
6872
|
-
return _localizeFormula
|
|
6880
|
+
function canonicalizeFormula(formula, locale) {
|
|
6881
|
+
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
6873
6882
|
}
|
|
6874
6883
|
/** Change a formula from the canonical form to the given locale */
|
|
6875
6884
|
function localizeFormula(formula, locale) {
|
|
6876
|
-
return _localizeFormula
|
|
6885
|
+
return _localizeFormula(formula, DEFAULT_LOCALE, locale);
|
|
6877
6886
|
}
|
|
6878
|
-
function _localizeFormula
|
|
6887
|
+
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
6879
6888
|
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
6880
6889
|
fromLocale.decimalSeparator === toLocale.decimalSeparator) {
|
|
6881
6890
|
return formula;
|
|
@@ -7031,37 +7040,6 @@
|
|
|
7031
7040
|
return locale.dateFormat + " " + locale.timeFormat;
|
|
7032
7041
|
}
|
|
7033
7042
|
|
|
7034
|
-
/** Change a number string to its canonical form (en_US locale) */
|
|
7035
|
-
function canonicalizeNumberValue(content, locale) {
|
|
7036
|
-
return content.startsWith("=")
|
|
7037
|
-
? canonicalizeFormula(content, locale)
|
|
7038
|
-
: canonicalizeNumberLiteral(content, locale);
|
|
7039
|
-
}
|
|
7040
|
-
/** Change a formula to its canonical form (en_US locale) */
|
|
7041
|
-
function canonicalizeFormula(formula, locale) {
|
|
7042
|
-
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
7043
|
-
}
|
|
7044
|
-
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
7045
|
-
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
7046
|
-
fromLocale.decimalSeparator === toLocale.decimalSeparator) {
|
|
7047
|
-
return formula;
|
|
7048
|
-
}
|
|
7049
|
-
const tokens = tokenize(formula, fromLocale);
|
|
7050
|
-
let localizedFormula = "";
|
|
7051
|
-
for (const token of tokens) {
|
|
7052
|
-
if (token.type === "NUMBER") {
|
|
7053
|
-
localizedFormula += token.value.replace(fromLocale.decimalSeparator, toLocale.decimalSeparator);
|
|
7054
|
-
}
|
|
7055
|
-
else if (token.type === "ARG_SEPARATOR") {
|
|
7056
|
-
localizedFormula += toLocale.formulaArgSeparator;
|
|
7057
|
-
}
|
|
7058
|
-
else {
|
|
7059
|
-
localizedFormula += token.value;
|
|
7060
|
-
}
|
|
7061
|
-
}
|
|
7062
|
-
return localizedFormula;
|
|
7063
|
-
}
|
|
7064
|
-
|
|
7065
7043
|
function boolAnd(args) {
|
|
7066
7044
|
let foundBoolean = false;
|
|
7067
7045
|
let acc = true;
|
|
@@ -10072,9 +10050,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10072
10050
|
/** In XLSX color format (no #) */
|
|
10073
10051
|
const AUTO_COLOR = "000000";
|
|
10074
10052
|
const XLSX_ICONSET_MAP = {
|
|
10075
|
-
|
|
10053
|
+
arrows: "3Arrows",
|
|
10076
10054
|
smiley: "3Symbols",
|
|
10077
|
-
|
|
10055
|
+
dots: "3TrafficLights1",
|
|
10078
10056
|
};
|
|
10079
10057
|
const NAMESPACE = {
|
|
10080
10058
|
styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
|
@@ -10746,6 +10724,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10746
10724
|
};
|
|
10747
10725
|
/** Map between legend position in XLSX file and human readable position */
|
|
10748
10726
|
const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
|
|
10727
|
+
none: "none",
|
|
10749
10728
|
b: "bottom",
|
|
10750
10729
|
t: "top",
|
|
10751
10730
|
l: "left",
|
|
@@ -13502,7 +13481,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13502
13481
|
default: "ffffff",
|
|
13503
13482
|
}).asString(),
|
|
13504
13483
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
|
|
13505
|
-
default: "
|
|
13484
|
+
default: "none",
|
|
13506
13485
|
}).asString()],
|
|
13507
13486
|
stacked: barChartGrouping === "stacked",
|
|
13508
13487
|
fontColor: "000000",
|
|
@@ -13536,7 +13515,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13536
13515
|
default: "ffffff",
|
|
13537
13516
|
}).asString(),
|
|
13538
13517
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(chartElement, "c:legendPos", "val", {
|
|
13539
|
-
default: "
|
|
13518
|
+
default: "none",
|
|
13540
13519
|
}).asString()],
|
|
13541
13520
|
stacked: barChartGrouping === "stacked",
|
|
13542
13521
|
fontColor: "000000",
|
|
@@ -16728,7 +16707,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
16728
16707
|
}
|
|
16729
16708
|
}
|
|
16730
16709
|
else if (dataSets.length === 1) {
|
|
16731
|
-
|
|
16710
|
+
const dataLength = getData(getters, dataSets[0]).length;
|
|
16711
|
+
for (let i = 0; i < dataLength; i++) {
|
|
16732
16712
|
labels.formattedValues.push("");
|
|
16733
16713
|
labels.values.push("");
|
|
16734
16714
|
}
|
|
@@ -25974,11 +25954,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
25974
25954
|
const _searchFor = toString(searchFor).toLowerCase();
|
|
25975
25955
|
const _textToSearch = toString(textToSearch).toLowerCase();
|
|
25976
25956
|
const _startingAt = toNumber(startingAt, this.locale);
|
|
25977
|
-
|
|
25978
|
-
|
|
25957
|
+
if (_textToSearch === "") {
|
|
25958
|
+
return {
|
|
25959
|
+
value: CellErrorType.GenericError,
|
|
25960
|
+
message: _t("The text_to_search must be non-empty."),
|
|
25961
|
+
};
|
|
25962
|
+
}
|
|
25963
|
+
if (_startingAt < 1) {
|
|
25964
|
+
return {
|
|
25965
|
+
value: CellErrorType.GenericError,
|
|
25966
|
+
message: _t("The starting_at (%s) must be greater than or equal to 1.", _startingAt),
|
|
25967
|
+
};
|
|
25968
|
+
}
|
|
25979
25969
|
const result = _textToSearch.indexOf(_searchFor, _startingAt - 1);
|
|
25980
|
-
|
|
25981
|
-
|
|
25970
|
+
if (result === -1) {
|
|
25971
|
+
return {
|
|
25972
|
+
value: CellErrorType.GenericError,
|
|
25973
|
+
message: _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor, _textToSearch),
|
|
25974
|
+
};
|
|
25975
|
+
}
|
|
25976
|
+
return { value: result + 1 };
|
|
25982
25977
|
},
|
|
25983
25978
|
isExported: true,
|
|
25984
25979
|
};
|
|
@@ -27828,11 +27823,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27828
27823
|
}
|
|
27829
27824
|
}
|
|
27830
27825
|
function compileTokensOrThrow(tokens) {
|
|
27831
|
-
const { dependencies,
|
|
27832
|
-
const cacheKey = compilationCacheKey(tokens
|
|
27826
|
+
const { dependencies, literalValues, symbols } = formulaArguments(tokens);
|
|
27827
|
+
const cacheKey = compilationCacheKey(tokens);
|
|
27833
27828
|
if (!functionCache[cacheKey]) {
|
|
27834
27829
|
const ast = parseTokens([...tokens]);
|
|
27835
27830
|
const scope = new Scope();
|
|
27831
|
+
let stringCount = 0;
|
|
27832
|
+
let numberCount = 0;
|
|
27833
|
+
let dependencyCount = 0;
|
|
27836
27834
|
if (ast.type === "BIN_OPERATION" && ast.value === ":") {
|
|
27837
27835
|
throw new BadExpressionError(_t("Invalid formula"));
|
|
27838
27836
|
}
|
|
@@ -27905,16 +27903,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27905
27903
|
case "BOOLEAN":
|
|
27906
27904
|
return code.return(`{ value: ${ast.value} }`);
|
|
27907
27905
|
case "NUMBER":
|
|
27908
|
-
return code.return(`
|
|
27906
|
+
return code.return(`this.literalValues.numbers[${numberCount++}]`);
|
|
27909
27907
|
case "STRING":
|
|
27910
|
-
return code.return(`
|
|
27908
|
+
return code.return(`this.literalValues.strings[${stringCount++}]`);
|
|
27911
27909
|
case "REFERENCE":
|
|
27912
|
-
const referenceIndex = dependencies.indexOf(ast.value);
|
|
27913
27910
|
if ((!isMeta && ast.value.includes(":")) || hasRange) {
|
|
27914
|
-
return code.return(`range(deps[${
|
|
27911
|
+
return code.return(`range(deps[${dependencyCount++}])`);
|
|
27915
27912
|
}
|
|
27916
27913
|
else {
|
|
27917
|
-
return code.return(`ref(deps[${
|
|
27914
|
+
return code.return(`ref(deps[${dependencyCount++}], ${isMeta ? "true" : "false"})`);
|
|
27918
27915
|
}
|
|
27919
27916
|
case "FUNCALL":
|
|
27920
27917
|
const args = compileFunctionArgs(ast).map((arg) => arg.assignResultToVariable());
|
|
@@ -27946,7 +27943,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27946
27943
|
const compiledFormula = {
|
|
27947
27944
|
execute: functionCache[cacheKey],
|
|
27948
27945
|
dependencies,
|
|
27949
|
-
|
|
27946
|
+
literalValues,
|
|
27950
27947
|
symbols,
|
|
27951
27948
|
tokens,
|
|
27952
27949
|
isBadExpression: false,
|
|
@@ -27958,33 +27955,31 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27958
27955
|
* References, numbers and strings are replaced with placeholders because
|
|
27959
27956
|
* the compiled formula does not depend on their actual value.
|
|
27960
27957
|
* Both `=A1+1+"2"` and `=A2+2+"3"` are compiled to the exact same function.
|
|
27961
|
-
*
|
|
27962
27958
|
* Spaces are also ignored to compute the cache key.
|
|
27963
27959
|
*
|
|
27964
|
-
* A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|
|
|
27960
|
+
* A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|C|+|C|+SUM(|N|,|N|,|S|)`
|
|
27965
27961
|
*/
|
|
27966
|
-
function compilationCacheKey(tokens
|
|
27962
|
+
function compilationCacheKey(tokens) {
|
|
27967
27963
|
let cacheKey = "";
|
|
27968
27964
|
for (const token of tokens) {
|
|
27969
27965
|
switch (token.type) {
|
|
27970
27966
|
case "STRING":
|
|
27971
|
-
|
|
27972
|
-
cacheKey += `|S${constantValues.strings.indexOf(value)}|`;
|
|
27967
|
+
cacheKey += "|S|";
|
|
27973
27968
|
break;
|
|
27974
27969
|
case "NUMBER":
|
|
27975
|
-
cacheKey +=
|
|
27970
|
+
cacheKey += "|N|";
|
|
27976
27971
|
break;
|
|
27977
27972
|
case "REFERENCE":
|
|
27978
27973
|
case "INVALID_REFERENCE":
|
|
27979
27974
|
if (token.value.includes(":")) {
|
|
27980
|
-
cacheKey +=
|
|
27975
|
+
cacheKey += "|R|";
|
|
27981
27976
|
}
|
|
27982
27977
|
else {
|
|
27983
|
-
cacheKey +=
|
|
27978
|
+
cacheKey += "|C|";
|
|
27984
27979
|
}
|
|
27985
27980
|
break;
|
|
27986
27981
|
case "SPACE":
|
|
27987
|
-
|
|
27982
|
+
// ignore spaces
|
|
27988
27983
|
break;
|
|
27989
27984
|
default:
|
|
27990
27985
|
cacheKey += token.value;
|
|
@@ -27997,7 +27992,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27997
27992
|
* Return formula arguments which are references, strings and numbers.
|
|
27998
27993
|
*/
|
|
27999
27994
|
function formulaArguments(tokens) {
|
|
28000
|
-
const
|
|
27995
|
+
const literalValues = {
|
|
28001
27996
|
numbers: [],
|
|
28002
27997
|
strings: [],
|
|
28003
27998
|
};
|
|
@@ -28011,15 +28006,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28011
28006
|
break;
|
|
28012
28007
|
case "STRING":
|
|
28013
28008
|
const value = removeStringQuotes(token.value);
|
|
28014
|
-
|
|
28015
|
-
constantValues.strings.push(value);
|
|
28016
|
-
}
|
|
28009
|
+
literalValues.strings.push({ value });
|
|
28017
28010
|
break;
|
|
28018
28011
|
case "NUMBER": {
|
|
28019
28012
|
const value = parseNumber(token.value, DEFAULT_LOCALE);
|
|
28020
|
-
|
|
28021
|
-
constantValues.numbers.push(value);
|
|
28022
|
-
}
|
|
28013
|
+
literalValues.numbers.push({ value });
|
|
28023
28014
|
break;
|
|
28024
28015
|
}
|
|
28025
28016
|
case "SYMBOL": {
|
|
@@ -28030,7 +28021,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28030
28021
|
}
|
|
28031
28022
|
return {
|
|
28032
28023
|
dependencies,
|
|
28033
|
-
|
|
28024
|
+
literalValues,
|
|
28034
28025
|
symbols,
|
|
28035
28026
|
};
|
|
28036
28027
|
}
|
|
@@ -68298,7 +68289,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68298
68289
|
border: 1px solid;
|
|
68299
68290
|
font-family: ${DEFAULT_FONT};
|
|
68300
68291
|
|
|
68301
|
-
|
|
68292
|
+
/* In readonly we always show the fx icon if the composer is empty, not matter the focus */
|
|
68293
|
+
.o-composer:empty:not(:focus):not(.active)::before,
|
|
68294
|
+
&.o-topbar-composer-readonly .o-composer:empty::before {
|
|
68302
68295
|
content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
|
|
68303
68296
|
position: relative;
|
|
68304
68297
|
top: 20%;
|
|
@@ -71659,10 +71652,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71659
71652
|
continue;
|
|
71660
71653
|
}
|
|
71661
71654
|
const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
|
|
71655
|
+
const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
|
|
71656
|
+
if (isIconSetReversed(rule.icons)) {
|
|
71657
|
+
iconSetAttrs.push(["reverse", "1"]);
|
|
71658
|
+
}
|
|
71662
71659
|
conditionalFormats.push(escapeXml /*xml*/ `
|
|
71663
71660
|
<conditionalFormatting sqref="${range}">
|
|
71664
71661
|
<cfRule ${formatAttributes(ruleAttributes)}>
|
|
71665
|
-
<iconSet
|
|
71662
|
+
<iconSet ${formatAttributes(iconSetAttrs)}>
|
|
71666
71663
|
${joinXmlNodes(cfValueObjectNodes)}
|
|
71667
71664
|
</iconSet>
|
|
71668
71665
|
</cfRule>
|
|
@@ -71680,9 +71677,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71680
71677
|
["stopIfTrue", cf.stopIfTrue ? 1 : 0],
|
|
71681
71678
|
];
|
|
71682
71679
|
}
|
|
71680
|
+
function isIconSetReversed(iconSet) {
|
|
71681
|
+
const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
|
|
71682
|
+
return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
|
|
71683
|
+
}
|
|
71683
71684
|
function getIconSet(iconSet) {
|
|
71684
|
-
return XLSX_ICONSET_MAP[
|
|
71685
|
-
|
|
71685
|
+
return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
|
|
71686
|
+
}
|
|
71687
|
+
/**
|
|
71688
|
+
* Partial detection based on "upper" point only.
|
|
71689
|
+
* We support any arbitrary icon in the set, while excel doesn't allow
|
|
71690
|
+
* mixing icons from different types.
|
|
71691
|
+
*/
|
|
71692
|
+
function detectIconsType(iconSet) {
|
|
71693
|
+
const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
|
|
71694
|
+
return type;
|
|
71686
71695
|
}
|
|
71687
71696
|
function thresholdAttributes(threshold, position) {
|
|
71688
71697
|
const type = getExcelThresholdType(threshold.type, position);
|
|
@@ -73606,9 +73615,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
73606
73615
|
exports.tokenize = tokenize;
|
|
73607
73616
|
|
|
73608
73617
|
|
|
73609
|
-
__info__.version = "18.0.
|
|
73610
|
-
__info__.date = "2025-03-
|
|
73611
|
-
__info__.hash = "
|
|
73618
|
+
__info__.version = "18.0.21";
|
|
73619
|
+
__info__.date = "2025-03-26T12:49:46.872Z";
|
|
73620
|
+
__info__.hash = "c687e1c";
|
|
73612
73621
|
|
|
73613
73622
|
|
|
73614
73623
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|