@odoo/o-spreadsheet 18.0.28 → 18.0.30
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 +354 -243
- package/dist/o-spreadsheet.d.ts +33 -32
- package/dist/o-spreadsheet.esm.js +354 -243
- package/dist/o-spreadsheet.iife.js +354 -243
- package/dist/o-spreadsheet.iife.min.js +364 -364
- package/dist/o_spreadsheet.xml +6 -5
- 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-05-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.0.30
|
|
6
|
+
* @date 2025-05-26T12:35:05.184Z
|
|
7
|
+
* @hash 838c4f7
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -1452,18 +1452,53 @@ function lettersToNumber(letters) {
|
|
|
1452
1452
|
let result = 0;
|
|
1453
1453
|
const l = letters.length;
|
|
1454
1454
|
for (let i = 0; i < l; i++) {
|
|
1455
|
-
const
|
|
1456
|
-
const colIndex = charCode >= 65 && charCode <= 90 ? charCode - 64 : charCode - 96;
|
|
1455
|
+
const colIndex = charToNumber(letters[i]);
|
|
1457
1456
|
result = result * 26 + colIndex;
|
|
1458
1457
|
}
|
|
1459
1458
|
return result - 1;
|
|
1460
1459
|
}
|
|
1460
|
+
function charToNumber(char) {
|
|
1461
|
+
const charCode = char.charCodeAt(0);
|
|
1462
|
+
return charCode >= 65 && charCode <= 90 ? charCode - 64 : charCode - 96;
|
|
1463
|
+
}
|
|
1461
1464
|
function isCharALetter(char) {
|
|
1462
1465
|
return (char >= "A" && char <= "Z") || (char >= "a" && char <= "z");
|
|
1463
1466
|
}
|
|
1464
1467
|
function isCharADigit(char) {
|
|
1465
1468
|
return char >= "0" && char <= "9";
|
|
1466
1469
|
}
|
|
1470
|
+
// we limit the max column to 3 letters and max row to 7 digits for performance reasons
|
|
1471
|
+
const MAX_COL = lettersToNumber("ZZZ");
|
|
1472
|
+
const MAX_ROW = 9999998;
|
|
1473
|
+
function consumeSpaces(chars) {
|
|
1474
|
+
while (chars.current === " ") {
|
|
1475
|
+
chars.advanceBy(1);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
function consumeLetters(chars) {
|
|
1479
|
+
if (chars.current === "$")
|
|
1480
|
+
chars.advanceBy(1);
|
|
1481
|
+
if (!chars.current || !isCharALetter(chars.current)) {
|
|
1482
|
+
return -1;
|
|
1483
|
+
}
|
|
1484
|
+
let colCoordinate = 0;
|
|
1485
|
+
while (chars.current && isCharALetter(chars.current)) {
|
|
1486
|
+
colCoordinate = colCoordinate * 26 + charToNumber(chars.shift());
|
|
1487
|
+
}
|
|
1488
|
+
return colCoordinate;
|
|
1489
|
+
}
|
|
1490
|
+
function consumeDigits(chars) {
|
|
1491
|
+
if (chars.current === "$")
|
|
1492
|
+
chars.advanceBy(1);
|
|
1493
|
+
if (!chars.current || !isCharADigit(chars.current)) {
|
|
1494
|
+
return -1;
|
|
1495
|
+
}
|
|
1496
|
+
let num = 0;
|
|
1497
|
+
while (chars.current && isCharADigit(chars.current)) {
|
|
1498
|
+
num = num * 10 + Number(chars.shift());
|
|
1499
|
+
}
|
|
1500
|
+
return num;
|
|
1501
|
+
}
|
|
1467
1502
|
/**
|
|
1468
1503
|
* Convert a "XC" coordinate to cartesian coordinates.
|
|
1469
1504
|
*
|
|
@@ -1474,33 +1509,17 @@ function isCharADigit(char) {
|
|
|
1474
1509
|
* Note: it also accepts lowercase coordinates, but not fixed references
|
|
1475
1510
|
*/
|
|
1476
1511
|
function toCartesian(xc) {
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
// Process letter part
|
|
1482
|
-
if (xc[i] === "$")
|
|
1483
|
-
i++;
|
|
1484
|
-
while (i < xc.length && isCharALetter(xc[i])) {
|
|
1485
|
-
letterPart += xc[i++];
|
|
1486
|
-
}
|
|
1487
|
-
if (letterPart.length === 0 || letterPart.length > 3) {
|
|
1488
|
-
// limit to max 3 letters for performance reasons
|
|
1512
|
+
const chars = new TokenizingChars(xc);
|
|
1513
|
+
consumeSpaces(chars);
|
|
1514
|
+
const letterPart = consumeLetters(chars);
|
|
1515
|
+
if (letterPart === -1 || !chars.current) {
|
|
1489
1516
|
throw new Error(`Invalid cell description: ${xc}`);
|
|
1490
1517
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
}
|
|
1497
|
-
if (i !== xc.length || numberPart.length === 0 || numberPart.length > 7) {
|
|
1498
|
-
// limit to max 7 numbers for performance reasons
|
|
1499
|
-
throw new Error(`Invalid cell description: ${xc}`);
|
|
1500
|
-
}
|
|
1501
|
-
const col = lettersToNumber(letterPart);
|
|
1502
|
-
const row = Number(numberPart) - 1;
|
|
1503
|
-
if (isNaN(row)) {
|
|
1518
|
+
const num = consumeDigits(chars);
|
|
1519
|
+
consumeSpaces(chars);
|
|
1520
|
+
const col = letterPart - 1;
|
|
1521
|
+
const row = num - 1;
|
|
1522
|
+
if (!chars.isOver() || col > MAX_COL || row > MAX_ROW) {
|
|
1504
1523
|
throw new Error(`Invalid cell description: ${xc}`);
|
|
1505
1524
|
}
|
|
1506
1525
|
return { col, row };
|
|
@@ -1912,67 +1931,6 @@ class LazyTranslatedString extends String {
|
|
|
1912
1931
|
}
|
|
1913
1932
|
}
|
|
1914
1933
|
|
|
1915
|
-
/** Reference of a cell (eg. A1, $B$5) */
|
|
1916
|
-
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
1917
|
-
// Same as above, but matches the exact string (nothing before or after)
|
|
1918
|
-
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
1919
|
-
/** Reference of a column header (eg. A, AB, $A) */
|
|
1920
|
-
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
1921
|
-
/** Reference of a row header (eg. 1, $1) */
|
|
1922
|
-
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
1923
|
-
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
1924
|
-
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
1925
|
-
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
1926
|
-
const rowReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([0-9]{1,7})$/, "i");
|
|
1927
|
-
/** Reference of a normal range or a full row range (eg. A1:B1, 1:$5, $A2:5) */
|
|
1928
|
-
const fullRowXc = /(\$?[A-Z]{1,3})?\$?[0-9]{1,7}\s*:\s*(\$?[A-Z]{1,3})?\$?[0-9]{1,7}\s*/i;
|
|
1929
|
-
/** Reference of a normal range or a column row range (eg. A1:B1, A:$B, $A1:C) */
|
|
1930
|
-
const fullColXc = /\$?[A-Z]{1,3}(\$?[0-9]{1,7})?\s*:\s*\$?[A-Z]{1,3}(\$?[0-9]{1,7})?\s*/i;
|
|
1931
|
-
/** Reference of a cell or a range, it can be a bounded range, a full row or a full column */
|
|
1932
|
-
const rangeReference = new RegExp(/^\s*('.+'!|[^']+!)?/.source +
|
|
1933
|
-
"(" +
|
|
1934
|
-
[cellReference.source, fullRowXc.source, fullColXc.source].join("|") +
|
|
1935
|
-
")" +
|
|
1936
|
-
/$/.source, "i");
|
|
1937
|
-
/**
|
|
1938
|
-
* Return true if the given xc is the reference of a column (e.g. A or AC or Sheet1!A)
|
|
1939
|
-
*/
|
|
1940
|
-
function isColReference(xc) {
|
|
1941
|
-
return colReference.test(xc);
|
|
1942
|
-
}
|
|
1943
|
-
/**
|
|
1944
|
-
* Return true if the given xc is the reference of a column (e.g. 1 or Sheet1!1)
|
|
1945
|
-
*/
|
|
1946
|
-
function isRowReference(xc) {
|
|
1947
|
-
return rowReference.test(xc);
|
|
1948
|
-
}
|
|
1949
|
-
function isColHeader(str) {
|
|
1950
|
-
return colHeader.test(str);
|
|
1951
|
-
}
|
|
1952
|
-
function isRowHeader(str) {
|
|
1953
|
-
return rowHeader.test(str);
|
|
1954
|
-
}
|
|
1955
|
-
/**
|
|
1956
|
-
* Return true if the given xc is the reference of a single cell,
|
|
1957
|
-
* without any specified sheet (e.g. A1)
|
|
1958
|
-
*/
|
|
1959
|
-
function isSingleCellReference(xc) {
|
|
1960
|
-
return singleCellReference.test(xc);
|
|
1961
|
-
}
|
|
1962
|
-
function splitReference(ref) {
|
|
1963
|
-
if (!ref.includes("!")) {
|
|
1964
|
-
return { xc: ref };
|
|
1965
|
-
}
|
|
1966
|
-
const parts = ref.split("!");
|
|
1967
|
-
const xc = parts.pop();
|
|
1968
|
-
const sheetName = getUnquotedSheetName(parts.join("!")) || undefined;
|
|
1969
|
-
return { sheetName, xc };
|
|
1970
|
-
}
|
|
1971
|
-
/** Return a reference SheetName!xc from the given arguments */
|
|
1972
|
-
function getFullReference(sheetName, xc) {
|
|
1973
|
-
return sheetName !== undefined ? `${getCanonicalSymbolName(sheetName)}!${xc}` : xc;
|
|
1974
|
-
}
|
|
1975
|
-
|
|
1976
1934
|
/**
|
|
1977
1935
|
* Convert from a cartesian reference to a Zone
|
|
1978
1936
|
* The range boundaries will be kept in the same order as the
|
|
@@ -1990,63 +1948,55 @@ function getFullReference(sheetName, xc) {
|
|
|
1990
1948
|
*
|
|
1991
1949
|
*/
|
|
1992
1950
|
function toZoneWithoutBoundaryChanges(xc) {
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
if (
|
|
1997
|
-
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
if (xc.includes(":")) {
|
|
2002
|
-
[firstRangePart, secondRangePart] = xc.split(":");
|
|
2003
|
-
firstRangePart = firstRangePart.trim();
|
|
2004
|
-
secondRangePart = secondRangePart.trim();
|
|
2005
|
-
}
|
|
2006
|
-
else {
|
|
2007
|
-
firstRangePart = xc.trim();
|
|
2008
|
-
}
|
|
1951
|
+
const chars = new TokenizingChars(xc);
|
|
1952
|
+
consumeSpaces(chars);
|
|
1953
|
+
const sheetSeparatorIndex = xc.indexOf("!");
|
|
1954
|
+
if (sheetSeparatorIndex !== -1) {
|
|
1955
|
+
chars.advanceBy(sheetSeparatorIndex + 1);
|
|
1956
|
+
}
|
|
1957
|
+
const leftLetters = consumeLetters(chars);
|
|
1958
|
+
const leftNumbers = consumeDigits(chars);
|
|
2009
1959
|
let top, bottom, left, right;
|
|
2010
1960
|
let fullCol = false;
|
|
2011
1961
|
let fullRow = false;
|
|
2012
1962
|
let hasHeader = false;
|
|
2013
|
-
if (
|
|
2014
|
-
left = right =
|
|
1963
|
+
if (leftNumbers === -1) {
|
|
1964
|
+
left = right = leftLetters - 1;
|
|
2015
1965
|
top = bottom = 0;
|
|
2016
1966
|
fullCol = true;
|
|
2017
1967
|
}
|
|
2018
|
-
else if (
|
|
2019
|
-
top = bottom =
|
|
1968
|
+
else if (leftLetters === -1) {
|
|
1969
|
+
top = bottom = leftNumbers - 1;
|
|
2020
1970
|
left = right = 0;
|
|
2021
1971
|
fullRow = true;
|
|
2022
1972
|
}
|
|
2023
1973
|
else {
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
top = bottom = c.row;
|
|
1974
|
+
left = right = leftLetters - 1;
|
|
1975
|
+
top = bottom = leftNumbers - 1;
|
|
2027
1976
|
hasHeader = true;
|
|
2028
1977
|
}
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
1978
|
+
consumeSpaces(chars);
|
|
1979
|
+
if (chars.current === ":") {
|
|
1980
|
+
chars.advanceBy(1);
|
|
1981
|
+
consumeSpaces(chars);
|
|
1982
|
+
const rightLetters = consumeLetters(chars);
|
|
1983
|
+
const rightNumbers = consumeDigits(chars);
|
|
1984
|
+
if (rightNumbers === -1) {
|
|
1985
|
+
right = rightLetters - 1;
|
|
2032
1986
|
fullCol = true;
|
|
2033
1987
|
}
|
|
2034
|
-
else if (
|
|
2035
|
-
bottom =
|
|
1988
|
+
else if (rightLetters === -1) {
|
|
1989
|
+
bottom = rightNumbers - 1;
|
|
2036
1990
|
fullRow = true;
|
|
2037
1991
|
}
|
|
2038
1992
|
else {
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
bottom = c.row;
|
|
1993
|
+
right = rightLetters - 1;
|
|
1994
|
+
bottom = rightNumbers - 1;
|
|
2042
1995
|
top = fullCol ? bottom : top;
|
|
2043
1996
|
left = fullRow ? right : left;
|
|
2044
1997
|
hasHeader = true;
|
|
2045
1998
|
}
|
|
2046
1999
|
}
|
|
2047
|
-
if (fullCol && fullRow) {
|
|
2048
|
-
throw new Error("Wrong zone xc. The zone cannot be at the same time a full column and a full row");
|
|
2049
|
-
}
|
|
2050
2000
|
const zone = {
|
|
2051
2001
|
top,
|
|
2052
2002
|
left,
|
|
@@ -2075,7 +2025,16 @@ function toZoneWithoutBoundaryChanges(xc) {
|
|
|
2075
2025
|
*/
|
|
2076
2026
|
function toUnboundedZone(xc) {
|
|
2077
2027
|
const zone = toZoneWithoutBoundaryChanges(xc);
|
|
2078
|
-
|
|
2028
|
+
const orderedZone = reorderZone(zone);
|
|
2029
|
+
const bottom = orderedZone.bottom;
|
|
2030
|
+
const right = orderedZone.right;
|
|
2031
|
+
if ((bottom !== undefined && bottom > MAX_ROW) || (right !== undefined && right > MAX_COL)) {
|
|
2032
|
+
throw new Error(`Range string out of bounds: ${xc}`); // limit the size of the zone for performance
|
|
2033
|
+
}
|
|
2034
|
+
if (bottom === undefined && right === undefined) {
|
|
2035
|
+
throw new Error("Wrong zone xc. The zone cannot be at the same time a full column and a full row");
|
|
2036
|
+
}
|
|
2037
|
+
return orderedZone;
|
|
2079
2038
|
}
|
|
2080
2039
|
/**
|
|
2081
2040
|
* Convert from a cartesian reference to a Zone.
|
|
@@ -4012,6 +3971,113 @@ function transposeMatrix(matrix) {
|
|
|
4012
3971
|
}
|
|
4013
3972
|
return generateMatrix(matrix[0].length, matrix.length, (i, j) => matrix[j][i]);
|
|
4014
3973
|
}
|
|
3974
|
+
/**
|
|
3975
|
+
* Enables a formula function to accept matrix or vector inputs instead of simple value, computing results across multiple dimensions.
|
|
3976
|
+
*
|
|
3977
|
+
* ```
|
|
3978
|
+
* / |‾ ‾| \ |‾ ‾|
|
|
3979
|
+
* | | [A] | | | compute(A, D, E), compute(A, D, F), compute(A, D, G) |
|
|
3980
|
+
* applyVectorization| compute, | [B], D, [E, F, G] | | <=> | compute(B, D, E), compute(B, D, F), compute(B, D, G) |
|
|
3981
|
+
* | | [C] | | | compute(C, D, E), compute(C, D, F), compute(C, D, G) |
|
|
3982
|
+
* \ |_ _| / |_ _|
|
|
3983
|
+
* ```
|
|
3984
|
+
*
|
|
3985
|
+
* By default, all arguments are vectorized. To control which arguments are vectorized,
|
|
3986
|
+
* pass an `acceptToVectorize` boolean array of the same length as `args`:
|
|
3987
|
+
* - `true` enables vectorization for that argument
|
|
3988
|
+
* - `false` disables vectorization for that argument
|
|
3989
|
+
*
|
|
3990
|
+
* For example, with `[true, true, false]` on previous example you get:
|
|
3991
|
+
*
|
|
3992
|
+
* ```
|
|
3993
|
+
* |‾ ‾|
|
|
3994
|
+
* | compute(A, D, [E, F, G]) |
|
|
3995
|
+
* | compute(B, D, [E, F, G]) |
|
|
3996
|
+
* | compute(C, D, [E, F, G]) |
|
|
3997
|
+
* |_ _|
|
|
3998
|
+
* ```
|
|
3999
|
+
*
|
|
4000
|
+
* @remarks
|
|
4001
|
+
* This helper is automatically applied (by default) to **all** `compute` functions
|
|
4002
|
+
* across the various spreadsheet formula modules:
|
|
4003
|
+
* - If an argument is declared **scalar** (not `"range"`), it is vectorized.
|
|
4004
|
+
* - If **all** arguments are declared **ranges**, no vectorization occurs.
|
|
4005
|
+
* - e.g. `SUM(A1:B2)` returns a 1×1 sum over the range.
|
|
4006
|
+
* - e.g. `COS(A1:B2)` over `A1:B2` returns a 2×2 element-wise result.
|
|
4007
|
+
* - For special behaviors (e.g. the `IF` function), you may declare all arguments
|
|
4008
|
+
* as ranges and invoke this helper directly within your `compute` implementation.
|
|
4009
|
+
*/
|
|
4010
|
+
function applyVectorization(formula, args, acceptToVectorize = undefined) {
|
|
4011
|
+
let countVectorizedCol = 1;
|
|
4012
|
+
let countVectorizedRow = 1;
|
|
4013
|
+
let vectorizedColLimit = Infinity;
|
|
4014
|
+
let vectorizedRowLimit = Infinity;
|
|
4015
|
+
let vectorArgsType = undefined;
|
|
4016
|
+
for (let i = 0; i < args.length; i++) {
|
|
4017
|
+
const arg = args[i];
|
|
4018
|
+
if (isMatrix(arg) && (acceptToVectorize === undefined || acceptToVectorize[i])) {
|
|
4019
|
+
const nColumns = arg.length;
|
|
4020
|
+
const nRows = arg[0].length;
|
|
4021
|
+
if (nColumns !== 1 || nRows !== 1) {
|
|
4022
|
+
vectorArgsType ??= new Array(args.length);
|
|
4023
|
+
if (nColumns !== 1 && nRows !== 1) {
|
|
4024
|
+
vectorArgsType[i] = "matrix";
|
|
4025
|
+
countVectorizedCol = Math.max(countVectorizedCol, nColumns);
|
|
4026
|
+
countVectorizedRow = Math.max(countVectorizedRow, nRows);
|
|
4027
|
+
vectorizedColLimit = Math.min(vectorizedColLimit, nColumns);
|
|
4028
|
+
vectorizedRowLimit = Math.min(vectorizedRowLimit, nRows);
|
|
4029
|
+
}
|
|
4030
|
+
else if (nColumns !== 1) {
|
|
4031
|
+
vectorArgsType[i] = "horizontal";
|
|
4032
|
+
countVectorizedCol = Math.max(countVectorizedCol, nColumns);
|
|
4033
|
+
vectorizedColLimit = Math.min(vectorizedColLimit, nColumns);
|
|
4034
|
+
}
|
|
4035
|
+
else if (nRows !== 1) {
|
|
4036
|
+
vectorArgsType[i] = "vertical";
|
|
4037
|
+
countVectorizedRow = Math.max(countVectorizedRow, nRows);
|
|
4038
|
+
vectorizedRowLimit = Math.min(vectorizedRowLimit, nRows);
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
4041
|
+
else {
|
|
4042
|
+
args[i] = arg[0][0];
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
if (countVectorizedCol === 1 && countVectorizedRow === 1) {
|
|
4047
|
+
// either this function is not vectorized or it ends up with a 1x1 dimension
|
|
4048
|
+
return formula(...args);
|
|
4049
|
+
}
|
|
4050
|
+
const getArgOffset = (i, j) => args.map((arg, index) => {
|
|
4051
|
+
switch (vectorArgsType?.[index]) {
|
|
4052
|
+
case "matrix":
|
|
4053
|
+
return arg[i][j];
|
|
4054
|
+
case "horizontal":
|
|
4055
|
+
return arg[i][0];
|
|
4056
|
+
case "vertical":
|
|
4057
|
+
return arg[0][j];
|
|
4058
|
+
case undefined:
|
|
4059
|
+
return arg;
|
|
4060
|
+
}
|
|
4061
|
+
});
|
|
4062
|
+
return generateMatrix(countVectorizedCol, countVectorizedRow, (col, row) => {
|
|
4063
|
+
if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) {
|
|
4064
|
+
return new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
|
|
4065
|
+
}
|
|
4066
|
+
const singleCellComputeResult = formula(...getArgOffset(col, row));
|
|
4067
|
+
// In the case where the user tries to vectorize arguments of an array formula, we will get an
|
|
4068
|
+
// array for every combination of the vectorized arguments, which will lead to a 3D matrix and
|
|
4069
|
+
// we won't be able to return the values.
|
|
4070
|
+
// In this case, we keep the first element of each spreading part, just as Excel does, and
|
|
4071
|
+
// create an array with these parts.
|
|
4072
|
+
// For exemple, we have MUNIT(x) that return an unitary matrix of x*x. If we use it with a
|
|
4073
|
+
// range, like MUNIT(A1:A2), we will get two unitary matrices (one for the value in A1 and one
|
|
4074
|
+
// for the value in A2). In this case, we will simply take the first value of each matrix and
|
|
4075
|
+
// return the array [First value of MUNIT(A1), First value of MUNIT(A2)].
|
|
4076
|
+
return isMatrix(singleCellComputeResult)
|
|
4077
|
+
? singleCellComputeResult[0][0]
|
|
4078
|
+
: singleCellComputeResult;
|
|
4079
|
+
});
|
|
4080
|
+
}
|
|
4015
4081
|
// -----------------------------------------------------------------------------
|
|
4016
4082
|
// CONDITIONAL EXPLORE FUNCTIONS
|
|
4017
4083
|
// -----------------------------------------------------------------------------
|
|
@@ -5796,6 +5862,67 @@ function scrollDelay(value) {
|
|
|
5796
5862
|
return MIN_DELAY + (MAX_DELAY - MIN_DELAY) * Math.exp(-ACCELERATION * (value - 1));
|
|
5797
5863
|
}
|
|
5798
5864
|
|
|
5865
|
+
/** Reference of a cell (eg. A1, $B$5) */
|
|
5866
|
+
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
5867
|
+
// Same as above, but matches the exact string (nothing before or after)
|
|
5868
|
+
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
5869
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
5870
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
5871
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
5872
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
5873
|
+
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
5874
|
+
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
5875
|
+
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
5876
|
+
const rowReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([0-9]{1,7})$/, "i");
|
|
5877
|
+
/** Reference of a normal range or a full row range (eg. A1:B1, 1:$5, $A2:5) */
|
|
5878
|
+
const fullRowXc = /(\$?[A-Z]{1,3})?\$?[0-9]{1,7}\s*:\s*(\$?[A-Z]{1,3})?\$?[0-9]{1,7}\s*/i;
|
|
5879
|
+
/** Reference of a normal range or a column row range (eg. A1:B1, A:$B, $A1:C) */
|
|
5880
|
+
const fullColXc = /\$?[A-Z]{1,3}(\$?[0-9]{1,7})?\s*:\s*\$?[A-Z]{1,3}(\$?[0-9]{1,7})?\s*/i;
|
|
5881
|
+
/** Reference of a cell or a range, it can be a bounded range, a full row or a full column */
|
|
5882
|
+
const rangeReference = new RegExp(/^\s*('.+'!|[^']+!)?/.source +
|
|
5883
|
+
"(" +
|
|
5884
|
+
[cellReference.source, fullRowXc.source, fullColXc.source].join("|") +
|
|
5885
|
+
")" +
|
|
5886
|
+
/$/.source, "i");
|
|
5887
|
+
/**
|
|
5888
|
+
* Return true if the given xc is the reference of a column (e.g. A or AC or Sheet1!A)
|
|
5889
|
+
*/
|
|
5890
|
+
function isColReference(xc) {
|
|
5891
|
+
return colReference.test(xc);
|
|
5892
|
+
}
|
|
5893
|
+
/**
|
|
5894
|
+
* Return true if the given xc is the reference of a column (e.g. 1 or Sheet1!1)
|
|
5895
|
+
*/
|
|
5896
|
+
function isRowReference(xc) {
|
|
5897
|
+
return rowReference.test(xc);
|
|
5898
|
+
}
|
|
5899
|
+
function isColHeader(str) {
|
|
5900
|
+
return colHeader.test(str);
|
|
5901
|
+
}
|
|
5902
|
+
function isRowHeader(str) {
|
|
5903
|
+
return rowHeader.test(str);
|
|
5904
|
+
}
|
|
5905
|
+
/**
|
|
5906
|
+
* Return true if the given xc is the reference of a single cell,
|
|
5907
|
+
* without any specified sheet (e.g. A1)
|
|
5908
|
+
*/
|
|
5909
|
+
function isSingleCellReference(xc) {
|
|
5910
|
+
return singleCellReference.test(xc);
|
|
5911
|
+
}
|
|
5912
|
+
function splitReference(ref) {
|
|
5913
|
+
if (!ref.includes("!")) {
|
|
5914
|
+
return { xc: ref };
|
|
5915
|
+
}
|
|
5916
|
+
const parts = ref.split("!");
|
|
5917
|
+
const xc = parts.pop();
|
|
5918
|
+
const sheetName = getUnquotedSheetName(parts.join("!")) || undefined;
|
|
5919
|
+
return { sheetName, xc };
|
|
5920
|
+
}
|
|
5921
|
+
/** Return a reference SheetName!xc from the given arguments */
|
|
5922
|
+
function getFullReference(sheetName, xc) {
|
|
5923
|
+
return sheetName !== undefined ? `${getCanonicalSymbolName(sheetName)}!${xc}` : xc;
|
|
5924
|
+
}
|
|
5925
|
+
|
|
5799
5926
|
class RangeImpl {
|
|
5800
5927
|
getSheetSize;
|
|
5801
5928
|
_zone;
|
|
@@ -7257,14 +7384,20 @@ function multiplyMatrices(matrix1, matrix2) {
|
|
|
7257
7384
|
/**
|
|
7258
7385
|
* Return the input if it's a scalar or the first element of the input if it's a matrix.
|
|
7259
7386
|
*/
|
|
7260
|
-
function toScalar(
|
|
7261
|
-
if (!isMatrix(
|
|
7262
|
-
return
|
|
7387
|
+
function toScalar(arg) {
|
|
7388
|
+
if (!isMatrix(arg)) {
|
|
7389
|
+
return arg;
|
|
7263
7390
|
}
|
|
7264
|
-
if (
|
|
7391
|
+
if (!isSingleElementMatrix(arg)) {
|
|
7265
7392
|
throw new EvaluationError(_t("The value should be a scalar or a 1x1 matrix"));
|
|
7266
7393
|
}
|
|
7267
|
-
return
|
|
7394
|
+
return arg[0][0];
|
|
7395
|
+
}
|
|
7396
|
+
function isSingleElementMatrix(matrix) {
|
|
7397
|
+
return matrix.length === 1 && matrix[0].length === 1;
|
|
7398
|
+
}
|
|
7399
|
+
function isMultipleElementMatrix(arg) {
|
|
7400
|
+
return isMatrix(arg) && !isSingleElementMatrix(arg);
|
|
7268
7401
|
}
|
|
7269
7402
|
|
|
7270
7403
|
function assertSameNumberOfElements(...args) {
|
|
@@ -21465,7 +21598,7 @@ const FILTER = {
|
|
|
21465
21598
|
}
|
|
21466
21599
|
return mode === "row" ? transposeMatrix(result) : result;
|
|
21467
21600
|
},
|
|
21468
|
-
isExported:
|
|
21601
|
+
isExported: false,
|
|
21469
21602
|
};
|
|
21470
21603
|
// -----------------------------------------------------------------------------
|
|
21471
21604
|
// SORT
|
|
@@ -24433,16 +24566,23 @@ const FALSE = {
|
|
|
24433
24566
|
const IF = {
|
|
24434
24567
|
description: _t("Returns value depending on logical expression."),
|
|
24435
24568
|
args: [
|
|
24436
|
-
arg("logical_expression (boolean)", _t("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE.")),
|
|
24437
|
-
arg("value_if_true (any)", _t("The value the function returns if logical_expression is TRUE.")),
|
|
24438
|
-
arg("value_if_false (any, default=FALSE)", _t("The value the function returns if logical_expression is FALSE.")),
|
|
24569
|
+
arg("logical_expression (boolean, range<boolean>)", _t("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE.")),
|
|
24570
|
+
arg("value_if_true (any, range)", _t("The value the function returns if logical_expression is TRUE.")),
|
|
24571
|
+
arg("value_if_false (any, range, default=FALSE)", _t("The value the function returns if logical_expression is FALSE.")),
|
|
24439
24572
|
],
|
|
24440
24573
|
compute: function (logicalExpression, valueIfTrue, valueIfFalse) {
|
|
24441
|
-
|
|
24574
|
+
if (isMultipleElementMatrix(logicalExpression)) {
|
|
24575
|
+
return applyVectorization(IF.compute, [logicalExpression, valueIfTrue, valueIfFalse]);
|
|
24576
|
+
}
|
|
24577
|
+
let result = toBoolean(toScalar(logicalExpression)) ? valueIfTrue : valueIfFalse;
|
|
24578
|
+
// useful for interpreting empty cell references as empty strings. But must be removed to make empty cell references equal to zero
|
|
24579
|
+
if (!isMultipleElementMatrix(result)) {
|
|
24580
|
+
result = toScalar(result);
|
|
24581
|
+
}
|
|
24442
24582
|
if (result === undefined) {
|
|
24443
24583
|
return { value: "" };
|
|
24444
24584
|
}
|
|
24445
|
-
if (result.value === null) {
|
|
24585
|
+
if (!isMatrix(result) && result.value === null) {
|
|
24446
24586
|
return { ...result, value: "" };
|
|
24447
24587
|
}
|
|
24448
24588
|
return result;
|
|
@@ -24455,15 +24595,22 @@ const IF = {
|
|
|
24455
24595
|
const IFERROR = {
|
|
24456
24596
|
description: _t("Value if it is not an error, otherwise 2nd argument."),
|
|
24457
24597
|
args: [
|
|
24458
|
-
arg("value (any)", _t("The value to return if value itself is not an error.")),
|
|
24459
|
-
arg(`value_if_error (any, default="empty")`, _t("The value the function returns if value is an error.")),
|
|
24598
|
+
arg("value (any, range)", _t("The value to return if value itself is not an error.")),
|
|
24599
|
+
arg(`value_if_error (any, range, default="empty")`, _t("The value the function returns if value is an error.")),
|
|
24460
24600
|
],
|
|
24461
|
-
compute: function (value, valueIfError
|
|
24462
|
-
|
|
24601
|
+
compute: function (value, valueIfError) {
|
|
24602
|
+
if (isMultipleElementMatrix(value)) {
|
|
24603
|
+
return applyVectorization(IFERROR.compute, [value, valueIfError]);
|
|
24604
|
+
}
|
|
24605
|
+
let result = isEvaluationError(toScalar(value)?.value) ? valueIfError : value;
|
|
24606
|
+
// useful for interpreting empty cell references as empty strings. But must be removed to make empty cell references equal to zero
|
|
24607
|
+
if (!isMultipleElementMatrix(result)) {
|
|
24608
|
+
result = toScalar(result);
|
|
24609
|
+
}
|
|
24463
24610
|
if (result === undefined) {
|
|
24464
24611
|
return { value: "" };
|
|
24465
24612
|
}
|
|
24466
|
-
if (result.value === null) {
|
|
24613
|
+
if (!isMatrix(result) && result.value === null) {
|
|
24467
24614
|
return { ...result, value: "" };
|
|
24468
24615
|
}
|
|
24469
24616
|
return result;
|
|
@@ -24476,15 +24623,22 @@ const IFERROR = {
|
|
|
24476
24623
|
const IFNA = {
|
|
24477
24624
|
description: _t("Value if it is not an #N/A error, otherwise 2nd argument."),
|
|
24478
24625
|
args: [
|
|
24479
|
-
arg("value (any)", _t("The value to return if value itself is not #N/A an error.")),
|
|
24480
|
-
arg(`value_if_error (any, default="empty")`, _t("The value the function returns if value is an #N/A error.")),
|
|
24626
|
+
arg("value (any, range)", _t("The value to return if value itself is not #N/A an error.")),
|
|
24627
|
+
arg(`value_if_error (any, range, default="empty")`, _t("The value the function returns if value is an #N/A error.")),
|
|
24481
24628
|
],
|
|
24482
|
-
compute: function (value, valueIfError
|
|
24483
|
-
|
|
24629
|
+
compute: function (value, valueIfError) {
|
|
24630
|
+
if (isMultipleElementMatrix(value)) {
|
|
24631
|
+
return applyVectorization(IFNA.compute, [value, valueIfError]);
|
|
24632
|
+
}
|
|
24633
|
+
let result = toScalar(value)?.value === CellErrorType.NotAvailable ? valueIfError : value;
|
|
24634
|
+
// useful for interpreting empty cell references as empty strings. But must be removed to make empty cell references equal to zero
|
|
24635
|
+
if (!isMultipleElementMatrix(result)) {
|
|
24636
|
+
result = toScalar(result);
|
|
24637
|
+
}
|
|
24484
24638
|
if (result === undefined) {
|
|
24485
24639
|
return { value: "" };
|
|
24486
24640
|
}
|
|
24487
|
-
if (result.value === null) {
|
|
24641
|
+
if (!isMatrix(result) && result.value === null) {
|
|
24488
24642
|
return { ...result, value: "" };
|
|
24489
24643
|
}
|
|
24490
24644
|
return result;
|
|
@@ -24497,23 +24651,31 @@ const IFNA = {
|
|
|
24497
24651
|
const IFS = {
|
|
24498
24652
|
description: _t("Returns a value depending on multiple logical expressions."),
|
|
24499
24653
|
args: [
|
|
24500
|
-
arg("condition1 (boolean)", _t("The first condition to be evaluated. This can be a boolean, a number, an array, or a reference to any of those.")),
|
|
24501
|
-
arg("value1 (any)", _t("The returned value if condition1 is TRUE.")),
|
|
24502
|
-
arg("condition2 (boolean, any, repeating)", _t("Additional conditions to be evaluated if the previous ones are FALSE.")),
|
|
24503
|
-
arg("value2 (any, repeating)", _t("Additional values to be returned if their corresponding conditions are TRUE.")),
|
|
24654
|
+
arg("condition1 (boolean, range<boolean>)", _t("The first condition to be evaluated. This can be a boolean, a number, an array, or a reference to any of those.")),
|
|
24655
|
+
arg("value1 (any, range)", _t("The returned value if condition1 is TRUE.")),
|
|
24656
|
+
arg("condition2 (boolean, any, range, repeating)", _t("Additional conditions to be evaluated if the previous ones are FALSE.")),
|
|
24657
|
+
arg("value2 (any, range, repeating)", _t("Additional values to be returned if their corresponding conditions are TRUE.")),
|
|
24504
24658
|
],
|
|
24505
24659
|
compute: function (...values) {
|
|
24506
24660
|
assert(() => values.length % 2 === 0, _t("Wrong number of arguments. Expected an even number of arguments."));
|
|
24507
|
-
|
|
24508
|
-
if (
|
|
24509
|
-
|
|
24510
|
-
|
|
24661
|
+
while (values.length > 0) {
|
|
24662
|
+
if (isMultipleElementMatrix(values[0])) {
|
|
24663
|
+
return applyVectorization(IFS.compute, values);
|
|
24664
|
+
}
|
|
24665
|
+
const condition = toBoolean(toScalar(values.shift()));
|
|
24666
|
+
let valueIfTrue = values.shift();
|
|
24667
|
+
if (condition) {
|
|
24668
|
+
// useful for interpreting empty cell references as empty strings. But must be removed to make empty cell references equal to zero
|
|
24669
|
+
if (!isMultipleElementMatrix(valueIfTrue)) {
|
|
24670
|
+
valueIfTrue = toScalar(valueIfTrue);
|
|
24671
|
+
}
|
|
24672
|
+
if (valueIfTrue === undefined) {
|
|
24511
24673
|
return { value: "" };
|
|
24512
24674
|
}
|
|
24513
|
-
if (
|
|
24514
|
-
return { ...
|
|
24675
|
+
if (!isMatrix(valueIfTrue) && valueIfTrue.value === null) {
|
|
24676
|
+
return { ...valueIfTrue, value: "" };
|
|
24515
24677
|
}
|
|
24516
|
-
return
|
|
24678
|
+
return valueIfTrue;
|
|
24517
24679
|
}
|
|
24518
24680
|
}
|
|
24519
24681
|
return new EvaluationError(_t("No match."));
|
|
@@ -26157,7 +26319,7 @@ const SPLIT = {
|
|
|
26157
26319
|
}
|
|
26158
26320
|
return transposeMatrix([result]);
|
|
26159
26321
|
},
|
|
26160
|
-
isExported:
|
|
26322
|
+
isExported: false,
|
|
26161
26323
|
};
|
|
26162
26324
|
// -----------------------------------------------------------------------------
|
|
26163
26325
|
// SUBSTITUTE
|
|
@@ -26350,86 +26512,21 @@ for (let category of categories) {
|
|
|
26350
26512
|
functionRegistry.add(name, { isExported: false, ...addDescr });
|
|
26351
26513
|
}
|
|
26352
26514
|
}
|
|
26353
|
-
|
|
26515
|
+
//------------------------------------------------------------------------------
|
|
26516
|
+
// CREATE COMPUTE FUNCTION
|
|
26517
|
+
//------------------------------------------------------------------------------
|
|
26354
26518
|
function createComputeFunction(descr, functionName) {
|
|
26355
26519
|
function vectorizedCompute(...args) {
|
|
26356
|
-
|
|
26357
|
-
let countVectorizableRow = 1;
|
|
26358
|
-
let vectorizableColLimit = Infinity;
|
|
26359
|
-
let vectorizableRowLimit = Infinity;
|
|
26360
|
-
let vectorArgsType = undefined;
|
|
26361
|
-
//#region Compute vectorisation limits
|
|
26520
|
+
const acceptToVectorize = [];
|
|
26362
26521
|
for (let i = 0; i < args.length; i++) {
|
|
26363
26522
|
const argDefinition = descr.args[descr.getArgToFocus(i + 1) - 1];
|
|
26364
26523
|
const arg = args[i];
|
|
26365
|
-
if (isMatrix(arg) && !argDefinition.acceptMatrix) {
|
|
26366
|
-
// if argDefinition does not accept a matrix but arg is still a matrix
|
|
26367
|
-
// --> triggers the arguments vectorization
|
|
26368
|
-
const nColumns = arg.length;
|
|
26369
|
-
const nRows = arg[0].length;
|
|
26370
|
-
if (nColumns !== 1 || nRows !== 1) {
|
|
26371
|
-
vectorArgsType ??= new Array(args.length);
|
|
26372
|
-
if (nColumns !== 1 && nRows !== 1) {
|
|
26373
|
-
vectorArgsType[i] = "matrix";
|
|
26374
|
-
countVectorizableCol = Math.max(countVectorizableCol, nColumns);
|
|
26375
|
-
countVectorizableRow = Math.max(countVectorizableRow, nRows);
|
|
26376
|
-
vectorizableColLimit = Math.min(vectorizableColLimit, nColumns);
|
|
26377
|
-
vectorizableRowLimit = Math.min(vectorizableRowLimit, nRows);
|
|
26378
|
-
}
|
|
26379
|
-
else if (nColumns !== 1) {
|
|
26380
|
-
vectorArgsType[i] = "horizontal";
|
|
26381
|
-
countVectorizableCol = Math.max(countVectorizableCol, nColumns);
|
|
26382
|
-
vectorizableColLimit = Math.min(vectorizableColLimit, nColumns);
|
|
26383
|
-
}
|
|
26384
|
-
else if (nRows !== 1) {
|
|
26385
|
-
vectorArgsType[i] = "vertical";
|
|
26386
|
-
countVectorizableRow = Math.max(countVectorizableRow, nRows);
|
|
26387
|
-
vectorizableRowLimit = Math.min(vectorizableRowLimit, nRows);
|
|
26388
|
-
}
|
|
26389
|
-
}
|
|
26390
|
-
else {
|
|
26391
|
-
args[i] = arg[0][0];
|
|
26392
|
-
}
|
|
26393
|
-
}
|
|
26394
26524
|
if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
|
|
26395
26525
|
throw new BadExpressionError(_t("Function %s expects the parameter '%s' to be reference to a cell or range.", functionName, (i + 1).toString()));
|
|
26396
26526
|
}
|
|
26527
|
+
acceptToVectorize.push(!argDefinition.acceptMatrix);
|
|
26397
26528
|
}
|
|
26398
|
-
|
|
26399
|
-
if (countVectorizableCol === 1 && countVectorizableRow === 1) {
|
|
26400
|
-
// either this function is not vectorized or it ends up with a 1x1 dimension
|
|
26401
|
-
return errorHandlingCompute.apply(this, args);
|
|
26402
|
-
}
|
|
26403
|
-
const getArgOffset = (i, j) => args.map((arg, index) => {
|
|
26404
|
-
switch (vectorArgsType?.[index]) {
|
|
26405
|
-
case "matrix":
|
|
26406
|
-
return arg[i][j];
|
|
26407
|
-
case "horizontal":
|
|
26408
|
-
return arg[i][0];
|
|
26409
|
-
case "vertical":
|
|
26410
|
-
return arg[0][j];
|
|
26411
|
-
case undefined:
|
|
26412
|
-
return arg;
|
|
26413
|
-
}
|
|
26414
|
-
});
|
|
26415
|
-
return generateMatrix(countVectorizableCol, countVectorizableRow, (col, row) => {
|
|
26416
|
-
if (col > vectorizableColLimit - 1 || row > vectorizableRowLimit - 1) {
|
|
26417
|
-
return notAvailableError;
|
|
26418
|
-
}
|
|
26419
|
-
const singleCellComputeResult = errorHandlingCompute.apply(this, getArgOffset(col, row));
|
|
26420
|
-
// In the case where the user tries to vectorize arguments of an array formula, we will get an
|
|
26421
|
-
// array for every combination of the vectorized arguments, which will lead to a 3D matrix and
|
|
26422
|
-
// we won't be able to return the values.
|
|
26423
|
-
// In this case, we keep the first element of each spreading part, just as Excel does, and
|
|
26424
|
-
// create an array with these parts.
|
|
26425
|
-
// For exemple, we have MUNIT(x) that return an unitary matrix of x*x. If we use it with a
|
|
26426
|
-
// range, like MUNIT(A1:A2), we will get two unitary matrices (one for the value in A1 and one
|
|
26427
|
-
// for the value in A2). In this case, we will simply take the first value of each matrix and
|
|
26428
|
-
// return the array [First value of MUNIT(A1), First value of MUNIT(A2)].
|
|
26429
|
-
return isMatrix(singleCellComputeResult)
|
|
26430
|
-
? singleCellComputeResult[0][0]
|
|
26431
|
-
: singleCellComputeResult;
|
|
26432
|
-
});
|
|
26529
|
+
return applyVectorization(errorHandlingCompute.bind(this), args, acceptToVectorize);
|
|
26433
26530
|
}
|
|
26434
26531
|
function errorHandlingCompute(...args) {
|
|
26435
26532
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -39418,7 +39515,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
39418
39515
|
proposals &&
|
|
39419
39516
|
!["ARG_SEPARATOR", "LEFT_PAREN", "OPERATOR"].includes(tokenAtCursor.type)) {
|
|
39420
39517
|
const filteredProposals = fuzzyLookup(searchTerm, proposals, (p) => p.fuzzySearchKey || p.text);
|
|
39421
|
-
if (!exactMatch || filteredProposals.length
|
|
39518
|
+
if (!exactMatch || filteredProposals.length) {
|
|
39422
39519
|
proposals = filteredProposals;
|
|
39423
39520
|
}
|
|
39424
39521
|
}
|
|
@@ -39493,12 +39590,13 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
39493
39590
|
return providersDefinitions;
|
|
39494
39591
|
}
|
|
39495
39592
|
getComposerContent() {
|
|
39593
|
+
let content = this._currentContent;
|
|
39496
39594
|
if (this.editionMode === "inactive") {
|
|
39497
39595
|
// References in the content might not be linked to the current active sheet
|
|
39498
39596
|
// We here force the sheet name prefix for all references that are not in
|
|
39499
39597
|
// the current active sheet
|
|
39500
39598
|
const defaultRangeSheetId = this.args().defaultRangeSheetId;
|
|
39501
|
-
|
|
39599
|
+
content = rangeTokenize(this.args().content)
|
|
39502
39600
|
.map((token) => {
|
|
39503
39601
|
if (token.type === "REFERENCE") {
|
|
39504
39602
|
const range = this.getters.getRangeFromSheetXC(defaultRangeSheetId, token.value);
|
|
@@ -39508,7 +39606,7 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
39508
39606
|
})
|
|
39509
39607
|
.join("");
|
|
39510
39608
|
}
|
|
39511
|
-
return this.
|
|
39609
|
+
return localizeContent(content, this.getters.getLocale());
|
|
39512
39610
|
}
|
|
39513
39611
|
stopEdition() {
|
|
39514
39612
|
this._stopEdition();
|
|
@@ -43111,6 +43209,9 @@ class PivotMeasureEditor extends Component {
|
|
|
43111
43209
|
measure: this.props.measure,
|
|
43112
43210
|
});
|
|
43113
43211
|
}
|
|
43212
|
+
get isCalculatedMeasureInvalid() {
|
|
43213
|
+
return this.env.model.getters.getMeasureCompiledFormula(this.props.measure).isBadExpression;
|
|
43214
|
+
}
|
|
43114
43215
|
}
|
|
43115
43216
|
|
|
43116
43217
|
css /* scss */ `
|
|
@@ -44023,7 +44124,9 @@ function compareDimensionValues(dimension, a, b) {
|
|
|
44023
44124
|
return dimension.order === "asc" ? -1 : 1;
|
|
44024
44125
|
}
|
|
44025
44126
|
if (dimension.type === "integer" || dimension.type === "datetime") {
|
|
44026
|
-
return dimension.order === "asc"
|
|
44127
|
+
return dimension.order === "asc"
|
|
44128
|
+
? toNumber(a, DEFAULT_LOCALE) - toNumber(b, DEFAULT_LOCALE)
|
|
44129
|
+
: toNumber(b, DEFAULT_LOCALE) - toNumber(a, DEFAULT_LOCALE);
|
|
44027
44130
|
}
|
|
44028
44131
|
return dimension.order === "asc" ? a.localeCompare(b) : b.localeCompare(a);
|
|
44029
44132
|
}
|
|
@@ -46764,8 +46867,7 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
46764
46867
|
if (!spreader) {
|
|
46765
46868
|
return undefined;
|
|
46766
46869
|
}
|
|
46767
|
-
|
|
46768
|
-
return cell?.content;
|
|
46870
|
+
return this.getters.getCellText(spreader, { showFormula: true });
|
|
46769
46871
|
}
|
|
46770
46872
|
get currentEditedCell() {
|
|
46771
46873
|
return {
|
|
@@ -49568,6 +49670,7 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
49568
49670
|
const friction = 0.95;
|
|
49569
49671
|
const verticalScrollFactor = 1;
|
|
49570
49672
|
const horizontalScrollFactor = 1;
|
|
49673
|
+
const resetTimeoutDuration = 100;
|
|
49571
49674
|
function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
49572
49675
|
let lastX = 0;
|
|
49573
49676
|
let lastY = 0;
|
|
@@ -49575,6 +49678,7 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
|
49575
49678
|
let velocityY = 0;
|
|
49576
49679
|
let isMouseDown = false;
|
|
49577
49680
|
let lastTime = 0;
|
|
49681
|
+
let resetTimeout = null;
|
|
49578
49682
|
useRefListener(ref, "touchstart", onTouchStart, { capture: false });
|
|
49579
49683
|
useRefListener(ref, "touchmove", onTouchMove, { capture: false });
|
|
49580
49684
|
useRefListener(ref, "touchend", onTouchEnd, { capture: false });
|
|
@@ -49587,6 +49691,10 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
|
49587
49691
|
function onTouchMove(event) {
|
|
49588
49692
|
if (!isMouseDown)
|
|
49589
49693
|
return;
|
|
49694
|
+
if (resetTimeout) {
|
|
49695
|
+
clearTimeout(resetTimeout);
|
|
49696
|
+
resetTimeout = null;
|
|
49697
|
+
}
|
|
49590
49698
|
const currentTime = Date.now();
|
|
49591
49699
|
const { clientX, clientY } = event.touches[0];
|
|
49592
49700
|
let deltaX = lastX - clientX;
|
|
@@ -49603,6 +49711,10 @@ function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
|
49603
49711
|
}
|
|
49604
49712
|
event.stopPropagation();
|
|
49605
49713
|
}
|
|
49714
|
+
resetTimeout = setTimeout(() => {
|
|
49715
|
+
velocityX = 0;
|
|
49716
|
+
velocityY = 0;
|
|
49717
|
+
}, resetTimeoutDuration);
|
|
49606
49718
|
updateScroll(deltaX * horizontalScrollFactor, deltaY * verticalScrollFactor);
|
|
49607
49719
|
}
|
|
49608
49720
|
function onTouchEnd(ev) {
|
|
@@ -58445,10 +58557,9 @@ class Evaluator {
|
|
|
58445
58557
|
return this.evaluatedCells.keysForSheet(sheetId);
|
|
58446
58558
|
}
|
|
58447
58559
|
getArrayFormulaSpreadingOn(position) {
|
|
58448
|
-
const
|
|
58449
|
-
|
|
58450
|
-
|
|
58451
|
-
return this.spreadingRelations.isArrayFormula(position) ? position : undefined;
|
|
58560
|
+
const isEmpty = this.getEvaluatedCell(position).type === CellValueType.empty;
|
|
58561
|
+
if (isEmpty) {
|
|
58562
|
+
return undefined;
|
|
58452
58563
|
}
|
|
58453
58564
|
const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
|
|
58454
58565
|
return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
|
|
@@ -74248,6 +74359,6 @@ const constants = {
|
|
|
74248
74359
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
74249
74360
|
|
|
74250
74361
|
|
|
74251
|
-
__info__.version = "18.0.
|
|
74252
|
-
__info__.date = "2025-05-
|
|
74253
|
-
__info__.hash = "
|
|
74362
|
+
__info__.version = "18.0.30";
|
|
74363
|
+
__info__.date = "2025-05-26T12:35:05.184Z";
|
|
74364
|
+
__info__.hash = "838c4f7";
|