|
|
@@ -996,38 +996,45 @@ class CellExpression {
|
|
996
|
996
|
* @type {CellExpressionOperation}
|
|
997
|
997
|
*/
|
|
998
|
998
|
op;
|
|
|
999
|
+
|
|
999
|
1000
|
/**
|
|
1000
|
1001
|
* Mixed array of `CellValue`, `CellAddress`, `CellAddressRange`,
|
|
1001
|
1002
|
* `CellExpression`, perhaps more.
|
|
1002
|
1003
|
* @type {Array}
|
|
1003
|
1004
|
*/
|
|
1004
|
1005
|
arguments;
|
|
|
1006
|
+
|
|
1005
|
1007
|
/**
|
|
1006
|
1008
|
* For `Function`, the function name.
|
|
1007
|
1009
|
* @type {string|null}
|
|
1008
|
1010
|
*/
|
|
1009
|
1011
|
qualifier;
|
|
|
1012
|
+
|
|
1010
|
1013
|
/**
|
|
1011
|
1014
|
* Optional format override. One of `number`, `currency`, `percent`.
|
|
1012
|
1015
|
* @type {string|null}
|
|
1013
|
1016
|
*/
|
|
1014
|
1017
|
outputType = null;
|
|
|
1018
|
+
|
|
1015
|
1019
|
/**
|
|
1016
|
1020
|
* Optional decimal place formatting override.
|
|
1017
|
1021
|
* @type {number|null}
|
|
1018
|
1022
|
*/
|
|
1019
|
1023
|
outputDecimals = null;
|
|
|
1024
|
+
|
|
1020
|
1025
|
/**
|
|
1021
|
1026
|
* Address ranges to copy this expression into for any blank cells. Used
|
|
1022
|
1027
|
* by formulas with the `FILL` modifier.
|
|
1023
|
1028
|
* @type {CellAddressRange[]|null} fillRanges
|
|
1024
|
1029
|
*/
|
|
1025
|
1030
|
fillRanges = null;
|
|
|
1031
|
+
|
|
1026
|
1032
|
/**
|
|
1027
|
1033
|
* Source address of the formula.
|
|
1028
|
1034
|
* @type {CellAddress|null}
|
|
1029
|
1035
|
*/
|
|
1030
|
1036
|
location = null;
|
|
|
1037
|
+
|
|
1031
|
1038
|
/**
|
|
1032
|
1039
|
* @param {CellExpressionOperation} op
|
|
1033
|
1040
|
* @param {Array} args
|
|
|
@@ -1451,10 +1458,13 @@ class CellExpression {
|
|
1451
|
1458
|
/**
|
|
1452
|
1459
|
* Tries to parse a format suffix after a semicolon. Examples:
|
|
1453
|
1460
|
*
|
|
1454
|
|
- * ; number
|
|
1455
|
|
- * ; number 3
|
|
1456
|
|
- * ; currency 2
|
|
1457
|
|
- * ; percent 0
|
|
|
1461
|
+ * ```
|
|
|
1462
|
+ * ; number
|
|
|
1463
|
+ * ; number 3
|
|
|
1464
|
+ * ; currency 2
|
|
|
1465
|
+ * ; percent 0
|
|
|
1466
|
+ * ```
|
|
|
1467
|
+ *
|
|
1458
|
1468
|
* @param {CellExpressionToken[]} tokens
|
|
1459
|
1469
|
* @param {number} start
|
|
1460
|
1470
|
* @param {number} end
|
|
|
@@ -1663,6 +1673,21 @@ class CellExpression {
|
|
1663
|
1673
|
return new CellExpression(CellExpressionOperation.Reference, [ refAddress ]);
|
|
1664
|
1674
|
}
|
|
1665
|
1675
|
|
|
|
1676
|
+ static #infixPriority = {};
|
|
|
1677
|
+ static {
|
|
|
1678
|
+ this.#infixPriority[CellExpressionTokenType.Minus.name] = 1;
|
|
|
1679
|
+ this.#infixPriority[CellExpressionTokenType.Plus.name] = 2;
|
|
|
1680
|
+ this.#infixPriority[CellExpressionTokenType.Divide.name] = 3;
|
|
|
1681
|
+ this.#infixPriority[CellExpressionTokenType.Multiply.name] = 4;
|
|
|
1682
|
+ this.#infixPriority[CellExpressionTokenType.Ampersand.name] = 10;
|
|
|
1683
|
+ this.#infixPriority[CellExpressionTokenType.GreaterThan.name] = 20;
|
|
|
1684
|
+ this.#infixPriority[CellExpressionTokenType.GreaterThanEqual.name] = 20;
|
|
|
1685
|
+ this.#infixPriority[CellExpressionTokenType.LessThan.name] = 20;
|
|
|
1686
|
+ this.#infixPriority[CellExpressionTokenType.LessThanEqual.name] = 20;
|
|
|
1687
|
+ this.#infixPriority[CellExpressionTokenType.Equal.name] = 20;
|
|
|
1688
|
+ this.#infixPriority[CellExpressionTokenType.Unequal.name] = 20;
|
|
|
1689
|
+ }
|
|
|
1690
|
+
|
|
1666
|
1691
|
/**
|
|
1667
|
1692
|
* @param {CellExpressionToken[]} tokens
|
|
1668
|
1693
|
* @param {number} start
|
|
|
@@ -1673,18 +1698,6 @@ class CellExpression {
|
|
1673
|
1698
|
static #tryInfix(tokens, start, end, address) {
|
|
1674
|
1699
|
const count = end - start + 1;
|
|
1675
|
1700
|
if (count < 3) return null;
|
|
1676
|
|
- const opPriorities = {}
|
|
1677
|
|
- opPriorities[CellExpressionTokenType.Multiply.name] = 4;
|
|
1678
|
|
- opPriorities[CellExpressionTokenType.Divide.name] = 3;
|
|
1679
|
|
- opPriorities[CellExpressionTokenType.Plus.name] = 2;
|
|
1680
|
|
- opPriorities[CellExpressionTokenType.Minus.name] = 1;
|
|
1681
|
|
- opPriorities[CellExpressionTokenType.Ampersand.name] = 10;
|
|
1682
|
|
- opPriorities[CellExpressionTokenType.GreaterThan.name] = 20;
|
|
1683
|
|
- opPriorities[CellExpressionTokenType.GreaterThanEqual.name] = 20;
|
|
1684
|
|
- opPriorities[CellExpressionTokenType.LessThan.name] = 20;
|
|
1685
|
|
- opPriorities[CellExpressionTokenType.LessThanEqual.name] = 20;
|
|
1686
|
|
- opPriorities[CellExpressionTokenType.Equal.name] = 20;
|
|
1687
|
|
- opPriorities[CellExpressionTokenType.Unequal.name] = 20;
|
|
1688
|
1701
|
var candidates = [];
|
|
1689
|
1702
|
var parenLevel = 0;
|
|
1690
|
1703
|
var i;
|
|
|
@@ -1695,9 +1708,8 @@ class CellExpression {
|
|
1695
|
1708
|
parenLevel--;
|
|
1696
|
1709
|
} else if (parenLevel == 0 && i > start && i < end) {
|
|
1697
|
1710
|
const op = tokens[i].type.name;
|
|
1698
|
|
- const priority = opPriorities[op] ?? false;
|
|
|
1711
|
+ const priority = this.#infixPriority[op] ?? false;
|
|
1699
|
1712
|
if (priority === false) continue;
|
|
1700
|
|
- //console.info(`Found infix candidate at ${i} for ${op} priority ${priority}`);
|
|
1701
|
1713
|
candidates.push({ priority: priority, i: i });
|
|
1702
|
1714
|
}
|
|
1703
|
1715
|
}
|
|
|
@@ -1720,11 +1732,9 @@ class CellExpression {
|
|
1720
|
1732
|
}
|
|
1721
|
1733
|
}
|
|
1722
|
1734
|
if (bestCandidate === null) {
|
|
1723
|
|
- //console.info("No best candidate found");
|
|
1724
|
1735
|
return null;
|
|
1725
|
1736
|
}
|
|
1726
|
1737
|
i = bestCandidate.i;
|
|
1727
|
|
- //console.info(`Best candidate at token ${i}, priority ${bestCandidate.priority}`);
|
|
1728
|
1738
|
switch (tokens[bestCandidate.i].type) {
|
|
1729
|
1739
|
case CellExpressionTokenType.Plus:
|
|
1730
|
1740
|
return new CellExpression(CellExpressionOperation.Add, [ operand1, operand2 ]);
|
|
|
@@ -1800,26 +1810,26 @@ class CellExpressionToken {
|
|
1800
|
1810
|
* uniquely identify a cell.
|
|
1801
|
1811
|
*/
|
|
1802
|
1812
|
class CellAddress {
|
|
1803
|
|
- #name;
|
|
1804
|
1813
|
/**
|
|
1805
|
1814
|
* @type {string}
|
|
1806
|
1815
|
*/
|
|
1807
|
1816
|
get name() { return this.#name; }
|
|
|
1817
|
+ #name;
|
|
1808
|
1818
|
|
|
1809
|
|
- #isColumnFixed = false;
|
|
1810
|
1819
|
/**
|
|
1811
|
1820
|
* Whether the column should remain unchanged when transposed. This is
|
|
1812
|
1821
|
* symbolized by prefixing the column name with a `$` (e.g. `$C3`).
|
|
1813
|
1822
|
* @type {boolean}
|
|
1814
|
1823
|
*/
|
|
1815
|
1824
|
get isColumnFixed() { return this.#isColumnFixed; }
|
|
|
1825
|
+ #isColumnFixed = false;
|
|
1816
|
1826
|
|
|
1817
|
|
- #columnIndex = -1;
|
|
1818
|
1827
|
/**
|
|
1819
|
1828
|
* Zero-based column index.
|
|
1820
|
1829
|
* @type {number}
|
|
1821
|
1830
|
*/
|
|
1822
|
1831
|
get columnIndex() { return this.#columnIndex; };
|
|
|
1832
|
+ #columnIndex = -1;
|
|
1823
|
1833
|
|
|
1824
|
1834
|
/**
|
|
1825
|
1835
|
* Letter code for the column.
|
|
|
@@ -1827,20 +1837,20 @@ class CellAddress {
|
|
1827
|
1837
|
*/
|
|
1828
|
1838
|
get columnLetter() { return CellAddress.#columnIndexToLetters(this.#columnIndex); }
|
|
1829
|
1839
|
|
|
1830
|
|
- #isRowFixed = false;
|
|
1831
|
1840
|
/**
|
|
1832
|
1841
|
* Whether the row should remain unchanged when transposed. This is
|
|
1833
|
1842
|
* symbolized by prefixing the row number with a `$` (e.g. `C$3`).
|
|
1834
|
1843
|
* @type {boolean}
|
|
1835
|
1844
|
*/
|
|
1836
|
1845
|
get isRowFixed() { return this.#isRowFixed; }
|
|
|
1846
|
+ #isRowFixed = false;
|
|
1837
|
1847
|
|
|
1838
|
|
- #rowIndex = -1;
|
|
1839
|
1848
|
/**
|
|
1840
|
1849
|
* Zero-based row index.
|
|
1841
|
1850
|
* @type {number}
|
|
1842
|
1851
|
*/
|
|
1843
|
1852
|
get rowIndex() { return this.#rowIndex; }
|
|
|
1853
|
+ #rowIndex = -1;
|
|
1844
|
1854
|
|
|
1845
|
1855
|
/**
|
|
1846
|
1856
|
* One-based row number. This is the human-facing row number.
|
|
|
@@ -1877,6 +1887,7 @@ class CellAddress {
|
|
1877
|
1887
|
|
|
1878
|
1888
|
/**
|
|
1879
|
1889
|
* Tests if a string is formatted like an address.
|
|
|
1890
|
+ *
|
|
1880
|
1891
|
* @param {string} text
|
|
1881
|
1892
|
* @returns {boolean}
|
|
1882
|
1893
|
*/
|
|
|
@@ -1894,15 +1905,19 @@ class CellAddress {
|
|
1894
|
1905
|
*
|
|
1895
|
1906
|
* Examples:
|
|
1896
|
1907
|
* - C6.transpose(A5, A9) = C10 (A9-A5 = +4 rows, C6 + 4 rows = C10)
|
|
1897
|
|
- * - C6.transpose(A5, B9) = D10 (B9-A5 = +4 rows +1 cols, C6 + 4 rows + 1 col = D10)
|
|
1898
|
|
- * - C$6.transpose(A5, A9) = C6 (A9-A5 = +4 rows, but row is fixed, so still C6)
|
|
1899
|
|
- * - B.transpose(A5, A9) = B9 (A9-A4 = +4 rows, B has no row so last row used = B9)
|
|
|
1908
|
+ * - C6.transpose(A5, B9) = D10 (B9-A5 = +4 rows +1 cols, C6 + 4 rows + 1
|
|
|
1909
|
+ * col = D10)
|
|
|
1910
|
+ * - C$6.transpose(A5, A9) = C6 (A9-A5 = +4 rows, but row is fixed, so
|
|
|
1911
|
+ * still C6)
|
|
|
1912
|
+ * - B.transpose(A5, A9) = B9 (A9-A4 = +4 rows, B has no row so last row
|
|
|
1913
|
+ * used = B9)
|
|
1900
|
1914
|
* - A1.transpose(C3, A1) = null (out of bounds)
|
|
1901
|
1915
|
*
|
|
1902
|
1916
|
* @param {CellAddress} relativeFrom - original address of the formula
|
|
1903
|
|
- * @param {CellAddress} relativeTo - address where the formula is being repeated
|
|
1904
|
|
- * @param {boolean} resolveToRow - whether to fill in a row number if this address
|
|
1905
|
|
- * doesn't have one
|
|
|
1917
|
+ * @param {CellAddress} relativeTo - address where the formula is being
|
|
|
1918
|
+ * repeated
|
|
|
1919
|
+ * @param {boolean} resolveToRow - whether to fill in a row number if this
|
|
|
1920
|
+ * address doesn't have one
|
|
1906
|
1921
|
* @returns {CellAddress|null} - resolved address, or `null` if out of bounds
|
|
1907
|
1922
|
*/
|
|
1908
|
1923
|
transpose(relativeFrom, relativeTo, resolveToRow = true) {
|
|
|
@@ -1989,11 +2004,13 @@ class CellAddress {
|
|
1989
|
2004
|
* Attempts to convert a cell address string to a `CellAddress`.
|
|
1990
|
2005
|
*
|
|
1991
|
2006
|
* @param {string} address - cell address string
|
|
1992
|
|
- * @param {CellAddress|null} relativeTo - address to resolve relative addresses against
|
|
1993
|
|
- * @param {boolean} throwIfInvalid - whether to throw an error if address is invalid
|
|
|
2007
|
+ * @param {CellAddress|null} relativeTo - address to resolve relative
|
|
|
2008
|
+ * addresses against
|
|
|
2009
|
+ * @param {boolean} throwIfInvalid - whether to throw an error if address
|
|
|
2010
|
+ * is invalid
|
|
1994
|
2011
|
* @returns {CellAddress|null} address, if parsable
|
|
1995
|
|
- * @throws {CellEvaluationException} if the address is invalid and `throwIfInvalid`
|
|
1996
|
|
- * is `true`
|
|
|
2012
|
+ * @throws {CellEvaluationException} if the address is invalid and
|
|
|
2013
|
+ * `throwIfInvalid` is `true`
|
|
1997
|
2014
|
*/
|
|
1998
|
2015
|
static fromString(address, relativeTo=null, throwIfInvalid=false) {
|
|
1999
|
2016
|
const groups = /^(\$?)([A-Z]{1,2}?)((?:\$(?=[0-9]))?)([0-9]*)$/i.exec(address);
|
|
|
@@ -2069,9 +2086,11 @@ class CellAddressRange {
|
|
2069
|
2086
|
*/
|
|
2070
|
2087
|
cellsIn(grid) {
|
|
2071
|
2088
|
const minCol = this.minColumnIndex < 0 ? 0 : this.minColumnIndex;
|
|
2072
|
|
- const maxCol = this.maxColumnIndex < 0 ? grid.columnCount - 1 : Math.min(this.maxColumnIndex, grid.columnCount - 1);
|
|
|
2089
|
+ const maxCol = this.maxColumnIndex < 0 ? grid.columnCount - 1
|
|
|
2090
|
+ : Math.min(this.maxColumnIndex, grid.columnCount - 1);
|
|
2073
|
2091
|
const minRow = this.minRowIndex < 0 ? 0 : this.minRowIndex;
|
|
2074
|
|
- const maxRow = this.maxRowIndex < 0 ? grid.rowCount - 1 : Math.min(this.maxRowIndex, grid.rowCount - 1);
|
|
|
2092
|
+ const maxRow = this.maxRowIndex < 0 ? grid.rowCount - 1
|
|
|
2093
|
+ : Math.min(this.maxRowIndex, grid.rowCount - 1);
|
|
2075
|
2094
|
const iterable = {};
|
|
2076
|
2095
|
iterable[Symbol.iterator] = function() {
|
|
2077
|
2096
|
var currentCol = minCol;
|
|
|
@@ -2133,7 +2152,7 @@ class CellValue {
|
|
2133
|
2152
|
*/
|
|
2134
|
2153
|
static TYPE_FORMULA = 'formula';
|
|
2135
|
2154
|
|
|
2136
|
|
- // -- Properties -----
|
|
|
2155
|
+ // -- Properties -----
|
|
2137
|
2156
|
|
|
2138
|
2157
|
/**
|
|
2139
|
2158
|
* A blank value.
|
|
|
@@ -2187,6 +2206,7 @@ class CellValue {
|
|
2187
|
2206
|
|
|
2188
|
2207
|
/**
|
|
2189
|
2208
|
* Returns whether this value is a numeric type.
|
|
|
2209
|
+ *
|
|
2190
|
2210
|
* @returns {boolean}
|
|
2191
|
2211
|
*/
|
|
2192
|
2212
|
isNumeric() {
|
|
|
@@ -2356,6 +2376,7 @@ class CellValue {
|
|
2356
|
2376
|
|
|
2357
|
2377
|
/**
|
|
2358
|
2378
|
* Returns the boolean equivalent of this value if possible.
|
|
|
2379
|
+ *
|
|
2359
|
2380
|
* @returns {boolean|null}
|
|
2360
|
2381
|
*/
|
|
2361
|
2382
|
booleanValue() {
|
|
|
@@ -2377,6 +2398,7 @@ class CellValue {
|
|
2377
|
2398
|
|
|
2378
|
2399
|
/**
|
|
2379
|
2400
|
* Returns the numeric value of this value if possible.
|
|
|
2401
|
+ *
|
|
2380
|
2402
|
* @returns {number|null}
|
|
2381
|
2403
|
*/
|
|
2382
|
2404
|
numericValue() {
|
|
|
@@ -2398,6 +2420,7 @@ class CellValue {
|
|
2398
|
2420
|
|
|
2399
|
2421
|
/**
|
|
2400
|
2422
|
* Returns the string value of this value if possible.
|
|
|
2423
|
+ *
|
|
2401
|
2424
|
* @param {boolean} formatted
|
|
2402
|
2425
|
* @returns {string|null}
|
|
2403
|
2426
|
*/
|
|
|
@@ -2428,7 +2451,8 @@ class CellValue {
|
|
2428
|
2451
|
* @returns {CellValue} sum
|
|
2429
|
2452
|
*/
|
|
2430
|
2453
|
add(b) {
|
|
2431
|
|
- return CellValue.#binaryNumericOperation(this, b, '+', (aVal, bVal) => aVal + bVal);
|
|
|
2454
|
+ return CellValue.#binaryNumericOperation(this, b, '+',
|
|
|
2455
|
+ (aVal, bVal) => aVal + bVal);
|
|
2432
|
2456
|
}
|
|
2433
|
2457
|
|
|
2434
|
2458
|
/**
|
|
|
@@ -2438,7 +2462,8 @@ class CellValue {
|
|
2438
|
2462
|
* @returns {CellValue} difference
|
|
2439
|
2463
|
*/
|
|
2440
|
2464
|
subtract(b) {
|
|
2441
|
|
- return CellValue.#binaryNumericOperation(this, b, '-', (aVal, bVal) => aVal - bVal);
|
|
|
2465
|
+ return CellValue.#binaryNumericOperation(this, b, '-',
|
|
|
2466
|
+ (aVal, bVal) => aVal - bVal);
|
|
2442
|
2467
|
}
|
|
2443
|
2468
|
|
|
2444
|
2469
|
/**
|
|
|
@@ -2448,7 +2473,8 @@ class CellValue {
|
|
2448
|
2473
|
* @returns {CellValue} product
|
|
2449
|
2474
|
*/
|
|
2450
|
2475
|
multiply(b) {
|
|
2451
|
|
- return CellValue.#binaryNumericOperation(this, b, '*', (aVal, bVal) => aVal * bVal);
|
|
|
2476
|
+ return CellValue.#binaryNumericOperation(this, b, '*',
|
|
|
2477
|
+ (aVal, bVal) => aVal * bVal);
|
|
2452
|
2478
|
}
|
|
2453
|
2479
|
|
|
2454
|
2480
|
/**
|
|
|
@@ -2541,6 +2567,7 @@ class CellValue {
|
|
2541
|
2567
|
|
|
2542
|
2568
|
/**
|
|
2543
|
2569
|
* Returns the boolean not of this value.
|
|
|
2570
|
+ *
|
|
2544
|
2571
|
* @returns {CellValue}
|
|
2545
|
2572
|
*/
|
|
2546
|
2573
|
not() {
|
|
|
@@ -2563,6 +2590,9 @@ class CellValue {
|
|
2563
|
2590
|
}
|
|
2564
|
2591
|
|
|
2565
|
2592
|
/**
|
|
|
2593
|
+ * Returns the string representation of a value concatenated to the string
|
|
|
2594
|
+ * representation of this value.
|
|
|
2595
|
+ *
|
|
2566
|
2596
|
* @param {CellValue} b
|
|
2567
|
2597
|
* @returns {CellValue}
|
|
2568
|
2598
|
*/
|
|
|
@@ -2576,11 +2606,13 @@ class CellValue {
|
|
2576
|
2606
|
}
|
|
2577
|
2607
|
|
|
2578
|
2608
|
/**
|
|
2579
|
|
- * @param {CellValue} a
|
|
2580
|
|
- * @param {CellValue} b
|
|
2581
|
|
- * @param {string} op
|
|
|
2609
|
+ * Helper to resolve two numeric arguments and perform an operation on them.
|
|
|
2610
|
+ *
|
|
|
2611
|
+ * @param {CellValue} a - operand A
|
|
|
2612
|
+ * @param {CellValue} b - operand B
|
|
|
2613
|
+ * @param {string} op - operator
|
|
2582
|
2614
|
* @param {function} fn - takes two `number` arguments and returns a `number` result
|
|
2583
|
|
- * @returns {CellValue}
|
|
|
2615
|
+ * @returns {CellValue} result
|
|
2584
|
2616
|
* @throws {CellEvaluationException}
|
|
2585
|
2617
|
*/
|
|
2586
|
2618
|
static #binaryNumericOperation(a, b, op, fn) {
|
|
|
@@ -2654,9 +2686,11 @@ class CellValue {
|
|
2654
|
2686
|
}
|
|
2655
|
2687
|
|
|
2656
|
2688
|
/**
|
|
|
2689
|
+ * Performs a comparison of two values.
|
|
|
2690
|
+ *
|
|
2657
|
2691
|
* @param {CellValue} a
|
|
2658
|
2692
|
* @param {CellValue} b
|
|
2659
|
|
- * @returns {number}
|
|
|
2693
|
+ * @returns {number} `-1`, `0`, or `1` if a < b, a == b, or a > b, respectively
|
|
2660
|
2694
|
*/
|
|
2661
|
2695
|
static #compare(a, b) {
|
|
2662
|
2696
|
const args = CellValue.#resolveComparableArguments(a, b);
|
|
|
@@ -2712,10 +2746,11 @@ class CellValue {
|
|
2712
|
2746
|
/**
|
|
2713
|
2747
|
* Returns a formatted string for the given raw value, value type, and
|
|
2714
|
2748
|
* decimal places.
|
|
|
2749
|
+ *
|
|
2715
|
2750
|
* @param {any} value
|
|
2716
|
2751
|
* @param {string} type
|
|
2717
|
2752
|
* @param {number} decimals
|
|
2718
|
|
- * @returns {string}
|
|
|
2753
|
+ * @returns {string} formatted value
|
|
2719
|
2754
|
*/
|
|
2720
|
2755
|
static formatType(value, type, decimals) {
|
|
2721
|
2756
|
switch (type) {
|
|
|
@@ -2763,9 +2798,10 @@ class CellValue {
|
|
2763
|
2798
|
|
|
2764
|
2799
|
/**
|
|
2765
|
2800
|
* Determines a good number of decimal places to format a value to.
|
|
|
2801
|
+ *
|
|
2766
|
2802
|
* @param {any} value
|
|
2767
|
2803
|
* @param {number} maxDigits
|
|
2768
|
|
- * @returns {number}
|
|
|
2804
|
+ * @returns {number} digit count
|
|
2769
|
2805
|
*/
|
|
2770
|
2806
|
static #autodecimals(value, maxDigits = 6) {
|
|
2771
|
2807
|
if (value instanceof CellValue) {
|
|
|
@@ -2781,6 +2817,8 @@ class CellValue {
|
|
2781
|
2817
|
}
|
|
2782
|
2818
|
|
|
2783
|
2819
|
/**
|
|
|
2820
|
+ * Tests if a type is numeric.
|
|
|
2821
|
+ *
|
|
2784
|
2822
|
* @param {string} type
|
|
2785
|
2823
|
* @returns {boolean}
|
|
2786
|
2824
|
*/
|
|
|
@@ -2874,7 +2912,10 @@ class SpreadsheetCell {
|
|
2874
|
2912
|
*/
|
|
2875
|
2913
|
outputValue = null;
|
|
2876
|
2914
|
|
|
2877
|
|
- /** @type {boolean} */
|
|
|
2915
|
+ /**
|
|
|
2916
|
+ * Whether `outputValue` is the result of a formula evaluation.
|
|
|
2917
|
+ * @type {boolean}
|
|
|
2918
|
+ */
|
|
2878
|
2919
|
isCalculated = false;
|
|
2879
|
2920
|
|
|
2880
|
2921
|
/** @type {CellExpression|null} */
|