@odoo/o-spreadsheet 18.2.4 → 18.2.5
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 +131 -109
- package/dist/o-spreadsheet.d.ts +7 -5
- package/dist/o-spreadsheet.esm.js +131 -109
- package/dist/o-spreadsheet.iife.js +131 -109
- package/dist/o-spreadsheet.iife.min.js +371 -369
- package/dist/o_spreadsheet.xml +9 -6
- 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.2.
|
|
6
|
-
* @date 2025-03-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.5
|
|
6
|
+
* @date 2025-03-26T12:47:44.113Z
|
|
7
|
+
* @hash 4675edd
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -1132,7 +1132,10 @@
|
|
|
1132
1132
|
}
|
|
1133
1133
|
else if (stringVals.length === 4) {
|
|
1134
1134
|
const alpha = parseFloat(stringVals.pop() || "1");
|
|
1135
|
-
|
|
1135
|
+
if (isNaN(alpha)) {
|
|
1136
|
+
throw new Error("invalid alpha value");
|
|
1137
|
+
}
|
|
1138
|
+
alphaHex = Math.round(alpha * 255);
|
|
1136
1139
|
}
|
|
1137
1140
|
const vals = stringVals.map((val) => parseInt(val, 10));
|
|
1138
1141
|
if (alphaHex !== 255) {
|
|
@@ -7000,7 +7003,7 @@
|
|
|
7000
7003
|
*/
|
|
7001
7004
|
function canonicalizeNumberContent(content, locale) {
|
|
7002
7005
|
return content.startsWith("=")
|
|
7003
|
-
? canonicalizeFormula
|
|
7006
|
+
? canonicalizeFormula(content, locale)
|
|
7004
7007
|
: canonicalizeNumberLiteral(content, locale);
|
|
7005
7008
|
}
|
|
7006
7009
|
/**
|
|
@@ -7015,7 +7018,7 @@
|
|
|
7015
7018
|
*/
|
|
7016
7019
|
function canonicalizeContent(content, locale) {
|
|
7017
7020
|
return content.startsWith("=")
|
|
7018
|
-
? canonicalizeFormula
|
|
7021
|
+
? canonicalizeFormula(content, locale)
|
|
7019
7022
|
: canonicalizeLiteral(content, locale);
|
|
7020
7023
|
}
|
|
7021
7024
|
/**
|
|
@@ -7031,15 +7034,21 @@
|
|
|
7031
7034
|
? localizeFormula(content, locale)
|
|
7032
7035
|
: localizeLiteral(content, locale);
|
|
7033
7036
|
}
|
|
7037
|
+
/** Change a number string to its canonical form (en_US locale) */
|
|
7038
|
+
function canonicalizeNumberValue(content, locale) {
|
|
7039
|
+
return content.startsWith("=")
|
|
7040
|
+
? canonicalizeFormula(content, locale)
|
|
7041
|
+
: canonicalizeNumberLiteral(content, locale);
|
|
7042
|
+
}
|
|
7034
7043
|
/** Change a formula to its canonical form (en_US locale) */
|
|
7035
|
-
function canonicalizeFormula
|
|
7036
|
-
return _localizeFormula
|
|
7044
|
+
function canonicalizeFormula(formula, locale) {
|
|
7045
|
+
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
7037
7046
|
}
|
|
7038
7047
|
/** Change a formula from the canonical form to the given locale */
|
|
7039
7048
|
function localizeFormula(formula, locale) {
|
|
7040
|
-
return _localizeFormula
|
|
7049
|
+
return _localizeFormula(formula, DEFAULT_LOCALE, locale);
|
|
7041
7050
|
}
|
|
7042
|
-
function _localizeFormula
|
|
7051
|
+
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
7043
7052
|
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
7044
7053
|
fromLocale.decimalSeparator === toLocale.decimalSeparator) {
|
|
7045
7054
|
return formula;
|
|
@@ -7194,37 +7203,6 @@
|
|
|
7194
7203
|
return locale.dateFormat + " " + locale.timeFormat;
|
|
7195
7204
|
}
|
|
7196
7205
|
|
|
7197
|
-
/** Change a number string to its canonical form (en_US locale) */
|
|
7198
|
-
function canonicalizeNumberValue(content, locale) {
|
|
7199
|
-
return content.startsWith("=")
|
|
7200
|
-
? canonicalizeFormula(content, locale)
|
|
7201
|
-
: canonicalizeNumberLiteral(content, locale);
|
|
7202
|
-
}
|
|
7203
|
-
/** Change a formula to its canonical form (en_US locale) */
|
|
7204
|
-
function canonicalizeFormula(formula, locale) {
|
|
7205
|
-
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
7206
|
-
}
|
|
7207
|
-
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
7208
|
-
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
7209
|
-
fromLocale.decimalSeparator === toLocale.decimalSeparator) {
|
|
7210
|
-
return formula;
|
|
7211
|
-
}
|
|
7212
|
-
const tokens = tokenize(formula, fromLocale);
|
|
7213
|
-
let localizedFormula = "";
|
|
7214
|
-
for (const token of tokens) {
|
|
7215
|
-
if (token.type === "NUMBER") {
|
|
7216
|
-
localizedFormula += token.value.replace(fromLocale.decimalSeparator, toLocale.decimalSeparator);
|
|
7217
|
-
}
|
|
7218
|
-
else if (token.type === "ARG_SEPARATOR") {
|
|
7219
|
-
localizedFormula += toLocale.formulaArgSeparator;
|
|
7220
|
-
}
|
|
7221
|
-
else {
|
|
7222
|
-
localizedFormula += token.value;
|
|
7223
|
-
}
|
|
7224
|
-
}
|
|
7225
|
-
return localizedFormula;
|
|
7226
|
-
}
|
|
7227
|
-
|
|
7228
7206
|
function boolAnd(args) {
|
|
7229
7207
|
let foundBoolean = false;
|
|
7230
7208
|
let acc = true;
|
|
@@ -9600,6 +9578,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9600
9578
|
}
|
|
9601
9579
|
|
|
9602
9580
|
const TREND_LINE_XAXIS_ID = "x1";
|
|
9581
|
+
const MOVING_AVERAGE_TREND_LINE_XAXIS_ID = "xMovingAverage";
|
|
9603
9582
|
/**
|
|
9604
9583
|
* This file contains helpers that are common to different charts (mainly
|
|
9605
9584
|
* line, bar and pie charts)
|
|
@@ -9950,6 +9929,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9950
9929
|
}
|
|
9951
9930
|
return label;
|
|
9952
9931
|
}
|
|
9932
|
+
function isTrendLineAxis(axisID) {
|
|
9933
|
+
return axisID === TREND_LINE_XAXIS_ID || axisID === MOVING_AVERAGE_TREND_LINE_XAXIS_ID;
|
|
9934
|
+
}
|
|
9953
9935
|
|
|
9954
9936
|
/** This is a chartJS plugin that will draw the values of each data next to the point/bar/pie slice */
|
|
9955
9937
|
const chartShowValuesPlugin = {
|
|
@@ -9994,7 +9976,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9994
9976
|
const yMin = chart.chartArea.top;
|
|
9995
9977
|
const textsPositions = {};
|
|
9996
9978
|
for (const dataset of chart._metasets) {
|
|
9997
|
-
if (dataset.
|
|
9979
|
+
if (isTrendLineAxis(dataset.axisID) || dataset.hidden) {
|
|
9998
9980
|
continue;
|
|
9999
9981
|
}
|
|
10000
9982
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
@@ -10037,7 +10019,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10037
10019
|
const xMin = chart.chartArea.left;
|
|
10038
10020
|
const textsPositions = {};
|
|
10039
10021
|
for (const dataset of chart._metasets) {
|
|
10040
|
-
if (dataset.
|
|
10022
|
+
if (isTrendLineAxis(dataset.axisID)) {
|
|
10041
10023
|
return; // ignore trend lines
|
|
10042
10024
|
}
|
|
10043
10025
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
@@ -20545,11 +20527,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20545
20527
|
const _searchFor = toString(searchFor).toLowerCase();
|
|
20546
20528
|
const _textToSearch = toString(textToSearch).toLowerCase();
|
|
20547
20529
|
const _startingAt = toNumber(startingAt, this.locale);
|
|
20548
|
-
|
|
20549
|
-
|
|
20530
|
+
if (_textToSearch === "") {
|
|
20531
|
+
return {
|
|
20532
|
+
value: CellErrorType.GenericError,
|
|
20533
|
+
message: _t("The text_to_search must be non-empty."),
|
|
20534
|
+
};
|
|
20535
|
+
}
|
|
20536
|
+
if (_startingAt < 1) {
|
|
20537
|
+
return {
|
|
20538
|
+
value: CellErrorType.GenericError,
|
|
20539
|
+
message: _t("The starting_at (%s) must be greater than or equal to 1.", _startingAt),
|
|
20540
|
+
};
|
|
20541
|
+
}
|
|
20550
20542
|
const result = _textToSearch.indexOf(_searchFor, _startingAt - 1);
|
|
20551
|
-
|
|
20552
|
-
|
|
20543
|
+
if (result === -1) {
|
|
20544
|
+
return {
|
|
20545
|
+
value: CellErrorType.GenericError,
|
|
20546
|
+
message: _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor, _textToSearch),
|
|
20547
|
+
};
|
|
20548
|
+
}
|
|
20549
|
+
return { value: result + 1 };
|
|
20553
20550
|
},
|
|
20554
20551
|
isExported: true,
|
|
20555
20552
|
};
|
|
@@ -21884,11 +21881,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21884
21881
|
}
|
|
21885
21882
|
}
|
|
21886
21883
|
function compileTokensOrThrow(tokens) {
|
|
21887
|
-
const { dependencies,
|
|
21888
|
-
const cacheKey = compilationCacheKey(tokens
|
|
21884
|
+
const { dependencies, literalValues, symbols } = formulaArguments(tokens);
|
|
21885
|
+
const cacheKey = compilationCacheKey(tokens);
|
|
21889
21886
|
if (!functionCache[cacheKey]) {
|
|
21890
21887
|
const ast = parseTokens([...tokens]);
|
|
21891
21888
|
const scope = new Scope();
|
|
21889
|
+
let stringCount = 0;
|
|
21890
|
+
let numberCount = 0;
|
|
21891
|
+
let dependencyCount = 0;
|
|
21892
21892
|
if (ast.type === "BIN_OPERATION" && ast.value === ":") {
|
|
21893
21893
|
throw new BadExpressionError(_t("Invalid formula"));
|
|
21894
21894
|
}
|
|
@@ -21962,16 +21962,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21962
21962
|
case "BOOLEAN":
|
|
21963
21963
|
return code.return(`{ value: ${ast.value} }`);
|
|
21964
21964
|
case "NUMBER":
|
|
21965
|
-
return code.return(`
|
|
21965
|
+
return code.return(`this.literalValues.numbers[${numberCount++}]`);
|
|
21966
21966
|
case "STRING":
|
|
21967
|
-
return code.return(`
|
|
21967
|
+
return code.return(`this.literalValues.strings[${stringCount++}]`);
|
|
21968
21968
|
case "REFERENCE":
|
|
21969
|
-
const referenceIndex = dependencies.indexOf(ast.value);
|
|
21970
21969
|
if ((!isMeta && ast.value.includes(":")) || hasRange) {
|
|
21971
|
-
return code.return(`range(deps[${
|
|
21970
|
+
return code.return(`range(deps[${dependencyCount++}])`);
|
|
21972
21971
|
}
|
|
21973
21972
|
else {
|
|
21974
|
-
return code.return(`ref(deps[${
|
|
21973
|
+
return code.return(`ref(deps[${dependencyCount++}], ${isMeta ? "true" : "false"})`);
|
|
21975
21974
|
}
|
|
21976
21975
|
case "FUNCALL":
|
|
21977
21976
|
const args = compileFunctionArgs(ast).map((arg) => arg.assignResultToVariable());
|
|
@@ -22003,7 +22002,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22003
22002
|
const compiledFormula = {
|
|
22004
22003
|
execute: functionCache[cacheKey],
|
|
22005
22004
|
dependencies,
|
|
22006
|
-
|
|
22005
|
+
literalValues,
|
|
22007
22006
|
symbols,
|
|
22008
22007
|
tokens,
|
|
22009
22008
|
isBadExpression: false,
|
|
@@ -22016,33 +22015,31 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22016
22015
|
* References, numbers and strings are replaced with placeholders because
|
|
22017
22016
|
* the compiled formula does not depend on their actual value.
|
|
22018
22017
|
* Both `=A1+1+"2"` and `=A2+2+"3"` are compiled to the exact same function.
|
|
22019
|
-
*
|
|
22020
22018
|
* Spaces are also ignored to compute the cache key.
|
|
22021
22019
|
*
|
|
22022
|
-
* A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|
|
|
22020
|
+
* A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|C|+|C|+SUM(|N|,|N|,|S|)`
|
|
22023
22021
|
*/
|
|
22024
|
-
function compilationCacheKey(tokens
|
|
22022
|
+
function compilationCacheKey(tokens) {
|
|
22025
22023
|
let cacheKey = "";
|
|
22026
22024
|
for (const token of tokens) {
|
|
22027
22025
|
switch (token.type) {
|
|
22028
22026
|
case "STRING":
|
|
22029
|
-
|
|
22030
|
-
cacheKey += `|S${constantValues.strings.indexOf(value)}|`;
|
|
22027
|
+
cacheKey += "|S|";
|
|
22031
22028
|
break;
|
|
22032
22029
|
case "NUMBER":
|
|
22033
|
-
cacheKey +=
|
|
22030
|
+
cacheKey += "|N|";
|
|
22034
22031
|
break;
|
|
22035
22032
|
case "REFERENCE":
|
|
22036
22033
|
case "INVALID_REFERENCE":
|
|
22037
22034
|
if (token.value.includes(":")) {
|
|
22038
|
-
cacheKey +=
|
|
22035
|
+
cacheKey += "|R|";
|
|
22039
22036
|
}
|
|
22040
22037
|
else {
|
|
22041
|
-
cacheKey +=
|
|
22038
|
+
cacheKey += "|C|";
|
|
22042
22039
|
}
|
|
22043
22040
|
break;
|
|
22044
22041
|
case "SPACE":
|
|
22045
|
-
|
|
22042
|
+
// ignore spaces
|
|
22046
22043
|
break;
|
|
22047
22044
|
default:
|
|
22048
22045
|
cacheKey += token.value;
|
|
@@ -22055,7 +22052,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22055
22052
|
* Return formula arguments which are references, strings and numbers.
|
|
22056
22053
|
*/
|
|
22057
22054
|
function formulaArguments(tokens) {
|
|
22058
|
-
const
|
|
22055
|
+
const literalValues = {
|
|
22059
22056
|
numbers: [],
|
|
22060
22057
|
strings: [],
|
|
22061
22058
|
};
|
|
@@ -22069,15 +22066,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22069
22066
|
break;
|
|
22070
22067
|
case "STRING":
|
|
22071
22068
|
const value = removeStringQuotes(token.value);
|
|
22072
|
-
|
|
22073
|
-
constantValues.strings.push(value);
|
|
22074
|
-
}
|
|
22069
|
+
literalValues.strings.push({ value });
|
|
22075
22070
|
break;
|
|
22076
22071
|
case "NUMBER": {
|
|
22077
22072
|
const value = parseNumber(token.value, DEFAULT_LOCALE);
|
|
22078
|
-
|
|
22079
|
-
constantValues.numbers.push(value);
|
|
22080
|
-
}
|
|
22073
|
+
literalValues.numbers.push({ value });
|
|
22081
22074
|
break;
|
|
22082
22075
|
}
|
|
22083
22076
|
case "SYMBOL": {
|
|
@@ -22088,7 +22081,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22088
22081
|
}
|
|
22089
22082
|
return {
|
|
22090
22083
|
dependencies,
|
|
22091
|
-
|
|
22084
|
+
literalValues,
|
|
22092
22085
|
symbols,
|
|
22093
22086
|
};
|
|
22094
22087
|
}
|
|
@@ -23009,9 +23002,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23009
23002
|
/** In XLSX color format (no #) */
|
|
23010
23003
|
const AUTO_COLOR = "000000";
|
|
23011
23004
|
const XLSX_ICONSET_MAP = {
|
|
23012
|
-
|
|
23005
|
+
arrows: "3Arrows",
|
|
23013
23006
|
smiley: "3Symbols",
|
|
23014
|
-
|
|
23007
|
+
dots: "3TrafficLights1",
|
|
23015
23008
|
};
|
|
23016
23009
|
const NAMESPACE = {
|
|
23017
23010
|
styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
|
@@ -23542,6 +23535,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23542
23535
|
};
|
|
23543
23536
|
/** Map between legend position in XLSX file and human readable position */
|
|
23544
23537
|
const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
|
|
23538
|
+
none: "none",
|
|
23545
23539
|
b: "bottom",
|
|
23546
23540
|
t: "top",
|
|
23547
23541
|
l: "left",
|
|
@@ -26304,7 +26298,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26304
26298
|
default: "ffffff",
|
|
26305
26299
|
}).asString(),
|
|
26306
26300
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
|
|
26307
|
-
default: "
|
|
26301
|
+
default: "none",
|
|
26308
26302
|
}).asString()],
|
|
26309
26303
|
stacked: barChartGrouping === "stacked",
|
|
26310
26304
|
fontColor: "000000",
|
|
@@ -26338,7 +26332,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26338
26332
|
default: "ffffff",
|
|
26339
26333
|
}).asString(),
|
|
26340
26334
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(chartElement, "c:legendPos", "val", {
|
|
26341
|
-
default: "
|
|
26335
|
+
default: "none",
|
|
26342
26336
|
}).asString()],
|
|
26343
26337
|
stacked: barChartGrouping === "stacked",
|
|
26344
26338
|
fontColor: "000000",
|
|
@@ -28950,7 +28944,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28950
28944
|
}
|
|
28951
28945
|
}
|
|
28952
28946
|
else if (dataSets.length === 1) {
|
|
28953
|
-
|
|
28947
|
+
const dataLength = getData(getters, dataSets[0]).length;
|
|
28948
|
+
for (let i = 0; i < dataLength; i++) {
|
|
28954
28949
|
labels.formattedValues.push("");
|
|
28955
28950
|
labels.values.push("");
|
|
28956
28951
|
}
|
|
@@ -29133,7 +29128,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29133
29128
|
function getScatterChartDatasets(definition, args) {
|
|
29134
29129
|
const dataSets = getLineChartDatasets(definition, args);
|
|
29135
29130
|
for (const dataSet of dataSets) {
|
|
29136
|
-
if (dataSet.xAxisID
|
|
29131
|
+
if (!isTrendLineAxis(dataSet.xAxisID)) {
|
|
29137
29132
|
dataSet.showLine = false;
|
|
29138
29133
|
}
|
|
29139
29134
|
}
|
|
@@ -29260,7 +29255,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29260
29255
|
const borderColor = config.color || lightenColor(rgbaToHex(defaultBorderColor), 0.5);
|
|
29261
29256
|
return {
|
|
29262
29257
|
type: "line",
|
|
29263
|
-
xAxisID:
|
|
29258
|
+
xAxisID: config.type === "trailingMovingAverage"
|
|
29259
|
+
? MOVING_AVERAGE_TREND_LINE_XAXIS_ID
|
|
29260
|
+
: TREND_LINE_XAXIS_ID,
|
|
29264
29261
|
yAxisID: dataset.yAxisID,
|
|
29265
29262
|
label: dataset.label ? _t("Trend line for %s", dataset.label) : "",
|
|
29266
29263
|
data,
|
|
@@ -29335,22 +29332,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29335
29332
|
const { dataSetsValues } = args;
|
|
29336
29333
|
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
|
|
29337
29334
|
const colors = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
|
|
29335
|
+
const fontColor = chartFontColor(definition.background);
|
|
29338
29336
|
return {
|
|
29339
29337
|
...getLegendDisplayOptions(definition),
|
|
29340
29338
|
labels: {
|
|
29341
|
-
color: chartFontColor(definition.background),
|
|
29342
29339
|
usePointStyle: true,
|
|
29343
|
-
|
|
29344
|
-
generateLabels: (c) =>
|
|
29345
|
-
//@ts-ignore
|
|
29346
|
-
c.data.labels.map((label, index) => ({
|
|
29340
|
+
generateLabels: (c) => c.data.labels?.map((label, index) => ({
|
|
29347
29341
|
text: truncateLabel(String(label)),
|
|
29348
29342
|
strokeStyle: colors[index],
|
|
29349
29343
|
fillStyle: colors[index],
|
|
29350
29344
|
pointStyle: "rect",
|
|
29351
|
-
hidden: false,
|
|
29352
29345
|
lineWidth: 2,
|
|
29353
|
-
|
|
29346
|
+
fontColor,
|
|
29347
|
+
})) || [],
|
|
29354
29348
|
filter: (legendItem, data) => {
|
|
29355
29349
|
return "datasetIndex" in legendItem
|
|
29356
29350
|
? !data.datasets[legendItem.datasetIndex].hidden
|
|
@@ -29483,7 +29477,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29483
29477
|
color: fontColor,
|
|
29484
29478
|
usePointStyle: true,
|
|
29485
29479
|
generateLabels: (chart) => chart.data.datasets.map((dataset, index) => {
|
|
29486
|
-
if (dataset["xAxisID"]
|
|
29480
|
+
if (isTrendLineAxis(dataset["xAxisID"])) {
|
|
29487
29481
|
return {
|
|
29488
29482
|
text: truncateLabel(dataset.label),
|
|
29489
29483
|
fontColor,
|
|
@@ -29541,6 +29535,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29541
29535
|
offset: false,
|
|
29542
29536
|
display: false,
|
|
29543
29537
|
};
|
|
29538
|
+
scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID] = {
|
|
29539
|
+
...scales.x,
|
|
29540
|
+
offset: false,
|
|
29541
|
+
display: false,
|
|
29542
|
+
};
|
|
29544
29543
|
}
|
|
29545
29544
|
return scales;
|
|
29546
29545
|
}
|
|
@@ -29574,6 +29573,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29574
29573
|
...scales.x,
|
|
29575
29574
|
display: false,
|
|
29576
29575
|
};
|
|
29576
|
+
scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID] = {
|
|
29577
|
+
...scales.x,
|
|
29578
|
+
display: false,
|
|
29579
|
+
};
|
|
29577
29580
|
if (axisType === "category" || axisType === "time") {
|
|
29578
29581
|
/* We add a second x axis here to draw the trend lines, with the labels length being
|
|
29579
29582
|
* set so that the second axis points match the classical x axis
|
|
@@ -29582,6 +29585,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29582
29585
|
scales[TREND_LINE_XAXIS_ID]["type"] = "category";
|
|
29583
29586
|
scales[TREND_LINE_XAXIS_ID]["labels"] = range(0, maxLength).map((x) => x.toString());
|
|
29584
29587
|
scales[TREND_LINE_XAXIS_ID]["offset"] = false;
|
|
29588
|
+
scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID]["type"] = "category";
|
|
29589
|
+
scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID]["offset"] = false;
|
|
29585
29590
|
}
|
|
29586
29591
|
}
|
|
29587
29592
|
return scales;
|
|
@@ -29900,9 +29905,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29900
29905
|
external: customTooltipHandler,
|
|
29901
29906
|
callbacks: {
|
|
29902
29907
|
title: function (tooltipItems) {
|
|
29903
|
-
return tooltipItems.some((item) => item.dataset.xAxisID
|
|
29904
|
-
? undefined
|
|
29905
|
-
: "";
|
|
29908
|
+
return tooltipItems.some((item) => !isTrendLineAxis(item.dataset.xAxisID)) ? undefined : "";
|
|
29906
29909
|
},
|
|
29907
29910
|
beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
|
|
29908
29911
|
label: function (tooltipItem) {
|
|
@@ -29929,7 +29932,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29929
29932
|
if (axisType === "linear") {
|
|
29930
29933
|
tooltip.callbacks.label = (tooltipItem) => {
|
|
29931
29934
|
const dataSetPoint = tooltipItem.parsed.y;
|
|
29932
|
-
let label = tooltipItem.dataset.xAxisID
|
|
29935
|
+
let label = isTrendLineAxis(tooltipItem.dataset.xAxisID)
|
|
29933
29936
|
? ""
|
|
29934
29937
|
: tooltipItem.parsed.x;
|
|
29935
29938
|
if (typeof label === "string" && isNumber(label, locale)) {
|
|
@@ -29951,8 +29954,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29951
29954
|
}
|
|
29952
29955
|
tooltip.callbacks.beforeLabel = (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label;
|
|
29953
29956
|
tooltip.callbacks.title = function (tooltipItems) {
|
|
29954
|
-
const displayTooltipTitle = axisType !== "linear" &&
|
|
29955
|
-
tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
|
|
29957
|
+
const displayTooltipTitle = axisType !== "linear" && tooltipItems.some((item) => !isTrendLineAxis(item.dataset.xAxisID));
|
|
29956
29958
|
return displayTooltipTitle ? undefined : "";
|
|
29957
29959
|
};
|
|
29958
29960
|
return tooltip;
|
|
@@ -34206,6 +34208,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34206
34208
|
CHART_COMMON_OPTIONS: CHART_COMMON_OPTIONS,
|
|
34207
34209
|
GaugeChart: GaugeChart,
|
|
34208
34210
|
LineChart: LineChart,
|
|
34211
|
+
MOVING_AVERAGE_TREND_LINE_XAXIS_ID: MOVING_AVERAGE_TREND_LINE_XAXIS_ID,
|
|
34209
34212
|
PieChart: PieChart,
|
|
34210
34213
|
ScorecardChart: ScorecardChart$1,
|
|
34211
34214
|
TREND_LINE_XAXIS_ID: TREND_LINE_XAXIS_ID,
|
|
@@ -34235,6 +34238,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34235
34238
|
getDefinedAxis: getDefinedAxis,
|
|
34236
34239
|
getPieColors: getPieColors,
|
|
34237
34240
|
getSmartChartDefinition: getSmartChartDefinition,
|
|
34241
|
+
isTrendLineAxis: isTrendLineAxis,
|
|
34238
34242
|
shouldRemoveFirstLabel: shouldRemoveFirstLabel,
|
|
34239
34243
|
toExcelDataset: toExcelDataset,
|
|
34240
34244
|
toExcelLabelRange: toExcelLabelRange,
|
|
@@ -36282,9 +36286,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36282
36286
|
}
|
|
36283
36287
|
}
|
|
36284
36288
|
}
|
|
36285
|
-
|
|
36286
|
-
// =|N0|+|N1|+|N0| -> =|N|+|N|+|N|
|
|
36287
|
-
const normalizedFormula = cell.compiledFormula.normalizedFormula.replace(/(|\w)(\d)(|)/g, "$1$3");
|
|
36289
|
+
const normalizedFormula = cell.compiledFormula.normalizedFormula;
|
|
36288
36290
|
return hash(fingerprintVector) + normalizedFormula;
|
|
36289
36291
|
}
|
|
36290
36292
|
getLiteralFingerprint(position) {
|
|
@@ -39629,9 +39631,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39629
39631
|
if (!runtime || !("chartJsConfig" in runtime)) {
|
|
39630
39632
|
return [];
|
|
39631
39633
|
}
|
|
39632
|
-
return runtime.chartJsConfig.data.datasets
|
|
39634
|
+
return runtime.chartJsConfig.data.datasets
|
|
39635
|
+
.filter((d) => !isTrendLineAxis(d["xAxisID"] ?? ""))
|
|
39636
|
+
.map((d) => d.label);
|
|
39633
39637
|
}
|
|
39634
|
-
|
|
39638
|
+
updateEditedSeries(ev) {
|
|
39635
39639
|
this.state.index = ev.target.selectedIndex;
|
|
39636
39640
|
}
|
|
39637
39641
|
updateDataSeriesColor(color) {
|
|
@@ -39644,7 +39648,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39644
39648
|
};
|
|
39645
39649
|
this.props.updateChart(this.props.figureId, { dataSets });
|
|
39646
39650
|
}
|
|
39647
|
-
|
|
39651
|
+
getDataSeriesColor() {
|
|
39648
39652
|
const dataSets = this.props.definition.dataSets;
|
|
39649
39653
|
if (!dataSets?.[this.state.index])
|
|
39650
39654
|
return "";
|
|
@@ -39664,7 +39668,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39664
39668
|
};
|
|
39665
39669
|
this.props.updateChart(this.props.figureId, { dataSets });
|
|
39666
39670
|
}
|
|
39667
|
-
|
|
39671
|
+
getDataSeriesLabel() {
|
|
39668
39672
|
const dataSets = this.props.definition.dataSets;
|
|
39669
39673
|
return dataSets[this.state.index]?.label || this.getDataSeries()[this.state.index];
|
|
39670
39674
|
}
|
|
@@ -39777,7 +39781,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39777
39781
|
}
|
|
39778
39782
|
this.updateTrendLineValue(index, { window });
|
|
39779
39783
|
}
|
|
39780
|
-
|
|
39784
|
+
getDataSeriesColor(index) {
|
|
39781
39785
|
const dataSets = this.props.definition.dataSets;
|
|
39782
39786
|
if (!dataSets?.[index])
|
|
39783
39787
|
return "";
|
|
@@ -39788,7 +39792,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39788
39792
|
}
|
|
39789
39793
|
getTrendLineColor(index) {
|
|
39790
39794
|
return (this.getTrendLineConfiguration(index)?.color ??
|
|
39791
|
-
setColorAlpha(this.
|
|
39795
|
+
setColorAlpha(this.getDataSeriesColor(index), 0.5));
|
|
39792
39796
|
}
|
|
39793
39797
|
updateTrendLineColor(index, color) {
|
|
39794
39798
|
this.updateTrendLineValue(index, { color });
|
|
@@ -70768,7 +70772,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70768
70772
|
border: 1px solid;
|
|
70769
70773
|
font-family: ${DEFAULT_FONT};
|
|
70770
70774
|
|
|
70771
|
-
|
|
70775
|
+
/* In readonly we always show the fx icon if the composer is empty, not matter the focus */
|
|
70776
|
+
.o-composer:empty:not(:focus):not(.active)::before,
|
|
70777
|
+
&.o-topbar-composer-readonly .o-composer:empty::before {
|
|
70772
70778
|
content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
|
|
70773
70779
|
position: relative;
|
|
70774
70780
|
top: 20%;
|
|
@@ -74094,10 +74100,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74094
74100
|
continue;
|
|
74095
74101
|
}
|
|
74096
74102
|
const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
|
|
74103
|
+
const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
|
|
74104
|
+
if (isIconSetReversed(rule.icons)) {
|
|
74105
|
+
iconSetAttrs.push(["reverse", "1"]);
|
|
74106
|
+
}
|
|
74097
74107
|
conditionalFormats.push(escapeXml /*xml*/ `
|
|
74098
74108
|
<conditionalFormatting sqref="${range}">
|
|
74099
74109
|
<cfRule ${formatAttributes(ruleAttributes)}>
|
|
74100
|
-
<iconSet
|
|
74110
|
+
<iconSet ${formatAttributes(iconSetAttrs)}>
|
|
74101
74111
|
${joinXmlNodes(cfValueObjectNodes)}
|
|
74102
74112
|
</iconSet>
|
|
74103
74113
|
</cfRule>
|
|
@@ -74115,9 +74125,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74115
74125
|
["stopIfTrue", cf.stopIfTrue ? 1 : 0],
|
|
74116
74126
|
];
|
|
74117
74127
|
}
|
|
74128
|
+
function isIconSetReversed(iconSet) {
|
|
74129
|
+
const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
|
|
74130
|
+
return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
|
|
74131
|
+
}
|
|
74118
74132
|
function getIconSet(iconSet) {
|
|
74119
|
-
return XLSX_ICONSET_MAP[
|
|
74120
|
-
|
|
74133
|
+
return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
|
|
74134
|
+
}
|
|
74135
|
+
/**
|
|
74136
|
+
* Partial detection based on "upper" point only.
|
|
74137
|
+
* We support any arbitrary icon in the set, while excel doesn't allow
|
|
74138
|
+
* mixing icons from different types.
|
|
74139
|
+
*/
|
|
74140
|
+
function detectIconsType(iconSet) {
|
|
74141
|
+
const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
|
|
74142
|
+
return type;
|
|
74121
74143
|
}
|
|
74122
74144
|
function thresholdAttributes(threshold, position) {
|
|
74123
74145
|
const type = getExcelThresholdType(threshold.type, position);
|
|
@@ -76067,9 +76089,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
76067
76089
|
exports.tokenize = tokenize;
|
|
76068
76090
|
|
|
76069
76091
|
|
|
76070
|
-
__info__.version = "18.2.
|
|
76071
|
-
__info__.date = "2025-03-
|
|
76072
|
-
__info__.hash = "
|
|
76092
|
+
__info__.version = "18.2.5";
|
|
76093
|
+
__info__.date = "2025-03-26T12:47:44.113Z";
|
|
76094
|
+
__info__.hash = "4675edd";
|
|
76073
76095
|
|
|
76074
76096
|
|
|
76075
76097
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|