@devmm/puredocs-excel-formula 1.0.8 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +266 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +267 -92
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -807,6 +807,16 @@ var ArrayLiteralNode = class extends FormulaNode {
|
|
|
807
807
|
}
|
|
808
808
|
};
|
|
809
809
|
_value = new WeakMap();
|
|
810
|
+
var ValueNode = class extends FormulaNode {
|
|
811
|
+
/** Mutable so one wrapper can be re-pointed across a lifted call's cells. */
|
|
812
|
+
constructor(value2) {
|
|
813
|
+
super();
|
|
814
|
+
this.value = value2;
|
|
815
|
+
}
|
|
816
|
+
evaluate() {
|
|
817
|
+
return this.value;
|
|
818
|
+
}
|
|
819
|
+
};
|
|
810
820
|
var BlankNode = class extends FormulaNode {
|
|
811
821
|
evaluate() {
|
|
812
822
|
return FormulaValue.blank;
|
|
@@ -1576,42 +1586,42 @@ function registerMath(r) {
|
|
|
1576
1586
|
r.register("PRODUCT", product, 1);
|
|
1577
1587
|
r.register("SUMPRODUCT", sumProduct, 1);
|
|
1578
1588
|
r.register("SUMSQ", sumSq, 1);
|
|
1579
|
-
r.
|
|
1580
|
-
r.
|
|
1581
|
-
r.
|
|
1582
|
-
r.
|
|
1583
|
-
r.
|
|
1584
|
-
r.
|
|
1585
|
-
r.
|
|
1586
|
-
r.
|
|
1587
|
-
r.
|
|
1588
|
-
r.
|
|
1589
|
-
r.
|
|
1590
|
-
r.
|
|
1591
|
-
r.
|
|
1592
|
-
r.
|
|
1593
|
-
r.
|
|
1589
|
+
r.registerElementwise("ABS", abs, 1, 1);
|
|
1590
|
+
r.registerElementwise("ROUND", round, 2, 2);
|
|
1591
|
+
r.registerElementwise("ROUNDUP", roundUp, 2, 2);
|
|
1592
|
+
r.registerElementwise("ROUNDDOWN", roundDown, 2, 2);
|
|
1593
|
+
r.registerElementwise("CEILING", ceiling, 2, 2);
|
|
1594
|
+
r.registerElementwise("CEILING.MATH", ceiling, 2, 2);
|
|
1595
|
+
r.registerElementwise("FLOOR", floor, 2, 2);
|
|
1596
|
+
r.registerElementwise("FLOOR.MATH", floor, 2, 2);
|
|
1597
|
+
r.registerElementwise("INT", int_, 1, 1);
|
|
1598
|
+
r.registerElementwise("TRUNC", trunc, 1, 2);
|
|
1599
|
+
r.registerElementwise("MOD", mod, 2, 2);
|
|
1600
|
+
r.registerElementwise("QUOTIENT", quotient, 2, 2);
|
|
1601
|
+
r.registerElementwise("POWER", power, 2, 2);
|
|
1602
|
+
r.registerElementwise("SQRT", sqrt, 1, 1);
|
|
1603
|
+
r.registerElementwise("SIGN", sign, 1, 1);
|
|
1594
1604
|
r.register("PI", pi, 0, 0);
|
|
1595
1605
|
r.register("RAND", rand, 0, 0, true);
|
|
1596
1606
|
r.register("RANDBETWEEN", randBetween, 2, 2, true);
|
|
1597
|
-
r.
|
|
1598
|
-
r.
|
|
1599
|
-
r.
|
|
1600
|
-
r.
|
|
1601
|
-
r.
|
|
1602
|
-
r.
|
|
1603
|
-
r.
|
|
1604
|
-
r.
|
|
1605
|
-
r.
|
|
1606
|
-
r.
|
|
1607
|
-
r.
|
|
1608
|
-
r.
|
|
1609
|
-
r.
|
|
1610
|
-
r.
|
|
1611
|
-
r.
|
|
1612
|
-
r.
|
|
1613
|
-
r.
|
|
1614
|
-
r.
|
|
1607
|
+
r.registerElementwise("LOG", log, 1, 2);
|
|
1608
|
+
r.registerElementwise("LOG10", log10, 1, 1);
|
|
1609
|
+
r.registerElementwise("LN", ln, 1, 1);
|
|
1610
|
+
r.registerElementwise("EXP", exp, 1, 1);
|
|
1611
|
+
r.registerElementwise("FACT", fact, 1, 1);
|
|
1612
|
+
r.registerElementwise("COMBIN", combin, 2, 2);
|
|
1613
|
+
r.registerElementwise("SIN", unary(Math.sin), 1, 1);
|
|
1614
|
+
r.registerElementwise("COS", unary(Math.cos), 1, 1);
|
|
1615
|
+
r.registerElementwise("TAN", unary(Math.tan), 1, 1);
|
|
1616
|
+
r.registerElementwise("ASIN", asin, 1, 1);
|
|
1617
|
+
r.registerElementwise("ACOS", acos, 1, 1);
|
|
1618
|
+
r.registerElementwise("ATAN", unary(Math.atan), 1, 1);
|
|
1619
|
+
r.registerElementwise("ATAN2", atan2, 2, 2);
|
|
1620
|
+
r.registerElementwise("SINH", unary(Math.sinh), 1, 1);
|
|
1621
|
+
r.registerElementwise("COSH", unary(Math.cosh), 1, 1);
|
|
1622
|
+
r.registerElementwise("TANH", unary(Math.tanh), 1, 1);
|
|
1623
|
+
r.registerElementwise("DEGREES", unary((r2d) => r2d * 180 / Math.PI), 1, 1);
|
|
1624
|
+
r.registerElementwise("RADIANS", unary((d) => d * Math.PI / 180), 1, 1);
|
|
1615
1625
|
}
|
|
1616
1626
|
function valueAt(v, i) {
|
|
1617
1627
|
return v.isArray ? v.arrayVal.getFlat(i) : v;
|
|
@@ -2043,31 +2053,31 @@ function combin(a, c) {
|
|
|
2043
2053
|
return FormulaValue.number(Math.round(result));
|
|
2044
2054
|
}
|
|
2045
2055
|
function registerText(r) {
|
|
2046
|
-
r.
|
|
2047
|
-
r.
|
|
2048
|
-
r.
|
|
2049
|
-
r.
|
|
2050
|
-
r.
|
|
2051
|
-
r.
|
|
2052
|
-
r.
|
|
2053
|
-
r.
|
|
2054
|
-
r.
|
|
2055
|
-
r.
|
|
2056
|
-
r.
|
|
2056
|
+
r.registerElementwise("LEFT", left, 1, 2);
|
|
2057
|
+
r.registerElementwise("RIGHT", right, 1, 2);
|
|
2058
|
+
r.registerElementwise("MID", mid, 3, 3);
|
|
2059
|
+
r.registerElementwise("LEN", len, 1, 1);
|
|
2060
|
+
r.registerElementwise("UPPER", upper, 1, 1);
|
|
2061
|
+
r.registerElementwise("LOWER", lower, 1, 1);
|
|
2062
|
+
r.registerElementwise("PROPER", proper, 1, 1);
|
|
2063
|
+
r.registerElementwise("TRIM", trim, 1, 1);
|
|
2064
|
+
r.registerElementwise("CLEAN", clean, 1, 1);
|
|
2065
|
+
r.registerElementwise("SUBSTITUTE", substitute, 3, 4);
|
|
2066
|
+
r.registerElementwise("REPLACE", replace, 4, 4);
|
|
2057
2067
|
r.register("CONCATENATE", concatenate, 1);
|
|
2058
2068
|
r.register("CONCAT", concatenate, 1);
|
|
2059
2069
|
r.register("TEXTJOIN", textJoin, 3);
|
|
2060
|
-
r.
|
|
2061
|
-
r.
|
|
2062
|
-
r.
|
|
2063
|
-
r.
|
|
2064
|
-
r.
|
|
2065
|
-
r.
|
|
2066
|
-
r.
|
|
2067
|
-
r.
|
|
2068
|
-
r.
|
|
2069
|
-
r.
|
|
2070
|
-
r.
|
|
2070
|
+
r.registerElementwise("TEXT", text_, 2, 2);
|
|
2071
|
+
r.registerElementwise("VALUE", value, 1, 1);
|
|
2072
|
+
r.registerElementwise("FIND", find, 2, 3);
|
|
2073
|
+
r.registerElementwise("SEARCH", search, 2, 3);
|
|
2074
|
+
r.registerElementwise("REPT", rept, 2, 2);
|
|
2075
|
+
r.registerElementwise("EXACT", exact, 2, 2);
|
|
2076
|
+
r.registerElementwise("CHAR", char_, 1, 1);
|
|
2077
|
+
r.registerElementwise("CODE", code, 1, 1);
|
|
2078
|
+
r.registerElementwise("T", t_, 1, 1);
|
|
2079
|
+
r.registerElementwise("TEXTBEFORE", textBefore, 2, 3);
|
|
2080
|
+
r.registerElementwise("TEXTAFTER", textAfter, 2, 3);
|
|
2071
2081
|
}
|
|
2072
2082
|
function str(a, c, idx) {
|
|
2073
2083
|
const r = exports.FormulaHelper.evalString(a[idx], c);
|
|
@@ -2381,6 +2391,7 @@ function registerLogical(r) {
|
|
|
2381
2391
|
function if_(a, c) {
|
|
2382
2392
|
const cond = a[0].evaluate(c);
|
|
2383
2393
|
if (cond.isError) return cond;
|
|
2394
|
+
if (cond.isArray) return ifArray(cond.arrayVal, a, c);
|
|
2384
2395
|
const b = cond.coerceToBool();
|
|
2385
2396
|
if (b.isError) return b;
|
|
2386
2397
|
return b.booleanValue ? a[1].evaluate(c) : a.length > 2 ? a[2].evaluate(c) : FormulaValue.false_;
|
|
@@ -2457,13 +2468,63 @@ function xor(a, c) {
|
|
|
2457
2468
|
}
|
|
2458
2469
|
return FormulaValue.boolean(trueCount % 2 === 1);
|
|
2459
2470
|
}
|
|
2460
|
-
function
|
|
2471
|
+
function ifArray(mask, a, c) {
|
|
2472
|
+
let wantTrue = false, wantFalse = false;
|
|
2473
|
+
for (const item of mask.values()) {
|
|
2474
|
+
const b = item.coerceToBool();
|
|
2475
|
+
if (b.isError) return b;
|
|
2476
|
+
if (b.booleanValue) wantTrue = true;
|
|
2477
|
+
else wantFalse = true;
|
|
2478
|
+
if (wantTrue && wantFalse) break;
|
|
2479
|
+
}
|
|
2480
|
+
const yes = wantTrue ? a[1].evaluate(c) : FormulaValue.blank;
|
|
2481
|
+
const no = wantFalse ? a.length > 2 ? a[2].evaluate(c) : FormulaValue.false_ : FormulaValue.blank;
|
|
2482
|
+
const pick = (v, r, col) => {
|
|
2483
|
+
if (!v.isArray) return v;
|
|
2484
|
+
const arr = v.arrayVal;
|
|
2485
|
+
return r < arr.rows && col < arr.columns ? arr.get(r, col) : FormulaValue.errorNA;
|
|
2486
|
+
};
|
|
2487
|
+
const out = new ArrayValue(mask.rows, mask.columns);
|
|
2488
|
+
for (let r = 0; r < mask.rows; r++) {
|
|
2489
|
+
for (let col = 0; col < mask.columns; col++) {
|
|
2490
|
+
const b = mask.get(r, col).coerceToBool();
|
|
2491
|
+
out.set(r, col, b.booleanValue ? pick(yes, r, col) : pick(no, r, col));
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
return FormulaValue.array(out);
|
|
2495
|
+
}
|
|
2496
|
+
function ifCaught(a, c, caught) {
|
|
2461
2497
|
const v = a[0].evaluate(c);
|
|
2462
|
-
|
|
2498
|
+
if (!v.isArray) return caught(v) ? a[1].evaluate(c) : v;
|
|
2499
|
+
const arr = v.arrayVal;
|
|
2500
|
+
let any = false;
|
|
2501
|
+
for (const item of arr.values()) {
|
|
2502
|
+
if (caught(item)) {
|
|
2503
|
+
any = true;
|
|
2504
|
+
break;
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
if (!any) return v;
|
|
2508
|
+
const fb = a[1].evaluate(c);
|
|
2509
|
+
const fbArr = fb.isArray ? fb.arrayVal : null;
|
|
2510
|
+
const out = new ArrayValue(arr.rows, arr.columns);
|
|
2511
|
+
for (let r = 0; r < arr.rows; r++) {
|
|
2512
|
+
for (let col = 0; col < arr.columns; col++) {
|
|
2513
|
+
const item = arr.get(r, col);
|
|
2514
|
+
if (!caught(item)) {
|
|
2515
|
+
out.set(r, col, item);
|
|
2516
|
+
continue;
|
|
2517
|
+
}
|
|
2518
|
+
out.set(r, col, fbArr ? r < fbArr.rows && col < fbArr.columns ? fbArr.get(r, col) : FormulaValue.errorNA : fb);
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
return FormulaValue.array(out);
|
|
2522
|
+
}
|
|
2523
|
+
function ifError(a, c) {
|
|
2524
|
+
return ifCaught(a, c, (v) => v.isError);
|
|
2463
2525
|
}
|
|
2464
2526
|
function ifNa(a, c) {
|
|
2465
|
-
|
|
2466
|
-
return v.isError && v.errorCode === 7 /* NA */ ? a[1].evaluate(c) : v;
|
|
2527
|
+
return ifCaught(a, c, (v) => v.isError && v.errorCode === 7 /* NA */);
|
|
2467
2528
|
}
|
|
2468
2529
|
function ifs(a, c) {
|
|
2469
2530
|
for (let i = 0; i + 1 < a.length; i += 2) {
|
|
@@ -2520,21 +2581,21 @@ function fromOA(oa) {
|
|
|
2520
2581
|
function registerDate(r) {
|
|
2521
2582
|
r.register("NOW", now, 0, 0, true);
|
|
2522
2583
|
r.register("TODAY", today, 0, 0, true);
|
|
2523
|
-
r.
|
|
2524
|
-
r.
|
|
2525
|
-
r.
|
|
2526
|
-
r.
|
|
2527
|
-
r.
|
|
2528
|
-
r.
|
|
2529
|
-
r.
|
|
2530
|
-
r.
|
|
2531
|
-
r.
|
|
2532
|
-
r.
|
|
2533
|
-
r.
|
|
2534
|
-
r.
|
|
2535
|
-
r.
|
|
2584
|
+
r.registerElementwise("DATE", date_, 3, 3);
|
|
2585
|
+
r.registerElementwise("YEAR", year, 1, 1);
|
|
2586
|
+
r.registerElementwise("MONTH", month, 1, 1);
|
|
2587
|
+
r.registerElementwise("DAY", day, 1, 1);
|
|
2588
|
+
r.registerElementwise("HOUR", hour, 1, 1);
|
|
2589
|
+
r.registerElementwise("MINUTE", minute, 1, 1);
|
|
2590
|
+
r.registerElementwise("SECOND", second, 1, 1);
|
|
2591
|
+
r.registerElementwise("DATEVALUE", dateValue, 1, 1);
|
|
2592
|
+
r.registerElementwise("DAYS", days, 2, 2);
|
|
2593
|
+
r.registerElementwise("EDATE", edate, 2, 2);
|
|
2594
|
+
r.registerElementwise("EOMONTH", eomonth, 2, 2);
|
|
2595
|
+
r.registerElementwise("WEEKDAY", weekday, 1, 2);
|
|
2596
|
+
r.registerElementwise("WEEKNUM", weeknum, 1, 2);
|
|
2536
2597
|
r.register("NETWORKDAYS", networkdays, 2, 3);
|
|
2537
|
-
r.
|
|
2598
|
+
r.registerElementwise("DATEDIF", datedif, 3, 3);
|
|
2538
2599
|
}
|
|
2539
2600
|
function evalDate(a, c, idx) {
|
|
2540
2601
|
const r = exports.FormulaHelper.evalDouble(a[idx], c);
|
|
@@ -3347,20 +3408,20 @@ function ifsAggregate(a, c, mode2) {
|
|
|
3347
3408
|
|
|
3348
3409
|
// src/functions/info-functions.ts
|
|
3349
3410
|
function registerInfo(r) {
|
|
3350
|
-
r.
|
|
3351
|
-
r.
|
|
3352
|
-
r.
|
|
3353
|
-
r.
|
|
3354
|
-
r.
|
|
3355
|
-
r.
|
|
3356
|
-
r.
|
|
3357
|
-
r.
|
|
3411
|
+
r.registerElementwise("ISBLANK", isBlank, 1, 1);
|
|
3412
|
+
r.registerElementwise("ISNUMBER", isNumber, 1, 1);
|
|
3413
|
+
r.registerElementwise("ISTEXT", isText, 1, 1);
|
|
3414
|
+
r.registerElementwise("ISERROR", isError, 1, 1);
|
|
3415
|
+
r.registerElementwise("ISERR", isErr, 1, 1);
|
|
3416
|
+
r.registerElementwise("ISLOGICAL", isLogical, 1, 1);
|
|
3417
|
+
r.registerElementwise("ISNA", isNa, 1, 1);
|
|
3418
|
+
r.registerElementwise("ISNONTEXT", isNonText, 1, 1);
|
|
3358
3419
|
r.register("NA", na, 0, 0);
|
|
3359
|
-
r.
|
|
3360
|
-
r.
|
|
3361
|
-
r.
|
|
3362
|
-
r.
|
|
3363
|
-
r.
|
|
3420
|
+
r.registerElementwise("TYPE", type_, 1, 1);
|
|
3421
|
+
r.registerElementwise("N", n_, 1, 1);
|
|
3422
|
+
r.registerElementwise("ISODD", isOdd, 1, 1);
|
|
3423
|
+
r.registerElementwise("ISEVEN", isEven, 1, 1);
|
|
3424
|
+
r.registerElementwise("ERROR.TYPE", errorType, 1, 1);
|
|
3364
3425
|
}
|
|
3365
3426
|
function isBlank(a, c) {
|
|
3366
3427
|
return FormulaValue.boolean(a[0].evaluate(c).isBlank);
|
|
@@ -4448,7 +4509,8 @@ function toRow(a, c) {
|
|
|
4448
4509
|
}
|
|
4449
4510
|
|
|
4450
4511
|
// src/function-registry.ts
|
|
4451
|
-
var
|
|
4512
|
+
var MAX_LIFTED_CELLS = 1048576;
|
|
4513
|
+
var _default, _functions, _FunctionRegistry_static, executeElementwise_fn, _FunctionRegistry_instances, registerBuiltIns_fn;
|
|
4452
4514
|
var _FunctionRegistry = class _FunctionRegistry {
|
|
4453
4515
|
constructor() {
|
|
4454
4516
|
__privateAdd(this, _FunctionRegistry_instances);
|
|
@@ -4470,17 +4532,45 @@ var _FunctionRegistry = class _FunctionRegistry {
|
|
|
4470
4532
|
minArgs,
|
|
4471
4533
|
maxArgs,
|
|
4472
4534
|
isVolatile,
|
|
4473
|
-
handler
|
|
4535
|
+
handler,
|
|
4536
|
+
elementwise: false
|
|
4537
|
+
});
|
|
4538
|
+
}
|
|
4539
|
+
/**
|
|
4540
|
+
* Registers a **scalar** function — one whose arguments are single values —
|
|
4541
|
+
* and lifts it over arrays automatically.
|
|
4542
|
+
*
|
|
4543
|
+
* `LEFT(A2:A100, 3)` is not a special form in Excel: LEFT takes one string, and
|
|
4544
|
+
* the grid maps it over the range, giving a 99-row array. Without that lifting
|
|
4545
|
+
* the range collapses to one value, so the dynamic array built on top of it —
|
|
4546
|
+
* `FILTER(IFERROR(LEFT(A2:A100,3),""), …)` — filters a 1×1 input and returns
|
|
4547
|
+
* `#CALC!`. Lifting belongs here rather than in each handler: the ~40 scalar
|
|
4548
|
+
* text/math/date functions then get it for free and cannot each get it subtly
|
|
4549
|
+
* wrong.
|
|
4550
|
+
*
|
|
4551
|
+
* Only mark functions that are genuinely per-cell. Anything that *consumes* an
|
|
4552
|
+
* array (SUM, COUNTIF, FILTER, SORT, the lazy branch functions) must keep
|
|
4553
|
+
* `register`, or lifting would map it over the array it is meant to reduce.
|
|
4554
|
+
*/
|
|
4555
|
+
registerElementwise(name, handler, minArgs = 0, maxArgs = -1) {
|
|
4556
|
+
__privateGet(this, _functions).set(name.toUpperCase(), {
|
|
4557
|
+
name: name.toUpperCase(),
|
|
4558
|
+
minArgs,
|
|
4559
|
+
maxArgs,
|
|
4560
|
+
isVolatile: false,
|
|
4561
|
+
handler,
|
|
4562
|
+
elementwise: true
|
|
4474
4563
|
});
|
|
4475
4564
|
}
|
|
4476
4565
|
/** Executes a function by name with argument validation. */
|
|
4477
4566
|
execute(name, args, ctx) {
|
|
4567
|
+
var _a;
|
|
4478
4568
|
const def = __privateGet(this, _functions).get(name.toUpperCase());
|
|
4479
4569
|
if (!def) return FormulaValue.errorName;
|
|
4480
4570
|
if (args.length < def.minArgs) return FormulaValue.errorValue;
|
|
4481
4571
|
if (def.maxArgs >= 0 && args.length > def.maxArgs) return FormulaValue.errorValue;
|
|
4482
4572
|
try {
|
|
4483
|
-
return def.handler(args, ctx);
|
|
4573
|
+
return def.elementwise ? __privateMethod(_a = _FunctionRegistry, _FunctionRegistry_static, executeElementwise_fn).call(_a, def, args, ctx) : def.handler(args, ctx);
|
|
4484
4574
|
} catch {
|
|
4485
4575
|
return FormulaValue.errorValue;
|
|
4486
4576
|
}
|
|
@@ -4496,6 +4586,42 @@ var _FunctionRegistry = class _FunctionRegistry {
|
|
|
4496
4586
|
};
|
|
4497
4587
|
_default = new WeakMap();
|
|
4498
4588
|
_functions = new WeakMap();
|
|
4589
|
+
_FunctionRegistry_static = new WeakSet();
|
|
4590
|
+
executeElementwise_fn = function(def, args, ctx) {
|
|
4591
|
+
const values = args.map((a) => a.evaluate(ctx));
|
|
4592
|
+
let rows2 = 1, cols = 1;
|
|
4593
|
+
for (const v of values) {
|
|
4594
|
+
if (!v.isArray) continue;
|
|
4595
|
+
const a = v.arrayVal;
|
|
4596
|
+
if (a.rows > rows2) rows2 = a.rows;
|
|
4597
|
+
if (a.columns > cols) cols = a.columns;
|
|
4598
|
+
}
|
|
4599
|
+
if (rows2 === 1 && cols === 1) {
|
|
4600
|
+
return def.handler(values.map((v) => new ValueNode(v.isArray ? v.arrayVal.get(0, 0) : v)), ctx);
|
|
4601
|
+
}
|
|
4602
|
+
if (rows2 * cols > MAX_LIFTED_CELLS) return FormulaValue.errorValue;
|
|
4603
|
+
for (const v of values) {
|
|
4604
|
+
if (!v.isArray) continue;
|
|
4605
|
+
const a = v.arrayVal;
|
|
4606
|
+
if (a.rows !== 1 && a.rows !== rows2 || a.columns !== 1 && a.columns !== cols) {
|
|
4607
|
+
return FormulaValue.errorValue;
|
|
4608
|
+
}
|
|
4609
|
+
}
|
|
4610
|
+
const nodes = values.map((v) => new ValueNode(v));
|
|
4611
|
+
const out = new ArrayValue(rows2, cols);
|
|
4612
|
+
for (let r = 0; r < rows2; r++) {
|
|
4613
|
+
for (let c = 0; c < cols; c++) {
|
|
4614
|
+
for (let i = 0; i < values.length; i++) {
|
|
4615
|
+
const v = values[i];
|
|
4616
|
+
if (!v.isArray) continue;
|
|
4617
|
+
const a = v.arrayVal;
|
|
4618
|
+
nodes[i].value = a.get(a.rows === 1 ? 0 : r, a.columns === 1 ? 0 : c);
|
|
4619
|
+
}
|
|
4620
|
+
out.set(r, c, def.handler(nodes, ctx));
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
return FormulaValue.array(out);
|
|
4624
|
+
};
|
|
4499
4625
|
_FunctionRegistry_instances = new WeakSet();
|
|
4500
4626
|
registerBuiltIns_fn = function() {
|
|
4501
4627
|
registerMath(this);
|
|
@@ -4510,6 +4636,7 @@ registerBuiltIns_fn = function() {
|
|
|
4510
4636
|
registerAggregate(this);
|
|
4511
4637
|
registerArray(this);
|
|
4512
4638
|
};
|
|
4639
|
+
__privateAdd(_FunctionRegistry, _FunctionRegistry_static);
|
|
4513
4640
|
__privateAdd(_FunctionRegistry, _default);
|
|
4514
4641
|
var FunctionRegistry = _FunctionRegistry;
|
|
4515
4642
|
exports.FormulaHelper = void 0;
|
|
@@ -5371,6 +5498,7 @@ function createWorkbookRecalcModel(workbook) {
|
|
|
5371
5498
|
getDefinedName: (name, sheet) => workbook.getDefinedName(name, sheet)
|
|
5372
5499
|
};
|
|
5373
5500
|
}
|
|
5501
|
+
var MAX_ADOPTED_SPILL_CELLS = 262144;
|
|
5374
5502
|
var normSheet = (s) => s.toUpperCase();
|
|
5375
5503
|
var normRef = (r) => r.replace(/\$/g, "").toUpperCase();
|
|
5376
5504
|
var keyOf = (sheet, ref) => `${normSheet(sheet)}!${normRef(ref)}`;
|
|
@@ -5381,7 +5509,7 @@ function parseKey(key) {
|
|
|
5381
5509
|
const { row: row2, column: column2 } = puredocsExcel.parseCellRef(ref);
|
|
5382
5510
|
return { sheet, ref, row: row2, col: column2 };
|
|
5383
5511
|
}
|
|
5384
|
-
var _model, _registry, _formulas, _sheetNames, _spills, _spillOwner, _dependents, _volatiles, _sheetLikes, _workbookLike, _rangeCache, _RecalcEngine_instances, writeCell_fn, register_fn, unregister_fn, rememberSheet_fn, recalcInOrder_fn, applyShift_fn, shiftPrecedents_fn, shiftSpillBookkeeping_fn, recalcFrom_fn, runFixpoint_fn, addVolatiles_fn, dependentClosure_fn, forEachDirectDependent_fn, evaluatePass_fn, writeResult_fn, isOccupied_fn, clearSpill_fn, evaluateFormulaValue_fn, sheetLike_fn, buildSheetLike_fn, buildWorkbookLike_fn;
|
|
5512
|
+
var _model, _registry, _formulas, _sheetNames, _spills, _spillOwner, _dependents, _volatiles, _sheetLikes, _workbookLike, _rangeCache, _RecalcEngine_instances, writeCell_fn, register_fn, unregister_fn, rememberSheet_fn, adoptDeclaredSpill_fn, recalcInOrder_fn, applyShift_fn, shiftPrecedents_fn, shiftSpillBookkeeping_fn, recalcFrom_fn, runFixpoint_fn, addVolatiles_fn, dependentClosure_fn, forEachDirectDependent_fn, evaluatePass_fn, writeResult_fn, isOccupied_fn, clearSpill_fn, evaluateFormulaValue_fn, sheetLike_fn, buildSheetLike_fn, buildWorkbookLike_fn;
|
|
5385
5513
|
var RecalcEngine = class {
|
|
5386
5514
|
constructor(model, registry = FunctionRegistry.default) {
|
|
5387
5515
|
__privateAdd(this, _RecalcEngine_instances);
|
|
@@ -5489,11 +5617,12 @@ var RecalcEngine = class {
|
|
|
5489
5617
|
const ast = parseFormulaUncached(text);
|
|
5490
5618
|
const { refs, volatile } = extractReferences(ast, s, __privateGet(this, _registry), resolveName2);
|
|
5491
5619
|
__privateMethod(this, _RecalcEngine_instances, rememberSheet_fn).call(this, sheet);
|
|
5620
|
+
const key = keyOf(s, r);
|
|
5492
5621
|
__privateMethod(this, _RecalcEngine_instances, register_fn).call(this, {
|
|
5493
5622
|
sheet: s,
|
|
5494
5623
|
sheetName: sheet,
|
|
5495
5624
|
ref: r,
|
|
5496
|
-
key
|
|
5625
|
+
key,
|
|
5497
5626
|
row: row2,
|
|
5498
5627
|
col: column2,
|
|
5499
5628
|
formula: text,
|
|
@@ -5501,6 +5630,7 @@ var RecalcEngine = class {
|
|
|
5501
5630
|
refs,
|
|
5502
5631
|
volatile
|
|
5503
5632
|
});
|
|
5633
|
+
__privateMethod(this, _RecalcEngine_instances, adoptDeclaredSpill_fn).call(this, s, sheet, r, key, row2, column2);
|
|
5504
5634
|
registered++;
|
|
5505
5635
|
} catch (err) {
|
|
5506
5636
|
failed.push({ sheet, ref, error: err instanceof Error ? err.message : String(err) });
|
|
@@ -5668,6 +5798,51 @@ unregister_fn = function(key) {
|
|
|
5668
5798
|
rememberSheet_fn = function(name) {
|
|
5669
5799
|
__privateGet(this, _sheetNames).set(normSheet(name), name);
|
|
5670
5800
|
};
|
|
5801
|
+
/**
|
|
5802
|
+
* Takes ownership of the spill block a *file* already declared for an anchor.
|
|
5803
|
+
*
|
|
5804
|
+
* Excel stores a dynamic array as one formula on the anchor plus the spilled
|
|
5805
|
+
* results written as plain cached values in the cells below/right, and records
|
|
5806
|
+
* the extent in the anchor's `<f t="array" ref="…">`. Without this step the
|
|
5807
|
+
* engine meets those cached values on the first recalculation, sees literal
|
|
5808
|
+
* content inside the block it wants to spill into, and reports `#SPILL!` for
|
|
5809
|
+
* every dynamic array in every real file. Registering the declared block as
|
|
5810
|
+
* this anchor's existing spill makes them what they actually are — the anchor's
|
|
5811
|
+
* own territory, free to overwrite — and reuses the ordinary shrink path, so a
|
|
5812
|
+
* result smaller than the declared block clears the leftovers.
|
|
5813
|
+
*
|
|
5814
|
+
* Cost is one Set entry per already-spilled cell, paid once at load. A declared
|
|
5815
|
+
* block far larger than any real spill (a corrupt or hand-written `ref`) is
|
|
5816
|
+
* skipped rather than materialised.
|
|
5817
|
+
*/
|
|
5818
|
+
adoptDeclaredSpill_fn = function(s, sheetName, ref, anchorKey, row2, col) {
|
|
5819
|
+
const declared = __privateGet(this, _model).getSpillRange?.(sheetName, ref);
|
|
5820
|
+
if (!declared || !declared.includes(":")) return;
|
|
5821
|
+
let rect;
|
|
5822
|
+
try {
|
|
5823
|
+
rect = puredocsExcel.parseRangeRef(declared);
|
|
5824
|
+
} catch {
|
|
5825
|
+
return;
|
|
5826
|
+
}
|
|
5827
|
+
if (rect.startRow !== row2 || rect.startColumn !== col) return;
|
|
5828
|
+
const height = rect.endRow - rect.startRow + 1;
|
|
5829
|
+
const width = rect.endColumn - rect.startColumn + 1;
|
|
5830
|
+
if (height < 1 || width < 1) return;
|
|
5831
|
+
if (height * width > MAX_ADOPTED_SPILL_CELLS) return;
|
|
5832
|
+
if (height === 1 && width === 1) return;
|
|
5833
|
+
const members = /* @__PURE__ */ new Set();
|
|
5834
|
+
for (let r = rect.startRow; r <= rect.endRow; r++) {
|
|
5835
|
+
for (let c = rect.startColumn; c <= rect.endColumn; c++) {
|
|
5836
|
+
if (r === row2 && c === col) continue;
|
|
5837
|
+
const key = keyOf(s, puredocsExcel.cellRefFromRowCol(r, c));
|
|
5838
|
+
if (__privateGet(this, _formulas).has(key)) continue;
|
|
5839
|
+
if (__privateGet(this, _spillOwner).has(key)) continue;
|
|
5840
|
+
members.add(key);
|
|
5841
|
+
__privateGet(this, _spillOwner).set(key, anchorKey);
|
|
5842
|
+
}
|
|
5843
|
+
}
|
|
5844
|
+
if (members.size > 0) __privateGet(this, _spills).set(anchorKey, members);
|
|
5845
|
+
};
|
|
5671
5846
|
/**
|
|
5672
5847
|
* One pass in a caller-supplied order, watching for inversions.
|
|
5673
5848
|
*
|