@devmm/puredocs-excel-formula 1.0.0

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.js ADDED
@@ -0,0 +1,2905 @@
1
+ import { toOADate, fromOADate, parseCellRef, cellRefFromRowCol } from '@devmm/puredocs-excel';
2
+
3
+ var __typeError = (msg) => {
4
+ throw TypeError(msg);
5
+ };
6
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
7
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
8
+ var __privateAdd = (obj, member, value2) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value2);
9
+ var __privateSet = (obj, member, value2, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value2), value2);
10
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
11
+ var __privateWrapper = (obj, member, setter, getter) => ({
12
+ set _(value2) {
13
+ __privateSet(obj, member, value2);
14
+ },
15
+ get _() {
16
+ return __privateGet(obj, member, getter);
17
+ }
18
+ });
19
+ var FormulaError = /* @__PURE__ */ ((FormulaError2) => {
20
+ FormulaError2[FormulaError2["None"] = 0] = "None";
21
+ FormulaError2[FormulaError2["Null"] = 1] = "Null";
22
+ FormulaError2[FormulaError2["Div0"] = 2] = "Div0";
23
+ FormulaError2[FormulaError2["Value"] = 3] = "Value";
24
+ FormulaError2[FormulaError2["Ref"] = 4] = "Ref";
25
+ FormulaError2[FormulaError2["Name"] = 5] = "Name";
26
+ FormulaError2[FormulaError2["Num"] = 6] = "Num";
27
+ FormulaError2[FormulaError2["NA"] = 7] = "NA";
28
+ FormulaError2[FormulaError2["Calc"] = 8] = "Calc";
29
+ FormulaError2[FormulaError2["Spill"] = 9] = "Spill";
30
+ return FormulaError2;
31
+ })(FormulaError || {});
32
+ var _num, _obj;
33
+ var _FormulaValue = class _FormulaValue {
34
+ constructor(kind, num4 = 0, obj, errorCode = 0 /* None */) {
35
+ /** Numeric payload (also used for boolean: 1=true, 0=false). */
36
+ __privateAdd(this, _num);
37
+ /** String or ArrayValue payload. */
38
+ __privateAdd(this, _obj);
39
+ this.kind = kind;
40
+ __privateSet(this, _num, num4);
41
+ __privateSet(this, _obj, obj);
42
+ this.errorCode = errorCode;
43
+ }
44
+ // ── Static factories ─────────────────────────────────────────────────────
45
+ static number(v) {
46
+ if (v === 0) return _FormulaValue.zero;
47
+ if (v === 1) return _FormulaValue.one;
48
+ return new _FormulaValue("number", v);
49
+ }
50
+ static text(v) {
51
+ if (v === "") return _FormulaValue.emptyString;
52
+ return new _FormulaValue("text", 0, v);
53
+ }
54
+ static boolean(v) {
55
+ return v ? _FormulaValue.true_ : _FormulaValue.false_;
56
+ }
57
+ static error(e) {
58
+ switch (e) {
59
+ case 2 /* Div0 */:
60
+ return _FormulaValue.errorDiv0;
61
+ case 3 /* Value */:
62
+ return _FormulaValue.errorValue;
63
+ case 4 /* Ref */:
64
+ return _FormulaValue.errorRef;
65
+ case 5 /* Name */:
66
+ return _FormulaValue.errorName;
67
+ case 7 /* NA */:
68
+ return _FormulaValue.errorNA;
69
+ case 6 /* Num */:
70
+ return _FormulaValue.errorNum;
71
+ case 1 /* Null */:
72
+ return _FormulaValue.errorNull;
73
+ default:
74
+ return new _FormulaValue("error", 0, void 0, e);
75
+ }
76
+ }
77
+ static array(a) {
78
+ return new _FormulaValue("array", 0, a);
79
+ }
80
+ // ── Type checks ──────────────────────────────────────────────────────────
81
+ get isBlank() {
82
+ return this.kind === "blank";
83
+ }
84
+ get isNumber() {
85
+ return this.kind === "number";
86
+ }
87
+ get isText() {
88
+ return this.kind === "text";
89
+ }
90
+ get isBoolean() {
91
+ return this.kind === "boolean";
92
+ }
93
+ get isError() {
94
+ return this.kind === "error";
95
+ }
96
+ get isArray() {
97
+ return this.kind === "array";
98
+ }
99
+ get isNumeric() {
100
+ return this.kind === "number" || this.kind === "boolean" || this.kind === "blank";
101
+ }
102
+ // ── Value accessors ──────────────────────────────────────────────────────
103
+ get numberValue() {
104
+ return __privateGet(this, _num);
105
+ }
106
+ get textValue() {
107
+ return __privateGet(this, _obj) ?? "";
108
+ }
109
+ get booleanValue() {
110
+ return __privateGet(this, _num) !== 0;
111
+ }
112
+ get arrayVal() {
113
+ return __privateGet(this, _obj) ?? ArrayValue.empty;
114
+ }
115
+ // ── Coercion (Excel semantics, no exceptions) ─────────────────────────────
116
+ coerceToNumber() {
117
+ switch (this.kind) {
118
+ case "number":
119
+ return this;
120
+ case "blank":
121
+ return _FormulaValue.zero;
122
+ case "boolean":
123
+ return _FormulaValue.number(__privateGet(this, _num));
124
+ case "error":
125
+ return this;
126
+ case "text": {
127
+ const n = parseFloat(this.textValue);
128
+ return isNaN(n) ? _FormulaValue.errorValue : _FormulaValue.number(n);
129
+ }
130
+ default:
131
+ return _FormulaValue.errorValue;
132
+ }
133
+ }
134
+ tryAsDouble() {
135
+ switch (this.kind) {
136
+ case "number":
137
+ return { ok: true, value: __privateGet(this, _num) };
138
+ case "blank":
139
+ return { ok: true, value: 0 };
140
+ case "boolean":
141
+ return { ok: true, value: __privateGet(this, _num) };
142
+ case "text": {
143
+ const n = parseFloat(this.textValue);
144
+ return isNaN(n) ? { ok: false } : { ok: true, value: n };
145
+ }
146
+ default:
147
+ return { ok: false };
148
+ }
149
+ }
150
+ coerceToBool() {
151
+ switch (this.kind) {
152
+ case "boolean":
153
+ return this;
154
+ case "number":
155
+ return _FormulaValue.boolean(__privateGet(this, _num) !== 0);
156
+ case "blank":
157
+ return _FormulaValue.false_;
158
+ case "error":
159
+ return this;
160
+ case "text": {
161
+ const u = this.textValue.toUpperCase();
162
+ if (u === "TRUE") return _FormulaValue.true_;
163
+ if (u === "FALSE") return _FormulaValue.false_;
164
+ return _FormulaValue.errorValue;
165
+ }
166
+ default:
167
+ return _FormulaValue.errorValue;
168
+ }
169
+ }
170
+ asText() {
171
+ switch (this.kind) {
172
+ case "text":
173
+ return this.textValue;
174
+ case "number":
175
+ return String(__privateGet(this, _num));
176
+ case "boolean":
177
+ return __privateGet(this, _num) !== 0 ? "TRUE" : "FALSE";
178
+ case "blank":
179
+ return "";
180
+ case "error":
181
+ return _FormulaValue.errorToString(this.errorCode);
182
+ default:
183
+ return "";
184
+ }
185
+ }
186
+ // ── Comparison (Excel semantics) ─────────────────────────────────────────
187
+ static areEqual(a, b) {
188
+ if (a.isBlank && b.isBlank) return true;
189
+ if (a.isBlank) {
190
+ if (b.isNumber) return Math.abs(b.numberValue) < 1e-10;
191
+ if (b.isText) return b.textValue === "";
192
+ if (b.isBoolean) return !b.booleanValue;
193
+ return false;
194
+ }
195
+ if (b.isBlank) return _FormulaValue.areEqual(b, a);
196
+ if (a.kind !== b.kind) return false;
197
+ switch (a.kind) {
198
+ case "number":
199
+ return Math.abs(__privateGet(a, _num) - __privateGet(b, _num)) < 1e-10;
200
+ case "boolean":
201
+ return __privateGet(a, _num) === __privateGet(b, _num);
202
+ case "text":
203
+ return a.textValue.toUpperCase() === b.textValue.toUpperCase();
204
+ default:
205
+ return false;
206
+ }
207
+ }
208
+ /** Excel-compatible sort order: Number/Blank < Text < Boolean. */
209
+ static compare(a, b) {
210
+ const order = (v) => v.kind === "boolean" ? 2 : v.isText ? 1 : 0;
211
+ const oa = order(a), ob = order(b);
212
+ if (oa !== ob) return oa - ob;
213
+ switch (oa) {
214
+ case 0:
215
+ return (a.isBlank ? 0 : a.numberValue) - (b.isBlank ? 0 : b.numberValue);
216
+ case 1:
217
+ return a.textValue.toUpperCase() < b.textValue.toUpperCase() ? -1 : a.textValue.toUpperCase() > b.textValue.toUpperCase() ? 1 : 0;
218
+ case 2:
219
+ return __privateGet(a, _num) - __privateGet(b, _num);
220
+ default:
221
+ return 0;
222
+ }
223
+ }
224
+ // ── Error helpers ─────────────────────────────────────────────────────────
225
+ static errorToString(e) {
226
+ const map = {
227
+ [0 /* None */]: "",
228
+ [1 /* Null */]: "#NULL!",
229
+ [2 /* Div0 */]: "#DIV/0!",
230
+ [3 /* Value */]: "#VALUE!",
231
+ [4 /* Ref */]: "#REF!",
232
+ [5 /* Name */]: "#NAME?",
233
+ [6 /* Num */]: "#NUM!",
234
+ [7 /* NA */]: "#N/A",
235
+ [8 /* Calc */]: "#CALC!",
236
+ [9 /* Spill */]: "#SPILL!"
237
+ };
238
+ return map[e] ?? "#ERROR!";
239
+ }
240
+ static errorFromString(s) {
241
+ const map = {
242
+ "#NULL!": 1 /* Null */,
243
+ "#DIV/0!": 2 /* Div0 */,
244
+ "#VALUE!": 3 /* Value */,
245
+ "#REF!": 4 /* Ref */,
246
+ "#NAME?": 5 /* Name */,
247
+ "#NUM!": 6 /* Num */,
248
+ "#N/A": 7 /* NA */,
249
+ "#CALC!": 8 /* Calc */,
250
+ "#SPILL!": 9 /* Spill */
251
+ };
252
+ return map[s] ?? 3 /* Value */;
253
+ }
254
+ // ── JS interop ────────────────────────────────────────────────────────────
255
+ static fromObjectSync(value2) {
256
+ if (value2 === null || value2 === void 0) return _FormulaValue.blank;
257
+ if (typeof value2 === "number") return isNaN(value2) ? _FormulaValue.errorValue : _FormulaValue.number(value2);
258
+ if (typeof value2 === "boolean") return _FormulaValue.boolean(value2);
259
+ if (typeof value2 === "string") return value2 === "" ? _FormulaValue.blank : _FormulaValue.text(value2);
260
+ if (value2 instanceof Date) {
261
+ return _FormulaValue.number(toOADate(value2));
262
+ }
263
+ return _FormulaValue.text(String(value2));
264
+ }
265
+ toObject() {
266
+ switch (this.kind) {
267
+ case "number":
268
+ return __privateGet(this, _num);
269
+ case "text":
270
+ return this.textValue;
271
+ case "boolean":
272
+ return this.booleanValue;
273
+ case "blank":
274
+ return null;
275
+ case "error":
276
+ return _FormulaValue.errorToString(this.errorCode);
277
+ case "array":
278
+ return this.arrayVal.toObjectArray();
279
+ default:
280
+ return null;
281
+ }
282
+ }
283
+ toString() {
284
+ return this.asText();
285
+ }
286
+ };
287
+ _num = new WeakMap();
288
+ _obj = new WeakMap();
289
+ // ── Cached singletons ────────────────────────────────────────────────────
290
+ _FormulaValue.blank = new _FormulaValue("blank");
291
+ _FormulaValue.zero = new _FormulaValue("number", 0);
292
+ _FormulaValue.one = new _FormulaValue("number", 1);
293
+ _FormulaValue.true_ = new _FormulaValue("boolean", 1);
294
+ _FormulaValue.false_ = new _FormulaValue("boolean", 0);
295
+ _FormulaValue.emptyString = new _FormulaValue("text", 0, "");
296
+ _FormulaValue.errorDiv0 = new _FormulaValue("error", 0, void 0, 2 /* Div0 */);
297
+ _FormulaValue.errorValue = new _FormulaValue("error", 0, void 0, 3 /* Value */);
298
+ _FormulaValue.errorRef = new _FormulaValue("error", 0, void 0, 4 /* Ref */);
299
+ _FormulaValue.errorName = new _FormulaValue("error", 0, void 0, 5 /* Name */);
300
+ _FormulaValue.errorNA = new _FormulaValue("error", 0, void 0, 7 /* NA */);
301
+ _FormulaValue.errorNum = new _FormulaValue("error", 0, void 0, 6 /* Num */);
302
+ _FormulaValue.errorNull = new _FormulaValue("error", 0, void 0, 1 /* Null */);
303
+ var FormulaValue = _FormulaValue;
304
+ var _data;
305
+ var _ArrayValue = class _ArrayValue {
306
+ constructor(rows2, columns2) {
307
+ __privateAdd(this, _data);
308
+ this.rows = rows2;
309
+ this.columns = columns2;
310
+ __privateSet(this, _data, new Array(rows2 * columns2).fill(FormulaValue.blank));
311
+ }
312
+ get length() {
313
+ return __privateGet(this, _data).length;
314
+ }
315
+ get(row2, col) {
316
+ if (row2 < 0 || row2 >= this.rows || col < 0 || col >= this.columns) {
317
+ return FormulaValue.errorRef;
318
+ }
319
+ return __privateGet(this, _data)[row2 * this.columns + col];
320
+ }
321
+ set(row2, col, value2) {
322
+ if (row2 >= 0 && row2 < this.rows && col >= 0 && col < this.columns) {
323
+ __privateGet(this, _data)[row2 * this.columns + col] = value2;
324
+ }
325
+ }
326
+ getFlat(index) {
327
+ return index >= 0 && index < __privateGet(this, _data).length ? __privateGet(this, _data)[index] : FormulaValue.errorRef;
328
+ }
329
+ setFlat(index, value2) {
330
+ if (index >= 0 && index < __privateGet(this, _data).length) {
331
+ __privateGet(this, _data)[index] = value2;
332
+ }
333
+ }
334
+ /** Iterate all values in row-major order. */
335
+ values() {
336
+ return __privateGet(this, _data);
337
+ }
338
+ toObjectArray() {
339
+ return __privateGet(this, _data).map((v) => v.toObject());
340
+ }
341
+ /** Create from a flat array (single column). */
342
+ static fromFlat(values) {
343
+ const arr = new _ArrayValue(values.length, 1);
344
+ values.forEach((v, i) => arr.setFlat(i, v));
345
+ return arr;
346
+ }
347
+ /** Create a 1×1 array wrapping a scalar value (for broadcasting). */
348
+ static fromScalar(value2) {
349
+ const arr = new _ArrayValue(1, 1);
350
+ arr.setFlat(0, value2);
351
+ return arr;
352
+ }
353
+ /** Element-wise broadcasting operation (mirrors ArrayValue.Broadcast in C#). */
354
+ static broadcast(a, b, op) {
355
+ const rows2 = Math.max(a.rows, b.rows);
356
+ const cols = Math.max(a.columns, b.columns);
357
+ if (a.rows !== 1 && b.rows !== 1 && a.rows !== b.rows || a.columns !== 1 && b.columns !== 1 && a.columns !== b.columns) {
358
+ const err = new _ArrayValue(rows2, cols);
359
+ for (let i = 0; i < err.length; i++) err.setFlat(i, FormulaValue.errorValue);
360
+ return err;
361
+ }
362
+ const result = new _ArrayValue(rows2, cols);
363
+ for (let r = 0; r < rows2; r++) {
364
+ for (let c = 0; c < cols; c++) {
365
+ const av = a.get(r < a.rows ? r : 0, c < a.columns ? c : 0);
366
+ const bv = b.get(r < b.rows ? r : 0, c < b.columns ? c : 0);
367
+ result.set(r, c, op(av, bv));
368
+ }
369
+ }
370
+ return result;
371
+ }
372
+ /** Implicit intersection: reduce array to scalar based on formula position. */
373
+ implicitIntersect(formulaRow, formulaCol, rangeStartRow, rangeStartCol) {
374
+ if (this.rows === 1 && this.columns === 1) return this.get(0, 0);
375
+ if (this.columns === 1) {
376
+ const offset2 = formulaRow - rangeStartRow;
377
+ return offset2 >= 0 && offset2 < this.rows ? this.get(offset2, 0) : FormulaValue.errorValue;
378
+ }
379
+ if (this.rows === 1) {
380
+ const offset2 = formulaCol - rangeStartCol;
381
+ return offset2 >= 0 && offset2 < this.columns ? this.get(0, offset2) : FormulaValue.errorValue;
382
+ }
383
+ const ro = formulaRow - rangeStartRow;
384
+ const co = formulaCol - rangeStartCol;
385
+ return ro >= 0 && ro < this.rows && co >= 0 && co < this.columns ? this.get(ro, co) : FormulaValue.errorValue;
386
+ }
387
+ transpose() {
388
+ const result = new _ArrayValue(this.columns, this.rows);
389
+ for (let r = 0; r < this.rows; r++) {
390
+ for (let c = 0; c < this.columns; c++) {
391
+ result.set(c, r, this.get(r, c));
392
+ }
393
+ }
394
+ return result;
395
+ }
396
+ };
397
+ _data = new WeakMap();
398
+ _ArrayValue.empty = new _ArrayValue(0, 0);
399
+ var ArrayValue = _ArrayValue;
400
+
401
+ // src/formula-token.ts
402
+ var TokenType = /* @__PURE__ */ ((TokenType2) => {
403
+ TokenType2[TokenType2["Number"] = 0] = "Number";
404
+ TokenType2[TokenType2["String"] = 1] = "String";
405
+ TokenType2[TokenType2["Boolean"] = 2] = "Boolean";
406
+ TokenType2[TokenType2["CellReference"] = 3] = "CellReference";
407
+ TokenType2[TokenType2["Colon"] = 4] = "Colon";
408
+ TokenType2[TokenType2["Function"] = 5] = "Function";
409
+ TokenType2[TokenType2["LeftParen"] = 6] = "LeftParen";
410
+ TokenType2[TokenType2["RightParen"] = 7] = "RightParen";
411
+ TokenType2[TokenType2["Comma"] = 8] = "Comma";
412
+ TokenType2[TokenType2["Plus"] = 9] = "Plus";
413
+ TokenType2[TokenType2["Minus"] = 10] = "Minus";
414
+ TokenType2[TokenType2["Multiply"] = 11] = "Multiply";
415
+ TokenType2[TokenType2["Divide"] = 12] = "Divide";
416
+ TokenType2[TokenType2["Power"] = 13] = "Power";
417
+ TokenType2[TokenType2["Percent"] = 14] = "Percent";
418
+ TokenType2[TokenType2["Ampersand"] = 15] = "Ampersand";
419
+ TokenType2[TokenType2["Equal"] = 16] = "Equal";
420
+ TokenType2[TokenType2["NotEqual"] = 17] = "NotEqual";
421
+ TokenType2[TokenType2["LessThan"] = 18] = "LessThan";
422
+ TokenType2[TokenType2["LessThanOrEqual"] = 19] = "LessThanOrEqual";
423
+ TokenType2[TokenType2["GreaterThan"] = 20] = "GreaterThan";
424
+ TokenType2[TokenType2["GreaterThanOrEqual"] = 21] = "GreaterThanOrEqual";
425
+ TokenType2[TokenType2["SheetReference"] = 22] = "SheetReference";
426
+ TokenType2[TokenType2["NamedRange"] = 23] = "NamedRange";
427
+ TokenType2[TokenType2["Exclamation"] = 24] = "Exclamation";
428
+ TokenType2[TokenType2["AtSign"] = 25] = "AtSign";
429
+ TokenType2[TokenType2["ErrorLiteral"] = 26] = "ErrorLiteral";
430
+ TokenType2[TokenType2["EOF"] = 27] = "EOF";
431
+ return TokenType2;
432
+ })(TokenType || {});
433
+ function makeToken(type, value2, position) {
434
+ return { type, value: value2, position };
435
+ }
436
+
437
+ // src/formula-lexer.ts
438
+ var FormulaException = class extends Error {
439
+ constructor(message) {
440
+ super(message);
441
+ this.name = "FormulaException";
442
+ }
443
+ };
444
+ var KNOWN_ERRORS = /* @__PURE__ */ new Set([
445
+ "#NULL!",
446
+ "#DIV/0!",
447
+ "#VALUE!",
448
+ "#REF!",
449
+ "#NAME?",
450
+ "#NUM!",
451
+ "#N/A",
452
+ "#CALC!",
453
+ "#SPILL!"
454
+ ]);
455
+ var _formula, _pos, _FormulaLexer_instances, readNextToken_fn, readString_fn, readErrorLiteral_fn, readQuotedSheetRef_fn, readNumber_fn, readIdentifier_fn, readCellRefChars_fn, readOperator_fn, skipWhitespace_fn;
456
+ var FormulaLexer = class {
457
+ constructor(formula) {
458
+ __privateAdd(this, _FormulaLexer_instances);
459
+ __privateAdd(this, _formula);
460
+ __privateAdd(this, _pos, 0);
461
+ if (!formula) throw new FormulaException("Formula cannot be empty.");
462
+ __privateSet(this, _formula, formula);
463
+ }
464
+ tokenize() {
465
+ __privateSet(this, _pos, 0);
466
+ const tokens = [];
467
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length) {
468
+ __privateMethod(this, _FormulaLexer_instances, skipWhitespace_fn).call(this);
469
+ if (__privateGet(this, _pos) >= __privateGet(this, _formula).length) break;
470
+ const token = __privateMethod(this, _FormulaLexer_instances, readNextToken_fn).call(this);
471
+ if (token) tokens.push(token);
472
+ }
473
+ tokens.push(makeToken(27 /* EOF */, "", __privateGet(this, _pos)));
474
+ return tokens;
475
+ }
476
+ };
477
+ _formula = new WeakMap();
478
+ _pos = new WeakMap();
479
+ _FormulaLexer_instances = new WeakSet();
480
+ // ── Private tokenisers ─────────────────────────────────────────────────────
481
+ readNextToken_fn = function() {
482
+ const c = __privateGet(this, _formula)[__privateGet(this, _pos)];
483
+ if (c === '"') return __privateMethod(this, _FormulaLexer_instances, readString_fn).call(this);
484
+ if (c === "#") return __privateMethod(this, _FormulaLexer_instances, readErrorLiteral_fn).call(this);
485
+ if (c === "'") return __privateMethod(this, _FormulaLexer_instances, readQuotedSheetRef_fn).call(this);
486
+ if (c === "." && __privateGet(this, _pos) + 1 < __privateGet(this, _formula).length && /\d/.test(__privateGet(this, _formula)[__privateGet(this, _pos) + 1])) {
487
+ return __privateMethod(this, _FormulaLexer_instances, readNumber_fn).call(this);
488
+ }
489
+ if (/\d/.test(c)) return __privateMethod(this, _FormulaLexer_instances, readNumber_fn).call(this);
490
+ if (/[a-zA-Z_$]/.test(c)) return __privateMethod(this, _FormulaLexer_instances, readIdentifier_fn).call(this);
491
+ return __privateMethod(this, _FormulaLexer_instances, readOperator_fn).call(this);
492
+ };
493
+ readString_fn = function() {
494
+ const start = __privateWrapper(this, _pos)._++;
495
+ let value2 = "";
496
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length) {
497
+ const ch = __privateGet(this, _formula)[__privateGet(this, _pos)];
498
+ if (ch === '"') {
499
+ __privateWrapper(this, _pos)._++;
500
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === '"') {
501
+ value2 += '"';
502
+ __privateWrapper(this, _pos)._++;
503
+ } else return makeToken(1 /* String */, value2, start);
504
+ } else {
505
+ value2 += ch;
506
+ __privateWrapper(this, _pos)._++;
507
+ }
508
+ }
509
+ throw new FormulaException(`Unterminated string at position ${start}.`);
510
+ };
511
+ readErrorLiteral_fn = function() {
512
+ const start = __privateGet(this, _pos);
513
+ let raw = "#";
514
+ __privateWrapper(this, _pos)._++;
515
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length) {
516
+ const ch = __privateGet(this, _formula)[__privateGet(this, _pos)];
517
+ if (/[a-zA-Z0-9/]/.test(ch) || ch === "!" || ch === "?") {
518
+ raw += ch;
519
+ __privateWrapper(this, _pos)._++;
520
+ if (ch === "!" || ch === "?") break;
521
+ } else break;
522
+ }
523
+ const upper2 = raw.toUpperCase();
524
+ if (!KNOWN_ERRORS.has(upper2)) {
525
+ throw new FormulaException(`Unknown error literal "${raw}" at position ${start}.`);
526
+ }
527
+ return makeToken(26 /* ErrorLiteral */, upper2, start);
528
+ };
529
+ readQuotedSheetRef_fn = function() {
530
+ const start = __privateWrapper(this, _pos)._++;
531
+ let sheetName = "";
532
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length) {
533
+ const ch = __privateGet(this, _formula)[__privateGet(this, _pos)];
534
+ if (ch === "'") {
535
+ __privateWrapper(this, _pos)._++;
536
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === "'") {
537
+ sheetName += "'";
538
+ __privateWrapper(this, _pos)._++;
539
+ } else {
540
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] !== "!") {
541
+ throw new FormulaException(`Expected '!' after quoted sheet name at position ${start}.`);
542
+ }
543
+ __privateWrapper(this, _pos)._++;
544
+ const cellRef = __privateMethod(this, _FormulaLexer_instances, readCellRefChars_fn).call(this);
545
+ return makeToken(22 /* SheetReference */, `${sheetName}!${cellRef}`, start);
546
+ }
547
+ } else {
548
+ sheetName += ch;
549
+ __privateWrapper(this, _pos)._++;
550
+ }
551
+ }
552
+ throw new FormulaException(`Unterminated quoted sheet name at position ${start}.`);
553
+ };
554
+ readNumber_fn = function() {
555
+ const start = __privateGet(this, _pos);
556
+ let raw = "";
557
+ let hasDot = false;
558
+ let hasE = false;
559
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length) {
560
+ const ch = __privateGet(this, _formula)[__privateGet(this, _pos)];
561
+ if (/\d/.test(ch)) {
562
+ raw += ch;
563
+ __privateWrapper(this, _pos)._++;
564
+ } else if (ch === "." && !hasDot && !hasE) {
565
+ hasDot = true;
566
+ raw += ch;
567
+ __privateWrapper(this, _pos)._++;
568
+ } else if ((ch === "e" || ch === "E") && !hasE && raw.length > 0) {
569
+ hasE = true;
570
+ raw += ch;
571
+ __privateWrapper(this, _pos)._++;
572
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === "+" || __privateGet(this, _formula)[__privateGet(this, _pos)] === "-") {
573
+ raw += __privateGet(this, _formula)[__privateWrapper(this, _pos)._++];
574
+ }
575
+ } else break;
576
+ }
577
+ return makeToken(0 /* Number */, raw, start);
578
+ };
579
+ readIdentifier_fn = function() {
580
+ const start = __privateGet(this, _pos);
581
+ let raw = "";
582
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length) {
583
+ const ch = __privateGet(this, _formula)[__privateGet(this, _pos)];
584
+ if (/[a-zA-Z0-9_$.]/.test(ch)) {
585
+ raw += ch;
586
+ __privateWrapper(this, _pos)._++;
587
+ } else break;
588
+ }
589
+ let upper2 = raw.toUpperCase();
590
+ if (upper2.startsWith("_XLFN.")) {
591
+ raw = raw.slice(6);
592
+ upper2 = upper2.slice(6);
593
+ }
594
+ if (upper2 === "TRUE") return makeToken(2 /* Boolean */, "TRUE", start);
595
+ if (upper2 === "FALSE") return makeToken(2 /* Boolean */, "FALSE", start);
596
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === "!") {
597
+ __privateWrapper(this, _pos)._++;
598
+ const cellRef = __privateMethod(this, _FormulaLexer_instances, readCellRefChars_fn).call(this);
599
+ return makeToken(22 /* SheetReference */, `${raw}!${cellRef}`, start);
600
+ }
601
+ __privateMethod(this, _FormulaLexer_instances, skipWhitespace_fn).call(this);
602
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === "(") {
603
+ return makeToken(5 /* Function */, upper2, start);
604
+ }
605
+ const stripped = raw.replace(/\$/g, "");
606
+ if (isCellRef(stripped)) return makeToken(3 /* CellReference */, stripped, start);
607
+ return makeToken(23 /* NamedRange */, raw, start);
608
+ };
609
+ readCellRefChars_fn = function() {
610
+ let ref = "";
611
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length) {
612
+ const ch = __privateGet(this, _formula)[__privateGet(this, _pos)];
613
+ if (/[a-zA-Z0-9$]/.test(ch)) {
614
+ ref += ch;
615
+ __privateWrapper(this, _pos)._++;
616
+ } else break;
617
+ }
618
+ return ref.replace(/\$/g, "");
619
+ };
620
+ readOperator_fn = function() {
621
+ const start = __privateGet(this, _pos);
622
+ const ch = __privateGet(this, _formula)[__privateWrapper(this, _pos)._++];
623
+ switch (ch) {
624
+ case "(":
625
+ return makeToken(6 /* LeftParen */, "(", start);
626
+ case ")":
627
+ return makeToken(7 /* RightParen */, ")", start);
628
+ case ",":
629
+ return makeToken(8 /* Comma */, ",", start);
630
+ case ":":
631
+ return makeToken(4 /* Colon */, ":", start);
632
+ case "+":
633
+ return makeToken(9 /* Plus */, "+", start);
634
+ case "-":
635
+ return makeToken(10 /* Minus */, "-", start);
636
+ case "*":
637
+ return makeToken(11 /* Multiply */, "*", start);
638
+ case "/":
639
+ return makeToken(12 /* Divide */, "/", start);
640
+ case "^":
641
+ return makeToken(13 /* Power */, "^", start);
642
+ case "%":
643
+ return makeToken(14 /* Percent */, "%", start);
644
+ case "&":
645
+ return makeToken(15 /* Ampersand */, "&", start);
646
+ case "=":
647
+ return makeToken(16 /* Equal */, "=", start);
648
+ case "@":
649
+ return makeToken(25 /* AtSign */, "@", start);
650
+ case "!":
651
+ return makeToken(24 /* Exclamation */, "!", start);
652
+ case "<":
653
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === ">") {
654
+ __privateWrapper(this, _pos)._++;
655
+ return makeToken(17 /* NotEqual */, "<>", start);
656
+ }
657
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === "=") {
658
+ __privateWrapper(this, _pos)._++;
659
+ return makeToken(19 /* LessThanOrEqual */, "<=", start);
660
+ }
661
+ return makeToken(18 /* LessThan */, "<", start);
662
+ case ">":
663
+ if (__privateGet(this, _formula)[__privateGet(this, _pos)] === "=") {
664
+ __privateWrapper(this, _pos)._++;
665
+ return makeToken(21 /* GreaterThanOrEqual */, ">=", start);
666
+ }
667
+ return makeToken(20 /* GreaterThan */, ">", start);
668
+ default:
669
+ throw new FormulaException(`Unexpected character '${ch}' at position ${start}.`);
670
+ }
671
+ };
672
+ skipWhitespace_fn = function() {
673
+ while (__privateGet(this, _pos) < __privateGet(this, _formula).length && /\s/.test(__privateGet(this, _formula)[__privateGet(this, _pos)])) {
674
+ __privateWrapper(this, _pos)._++;
675
+ }
676
+ };
677
+ function isCellRef(s) {
678
+ if (s.length < 2) return false;
679
+ let i = 0;
680
+ while (i < s.length && /[a-zA-Z]/.test(s[i])) i++;
681
+ if (i === 0 || i >= s.length) return false;
682
+ while (i < s.length && /\d/.test(s[i])) i++;
683
+ return i === s.length;
684
+ }
685
+
686
+ // src/formula-node.ts
687
+ var FormulaNode = class {
688
+ };
689
+ var NumberNode = class extends FormulaNode {
690
+ constructor(value2) {
691
+ super();
692
+ this.value = value2;
693
+ }
694
+ evaluate() {
695
+ return FormulaValue.number(this.value);
696
+ }
697
+ };
698
+ var StringNode = class extends FormulaNode {
699
+ constructor(value2) {
700
+ super();
701
+ this.value = value2;
702
+ }
703
+ evaluate() {
704
+ return FormulaValue.text(this.value);
705
+ }
706
+ };
707
+ var BooleanNode = class extends FormulaNode {
708
+ constructor(value2) {
709
+ super();
710
+ this.value = value2;
711
+ }
712
+ evaluate() {
713
+ return FormulaValue.boolean(this.value);
714
+ }
715
+ };
716
+ var ErrorNode = class extends FormulaNode {
717
+ constructor(errorValue) {
718
+ super();
719
+ this.errorValue = errorValue;
720
+ }
721
+ evaluate() {
722
+ return this.errorValue;
723
+ }
724
+ };
725
+ var BlankNode = class extends FormulaNode {
726
+ evaluate() {
727
+ return FormulaValue.blank;
728
+ }
729
+ };
730
+ var CellReferenceNode = class extends FormulaNode {
731
+ constructor(reference) {
732
+ super();
733
+ this.reference = reference;
734
+ }
735
+ evaluate(ctx) {
736
+ return ctx.getCellValue(this.reference);
737
+ }
738
+ };
739
+ var RangeReferenceNode = class extends FormulaNode {
740
+ constructor(startRef, endRef) {
741
+ super();
742
+ this.startRef = startRef;
743
+ this.endRef = endRef;
744
+ }
745
+ evaluate(ctx) {
746
+ return ctx.getRangeValues(this.startRef, this.endRef);
747
+ }
748
+ };
749
+ var SheetCellReferenceNode = class extends FormulaNode {
750
+ constructor(sheetName, cellReference) {
751
+ super();
752
+ this.sheetName = sheetName;
753
+ this.cellReference = cellReference;
754
+ }
755
+ evaluate(ctx) {
756
+ return ctx.getSheetCellValue(this.sheetName, this.cellReference);
757
+ }
758
+ };
759
+ var SheetRangeReferenceNode = class extends FormulaNode {
760
+ constructor(sheetName, startRef, endRef) {
761
+ super();
762
+ this.sheetName = sheetName;
763
+ this.startRef = startRef;
764
+ this.endRef = endRef;
765
+ }
766
+ evaluate(ctx) {
767
+ return ctx.getSheetRangeValues(this.sheetName, this.startRef, this.endRef);
768
+ }
769
+ };
770
+ var NamedRangeNode = class extends FormulaNode {
771
+ constructor(name) {
772
+ super();
773
+ this.name = name;
774
+ }
775
+ evaluate(ctx) {
776
+ return ctx.resolveNamedRange(this.name);
777
+ }
778
+ };
779
+ var BinaryOperator = /* @__PURE__ */ ((BinaryOperator2) => {
780
+ BinaryOperator2[BinaryOperator2["Add"] = 0] = "Add";
781
+ BinaryOperator2[BinaryOperator2["Subtract"] = 1] = "Subtract";
782
+ BinaryOperator2[BinaryOperator2["Multiply"] = 2] = "Multiply";
783
+ BinaryOperator2[BinaryOperator2["Divide"] = 3] = "Divide";
784
+ BinaryOperator2[BinaryOperator2["Power"] = 4] = "Power";
785
+ BinaryOperator2[BinaryOperator2["Concatenate"] = 5] = "Concatenate";
786
+ BinaryOperator2[BinaryOperator2["Equal"] = 6] = "Equal";
787
+ BinaryOperator2[BinaryOperator2["NotEqual"] = 7] = "NotEqual";
788
+ BinaryOperator2[BinaryOperator2["LessThan"] = 8] = "LessThan";
789
+ BinaryOperator2[BinaryOperator2["LessThanOrEqual"] = 9] = "LessThanOrEqual";
790
+ BinaryOperator2[BinaryOperator2["GreaterThan"] = 10] = "GreaterThan";
791
+ BinaryOperator2[BinaryOperator2["GreaterThanOrEqual"] = 11] = "GreaterThanOrEqual";
792
+ return BinaryOperator2;
793
+ })(BinaryOperator || {});
794
+ var UnaryOperator = /* @__PURE__ */ ((UnaryOperator2) => {
795
+ UnaryOperator2[UnaryOperator2["Negate"] = 0] = "Negate";
796
+ UnaryOperator2[UnaryOperator2["Plus"] = 1] = "Plus";
797
+ UnaryOperator2[UnaryOperator2["Percent"] = 2] = "Percent";
798
+ return UnaryOperator2;
799
+ })(UnaryOperator || {});
800
+ var _BinaryOpNode_instances, evalScalar_fn;
801
+ var BinaryOpNode = class extends FormulaNode {
802
+ constructor(left2, op, right2) {
803
+ super();
804
+ this.left = left2;
805
+ this.op = op;
806
+ this.right = right2;
807
+ __privateAdd(this, _BinaryOpNode_instances);
808
+ }
809
+ evaluate(ctx) {
810
+ const l = this.left.evaluate(ctx);
811
+ const r = this.right.evaluate(ctx);
812
+ if (l.isArray || r.isArray) {
813
+ const la = l.isArray ? l.arrayVal : ArrayValue.fromScalar(l);
814
+ const ra = r.isArray ? r.arrayVal : ArrayValue.fromScalar(r);
815
+ return FormulaValue.array(
816
+ ArrayValue.broadcast(la, ra, (a, b) => __privateMethod(this, _BinaryOpNode_instances, evalScalar_fn).call(this, a, b))
817
+ );
818
+ }
819
+ return __privateMethod(this, _BinaryOpNode_instances, evalScalar_fn).call(this, l, r);
820
+ }
821
+ };
822
+ _BinaryOpNode_instances = new WeakSet();
823
+ evalScalar_fn = function(l, r) {
824
+ const op = this.op;
825
+ if (op === 6 /* Equal */) return FormulaValue.boolean(FormulaValue.areEqual(l, r));
826
+ if (op === 7 /* NotEqual */) return FormulaValue.boolean(!FormulaValue.areEqual(l, r));
827
+ if (op === 8 /* LessThan */) return FormulaValue.boolean(FormulaValue.compare(l, r) < 0);
828
+ if (op === 9 /* LessThanOrEqual */) return FormulaValue.boolean(FormulaValue.compare(l, r) <= 0);
829
+ if (op === 10 /* GreaterThan */) return FormulaValue.boolean(FormulaValue.compare(l, r) > 0);
830
+ if (op === 11 /* GreaterThanOrEqual */) return FormulaValue.boolean(FormulaValue.compare(l, r) >= 0);
831
+ if (op === 5 /* Concatenate */) {
832
+ if (l.isError) return l;
833
+ if (r.isError) return r;
834
+ return FormulaValue.text(l.asText() + r.asText());
835
+ }
836
+ const ln2 = l.coerceToNumber();
837
+ if (ln2.isError) return ln2;
838
+ const rn = r.coerceToNumber();
839
+ if (rn.isError) return rn;
840
+ const lv = ln2.numberValue;
841
+ const rv = rn.numberValue;
842
+ switch (op) {
843
+ case 0 /* Add */:
844
+ return FormulaValue.number(lv + rv);
845
+ case 1 /* Subtract */:
846
+ return FormulaValue.number(lv - rv);
847
+ case 2 /* Multiply */:
848
+ return FormulaValue.number(lv * rv);
849
+ case 3 /* Divide */:
850
+ if (rv === 0) return FormulaValue.errorDiv0;
851
+ return FormulaValue.number(lv / rv);
852
+ case 4 /* Power */:
853
+ return FormulaValue.number(Math.pow(lv, rv));
854
+ default:
855
+ return FormulaValue.errorValue;
856
+ }
857
+ };
858
+ var UnaryOpNode = class extends FormulaNode {
859
+ constructor(op, operand) {
860
+ super();
861
+ this.op = op;
862
+ this.operand = operand;
863
+ }
864
+ evaluate(ctx) {
865
+ const val = this.operand.evaluate(ctx);
866
+ if (this.op === 1 /* Plus */) {
867
+ return val.coerceToNumber();
868
+ }
869
+ if (this.op === 0 /* Negate */) {
870
+ const n = val.coerceToNumber();
871
+ if (n.isError) return n;
872
+ return FormulaValue.number(-n.numberValue);
873
+ }
874
+ if (this.op === 2 /* Percent */) {
875
+ const n = val.coerceToNumber();
876
+ if (n.isError) return n;
877
+ return FormulaValue.number(n.numberValue / 100);
878
+ }
879
+ return FormulaValue.errorValue;
880
+ }
881
+ };
882
+ var ImplicitIntersectionNode = class extends FormulaNode {
883
+ constructor(inner) {
884
+ super();
885
+ this.inner = inner;
886
+ }
887
+ evaluate(ctx) {
888
+ const val = this.inner.evaluate(ctx);
889
+ if (!val.isArray) return val;
890
+ return val.arrayVal.implicitIntersect(ctx.formulaRow, ctx.formulaCol, 0, 0);
891
+ }
892
+ };
893
+ var FunctionCallNode = class extends FormulaNode {
894
+ constructor(functionName, args) {
895
+ super();
896
+ this.functionName = functionName;
897
+ this.args = args;
898
+ }
899
+ evaluate(ctx) {
900
+ return ctx.evaluateFunction(this.functionName, this.args);
901
+ }
902
+ };
903
+
904
+ // src/formula-parser.ts
905
+ var _tokens, _pos2, _FormulaParser_instances, current_get, advance_fn, expect_fn, parseComparison_fn, parseConcatenation_fn, parseAddSub_fn, parseMulDiv_fn, parseUnary_fn, parsePower_fn, parsePercent_fn, parsePrimary_fn, parseFunction_fn;
906
+ var FormulaParser = class {
907
+ constructor(tokens) {
908
+ __privateAdd(this, _FormulaParser_instances);
909
+ __privateAdd(this, _tokens);
910
+ __privateAdd(this, _pos2, 0);
911
+ __privateSet(this, _tokens, tokens);
912
+ }
913
+ parse() {
914
+ __privateSet(this, _pos2, 0);
915
+ const node = __privateMethod(this, _FormulaParser_instances, parseComparison_fn).call(this);
916
+ if (__privateGet(this, _FormulaParser_instances, current_get).type !== 27 /* EOF */) {
917
+ throw new FormulaException(
918
+ `Unexpected token '${__privateGet(this, _FormulaParser_instances, current_get).value}' at position ${__privateGet(this, _FormulaParser_instances, current_get).position}.`
919
+ );
920
+ }
921
+ return node;
922
+ }
923
+ };
924
+ _tokens = new WeakMap();
925
+ _pos2 = new WeakMap();
926
+ _FormulaParser_instances = new WeakSet();
927
+ current_get = function() {
928
+ return __privateGet(this, _tokens)[__privateGet(this, _pos2)] ?? { type: 27 /* EOF */, value: "", position: -1 };
929
+ };
930
+ advance_fn = function() {
931
+ const t = __privateGet(this, _FormulaParser_instances, current_get);
932
+ __privateWrapper(this, _pos2)._++;
933
+ return t;
934
+ };
935
+ expect_fn = function(type) {
936
+ if (__privateGet(this, _FormulaParser_instances, current_get).type !== type) {
937
+ throw new FormulaException(
938
+ `Expected token type ${type} but got ${__privateGet(this, _FormulaParser_instances, current_get).type} ('${__privateGet(this, _FormulaParser_instances, current_get).value}') at position ${__privateGet(this, _FormulaParser_instances, current_get).position}.`
939
+ );
940
+ }
941
+ return __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
942
+ };
943
+ // ── Precedence levels ──────────────────────────────────────────────────────
944
+ parseComparison_fn = function() {
945
+ let left2 = __privateMethod(this, _FormulaParser_instances, parseConcatenation_fn).call(this);
946
+ while (true) {
947
+ const op = comparisonOp(__privateGet(this, _FormulaParser_instances, current_get).type);
948
+ if (op === null) break;
949
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
950
+ left2 = new BinaryOpNode(left2, op, __privateMethod(this, _FormulaParser_instances, parseConcatenation_fn).call(this));
951
+ }
952
+ return left2;
953
+ };
954
+ parseConcatenation_fn = function() {
955
+ let left2 = __privateMethod(this, _FormulaParser_instances, parseAddSub_fn).call(this);
956
+ while (__privateGet(this, _FormulaParser_instances, current_get).type === 15 /* Ampersand */) {
957
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
958
+ left2 = new BinaryOpNode(left2, 5 /* Concatenate */, __privateMethod(this, _FormulaParser_instances, parseAddSub_fn).call(this));
959
+ }
960
+ return left2;
961
+ };
962
+ parseAddSub_fn = function() {
963
+ let left2 = __privateMethod(this, _FormulaParser_instances, parseMulDiv_fn).call(this);
964
+ while (true) {
965
+ const t = __privateGet(this, _FormulaParser_instances, current_get).type;
966
+ if (t !== 9 /* Plus */ && t !== 10 /* Minus */) break;
967
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
968
+ const op = t === 9 /* Plus */ ? 0 /* Add */ : 1 /* Subtract */;
969
+ left2 = new BinaryOpNode(left2, op, __privateMethod(this, _FormulaParser_instances, parseMulDiv_fn).call(this));
970
+ }
971
+ return left2;
972
+ };
973
+ parseMulDiv_fn = function() {
974
+ let left2 = __privateMethod(this, _FormulaParser_instances, parseUnary_fn).call(this);
975
+ while (true) {
976
+ const t = __privateGet(this, _FormulaParser_instances, current_get).type;
977
+ if (t !== 11 /* Multiply */ && t !== 12 /* Divide */) break;
978
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
979
+ const op = t === 11 /* Multiply */ ? 2 /* Multiply */ : 3 /* Divide */;
980
+ left2 = new BinaryOpNode(left2, op, __privateMethod(this, _FormulaParser_instances, parseUnary_fn).call(this));
981
+ }
982
+ return left2;
983
+ };
984
+ parseUnary_fn = function() {
985
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 10 /* Minus */) {
986
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
987
+ return new UnaryOpNode(0 /* Negate */, __privateMethod(this, _FormulaParser_instances, parsePower_fn).call(this));
988
+ }
989
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 9 /* Plus */) {
990
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
991
+ return new UnaryOpNode(1 /* Plus */, __privateMethod(this, _FormulaParser_instances, parsePower_fn).call(this));
992
+ }
993
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 25 /* AtSign */) {
994
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
995
+ return new ImplicitIntersectionNode(__privateMethod(this, _FormulaParser_instances, parsePower_fn).call(this));
996
+ }
997
+ return __privateMethod(this, _FormulaParser_instances, parsePower_fn).call(this);
998
+ };
999
+ parsePower_fn = function() {
1000
+ const left2 = __privateMethod(this, _FormulaParser_instances, parsePercent_fn).call(this);
1001
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 13 /* Power */) {
1002
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1003
+ return new BinaryOpNode(left2, 4 /* Power */, __privateMethod(this, _FormulaParser_instances, parseUnary_fn).call(this));
1004
+ }
1005
+ return left2;
1006
+ };
1007
+ parsePercent_fn = function() {
1008
+ let node = __privateMethod(this, _FormulaParser_instances, parsePrimary_fn).call(this);
1009
+ while (__privateGet(this, _FormulaParser_instances, current_get).type === 14 /* Percent */) {
1010
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1011
+ node = new UnaryOpNode(2 /* Percent */, node);
1012
+ }
1013
+ return node;
1014
+ };
1015
+ parsePrimary_fn = function() {
1016
+ const token = __privateGet(this, _FormulaParser_instances, current_get);
1017
+ switch (token.type) {
1018
+ case 0 /* Number */: {
1019
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1020
+ const n = parseFloat(token.value);
1021
+ if (isNaN(n)) throw new FormulaException(`Invalid number: ${token.value}`);
1022
+ return new NumberNode(n);
1023
+ }
1024
+ case 1 /* String */:
1025
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1026
+ return new StringNode(token.value);
1027
+ case 2 /* Boolean */:
1028
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1029
+ return new BooleanNode(token.value === "TRUE");
1030
+ case 26 /* ErrorLiteral */:
1031
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1032
+ return new ErrorNode(FormulaValue.error(FormulaValue.errorFromString(token.value)));
1033
+ case 3 /* CellReference */: {
1034
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1035
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 4 /* Colon */) {
1036
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1037
+ const end = __privateMethod(this, _FormulaParser_instances, expect_fn).call(this, 3 /* CellReference */);
1038
+ return new RangeReferenceNode(token.value, end.value);
1039
+ }
1040
+ return new CellReferenceNode(token.value);
1041
+ }
1042
+ case 22 /* SheetReference */: {
1043
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1044
+ const parts = token.value.split("!");
1045
+ const sheetName = parts[0];
1046
+ const cellRef = parts[1] ?? "";
1047
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 4 /* Colon */) {
1048
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1049
+ const end = __privateMethod(this, _FormulaParser_instances, expect_fn).call(this, 3 /* CellReference */);
1050
+ return new SheetRangeReferenceNode(sheetName, cellRef, end.value);
1051
+ }
1052
+ return new SheetCellReferenceNode(sheetName, cellRef);
1053
+ }
1054
+ case 23 /* NamedRange */:
1055
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1056
+ return new NamedRangeNode(token.value);
1057
+ case 5 /* Function */:
1058
+ return __privateMethod(this, _FormulaParser_instances, parseFunction_fn).call(this);
1059
+ case 6 /* LeftParen */: {
1060
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1061
+ const expr = __privateMethod(this, _FormulaParser_instances, parseComparison_fn).call(this);
1062
+ __privateMethod(this, _FormulaParser_instances, expect_fn).call(this, 7 /* RightParen */);
1063
+ return expr;
1064
+ }
1065
+ default:
1066
+ throw new FormulaException(
1067
+ `Unexpected token '${token.value}' (type ${token.type}) at position ${token.position}.`
1068
+ );
1069
+ }
1070
+ };
1071
+ parseFunction_fn = function() {
1072
+ const nameToken = __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1073
+ __privateMethod(this, _FormulaParser_instances, expect_fn).call(this, 6 /* LeftParen */);
1074
+ const args = [];
1075
+ if (__privateGet(this, _FormulaParser_instances, current_get).type !== 7 /* RightParen */) {
1076
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 8 /* Comma */) {
1077
+ args.push(new BlankNode());
1078
+ } else {
1079
+ args.push(__privateMethod(this, _FormulaParser_instances, parseComparison_fn).call(this));
1080
+ }
1081
+ while (__privateGet(this, _FormulaParser_instances, current_get).type === 8 /* Comma */) {
1082
+ __privateMethod(this, _FormulaParser_instances, advance_fn).call(this);
1083
+ if (__privateGet(this, _FormulaParser_instances, current_get).type === 8 /* Comma */ || __privateGet(this, _FormulaParser_instances, current_get).type === 7 /* RightParen */) {
1084
+ args.push(new BlankNode());
1085
+ } else {
1086
+ args.push(__privateMethod(this, _FormulaParser_instances, parseComparison_fn).call(this));
1087
+ }
1088
+ }
1089
+ }
1090
+ __privateMethod(this, _FormulaParser_instances, expect_fn).call(this, 7 /* RightParen */);
1091
+ return new FunctionCallNode(nameToken.value.toUpperCase(), args);
1092
+ };
1093
+ function comparisonOp(type) {
1094
+ switch (type) {
1095
+ case 16 /* Equal */:
1096
+ return 6 /* Equal */;
1097
+ case 17 /* NotEqual */:
1098
+ return 7 /* NotEqual */;
1099
+ case 18 /* LessThan */:
1100
+ return 8 /* LessThan */;
1101
+ case 19 /* LessThanOrEqual */:
1102
+ return 9 /* LessThanOrEqual */;
1103
+ case 20 /* GreaterThan */:
1104
+ return 10 /* GreaterThan */;
1105
+ case 21 /* GreaterThanOrEqual */:
1106
+ return 11 /* GreaterThanOrEqual */;
1107
+ default:
1108
+ return null;
1109
+ }
1110
+ }
1111
+
1112
+ // src/functions/math-functions.ts
1113
+ function registerMath(r) {
1114
+ r.register("SUM", sum, 1);
1115
+ r.register("AVERAGE", average, 1);
1116
+ r.register("MIN", min, 1);
1117
+ r.register("MAX", max, 1);
1118
+ r.register("COUNT", count, 1);
1119
+ r.register("COUNTA", countA, 1);
1120
+ r.register("COUNTBLANK", countBlank, 1, 1);
1121
+ r.register("COUNTIF", countIf, 2, 2);
1122
+ r.register("SUMIF", sumIf, 2, 3);
1123
+ r.register("AVERAGEIF", averageIf, 2, 3);
1124
+ r.register("PRODUCT", product, 1);
1125
+ r.register("SUMPRODUCT", sumProduct, 1);
1126
+ r.register("ABS", abs, 1, 1);
1127
+ r.register("ROUND", round, 2, 2);
1128
+ r.register("ROUNDUP", roundUp, 2, 2);
1129
+ r.register("ROUNDDOWN", roundDown, 2, 2);
1130
+ r.register("CEILING", ceiling, 2, 2);
1131
+ r.register("CEILING.MATH", ceiling, 2, 2);
1132
+ r.register("FLOOR", floor, 2, 2);
1133
+ r.register("FLOOR.MATH", floor, 2, 2);
1134
+ r.register("INT", int_, 1, 1);
1135
+ r.register("TRUNC", trunc, 1, 2);
1136
+ r.register("MOD", mod, 2, 2);
1137
+ r.register("QUOTIENT", quotient, 2, 2);
1138
+ r.register("POWER", power, 2, 2);
1139
+ r.register("SQRT", sqrt, 1, 1);
1140
+ r.register("SIGN", sign, 1, 1);
1141
+ r.register("PI", pi, 0, 0);
1142
+ r.register("RAND", rand, 0, 0, true);
1143
+ r.register("RANDBETWEEN", randBetween, 2, 2, true);
1144
+ r.register("LOG", log, 1, 2);
1145
+ r.register("LOG10", log10, 1, 1);
1146
+ r.register("LN", ln, 1, 1);
1147
+ r.register("EXP", exp, 1, 1);
1148
+ r.register("FACT", fact, 1, 1);
1149
+ r.register("COMBIN", combin, 2, 2);
1150
+ }
1151
+ function sum(a, c) {
1152
+ const r = FormulaHelper.collectNumbers(a, c);
1153
+ if (!r.ok) return r.error;
1154
+ return FormulaValue.number(r.values.reduce((s, n) => s + n, 0));
1155
+ }
1156
+ function average(a, c) {
1157
+ const r = FormulaHelper.collectNumbers(a, c);
1158
+ if (!r.ok) return r.error;
1159
+ if (r.values.length === 0) return FormulaValue.errorDiv0;
1160
+ return FormulaValue.number(r.values.reduce((s, n) => s + n, 0) / r.values.length);
1161
+ }
1162
+ function min(a, c) {
1163
+ const r = FormulaHelper.collectNumbers(a, c);
1164
+ if (!r.ok) return r.error;
1165
+ return r.values.length === 0 ? FormulaValue.zero : FormulaValue.number(Math.min(...r.values));
1166
+ }
1167
+ function max(a, c) {
1168
+ const r = FormulaHelper.collectNumbers(a, c);
1169
+ if (!r.ok) return r.error;
1170
+ return r.values.length === 0 ? FormulaValue.zero : FormulaValue.number(Math.max(...r.values));
1171
+ }
1172
+ function count(a, c) {
1173
+ const flat = FormulaHelper.flattenArgs(a, c);
1174
+ let n = 0;
1175
+ for (const v of flat) {
1176
+ if (v.isNumber || v.isText && !isNaN(parseFloat(v.textValue))) n++;
1177
+ }
1178
+ return FormulaValue.number(n);
1179
+ }
1180
+ function countA(a, c) {
1181
+ return FormulaValue.number(FormulaHelper.flattenArgs(a, c).filter((v) => !v.isBlank).length);
1182
+ }
1183
+ function countBlank(a, c) {
1184
+ const v = a[0].evaluate(c);
1185
+ if (!v.isArray) return FormulaValue.number(v.isBlank ? 1 : 0);
1186
+ let n = 0;
1187
+ for (const item of v.arrayVal.values()) if (item.isBlank) n++;
1188
+ return FormulaValue.number(n);
1189
+ }
1190
+ function countIf(a, c) {
1191
+ const range = a[0].evaluate(c);
1192
+ if (range.isError) return range;
1193
+ const crit = a[1].evaluate(c);
1194
+ if (crit.isError) return crit;
1195
+ const criteria = crit.asText();
1196
+ if (!range.isArray) return FormulaValue.number(FormulaHelper.matchesCriteria(range, criteria) ? 1 : 0);
1197
+ let n = 0;
1198
+ for (const item of range.arrayVal.values()) {
1199
+ if (!item.isBlank && FormulaHelper.matchesCriteria(item, criteria)) n++;
1200
+ }
1201
+ return FormulaValue.number(n);
1202
+ }
1203
+ function sumIf(a, c) {
1204
+ const range = a[0].evaluate(c);
1205
+ if (range.isError) return range;
1206
+ const crit = a[1].evaluate(c);
1207
+ if (crit.isError) return crit;
1208
+ const criteria = crit.asText();
1209
+ const sumRange = a.length > 2 ? a[2].evaluate(c) : range;
1210
+ if (sumRange.isError) return sumRange;
1211
+ if (!range.isArray) {
1212
+ if (FormulaHelper.matchesCriteria(range, criteria)) {
1213
+ const r = sumRange.tryAsDouble();
1214
+ return r.ok ? FormulaValue.number(r.value) : FormulaValue.zero;
1215
+ }
1216
+ return FormulaValue.zero;
1217
+ }
1218
+ const rangeArr = range.arrayVal;
1219
+ const sumArr = sumRange.isArray ? sumRange.arrayVal : null;
1220
+ let total = 0;
1221
+ for (let i = 0; i < rangeArr.length; i++) {
1222
+ const rv = rangeArr.getFlat(i);
1223
+ if (rv.isBlank) continue;
1224
+ if (FormulaHelper.matchesCriteria(rv, criteria)) {
1225
+ const sv = sumArr ? sumArr.getFlat(i) : rangeArr.getFlat(i);
1226
+ const r = sv.tryAsDouble();
1227
+ if (r.ok) total += r.value;
1228
+ }
1229
+ }
1230
+ return FormulaValue.number(total);
1231
+ }
1232
+ function averageIf(a, c) {
1233
+ const range = a[0].evaluate(c);
1234
+ if (range.isError) return range;
1235
+ const crit = a[1].evaluate(c);
1236
+ if (crit.isError) return crit;
1237
+ const criteria = crit.asText();
1238
+ const avgRange = a.length > 2 ? a[2].evaluate(c) : range;
1239
+ if (avgRange.isError) return avgRange;
1240
+ if (!range.isArray) {
1241
+ if (!FormulaHelper.matchesCriteria(range, criteria)) return FormulaValue.errorDiv0;
1242
+ const r = avgRange.tryAsDouble();
1243
+ return r.ok ? FormulaValue.number(r.value) : FormulaValue.errorDiv0;
1244
+ }
1245
+ const rangeArr = range.arrayVal;
1246
+ const avgArr = avgRange.isArray ? avgRange.arrayVal : null;
1247
+ let total = 0, cnt = 0;
1248
+ for (let i = 0; i < rangeArr.length; i++) {
1249
+ const rv = rangeArr.getFlat(i);
1250
+ if (rv.isBlank) continue;
1251
+ if (FormulaHelper.matchesCriteria(rv, criteria)) {
1252
+ const sv = avgArr ? avgArr.getFlat(i) : rangeArr.getFlat(i);
1253
+ const r = sv.tryAsDouble();
1254
+ if (r.ok) {
1255
+ total += r.value;
1256
+ cnt++;
1257
+ }
1258
+ }
1259
+ }
1260
+ return cnt === 0 ? FormulaValue.errorDiv0 : FormulaValue.number(total / cnt);
1261
+ }
1262
+ function product(a, c) {
1263
+ const r = FormulaHelper.collectNumbers(a, c);
1264
+ if (!r.ok) return r.error;
1265
+ return FormulaValue.number(r.values.reduce((p, n) => p * n, 1));
1266
+ }
1267
+ function sumProduct(a, c) {
1268
+ const arrays = a.map((arg) => arg.evaluate(c));
1269
+ for (const v of arrays) if (v.isError) return v;
1270
+ const first = arrays[0];
1271
+ const len2 = first.isArray ? first.arrayVal.length : 1;
1272
+ let total = 0;
1273
+ for (let i = 0; i < len2; i++) {
1274
+ let prod = 1;
1275
+ for (const v of arrays) {
1276
+ const item = v.isArray ? v.arrayVal.getFlat(i) : v;
1277
+ const r = item.tryAsDouble();
1278
+ if (!r.ok) {
1279
+ prod = 0;
1280
+ break;
1281
+ }
1282
+ prod *= r.value;
1283
+ }
1284
+ total += prod;
1285
+ }
1286
+ return FormulaValue.number(total);
1287
+ }
1288
+ function abs(a, c) {
1289
+ const r = FormulaHelper.evalDouble(a[0], c);
1290
+ return r.ok ? FormulaValue.number(Math.abs(r.value)) : r.error;
1291
+ }
1292
+ function round(a, c) {
1293
+ const n = FormulaHelper.evalDouble(a[0], c);
1294
+ if (!n.ok) return n.error;
1295
+ const d = FormulaHelper.evalDouble(a[1], c);
1296
+ if (!d.ok) return d.error;
1297
+ const factor = Math.pow(10, Math.round(d.value));
1298
+ return FormulaValue.number(Math.round(n.value * factor) / factor);
1299
+ }
1300
+ function roundUp(a, c) {
1301
+ const n = FormulaHelper.evalDouble(a[0], c);
1302
+ if (!n.ok) return n.error;
1303
+ const d = FormulaHelper.evalDouble(a[1], c);
1304
+ if (!d.ok) return d.error;
1305
+ const factor = Math.pow(10, Math.round(d.value));
1306
+ return FormulaValue.number(Math.ceil(n.value * factor) / factor);
1307
+ }
1308
+ function roundDown(a, c) {
1309
+ const n = FormulaHelper.evalDouble(a[0], c);
1310
+ if (!n.ok) return n.error;
1311
+ const d = FormulaHelper.evalDouble(a[1], c);
1312
+ if (!d.ok) return d.error;
1313
+ const factor = Math.pow(10, Math.round(d.value));
1314
+ return FormulaValue.number(Math.floor(n.value * factor) / factor);
1315
+ }
1316
+ function ceiling(a, c) {
1317
+ const n = FormulaHelper.evalDouble(a[0], c);
1318
+ if (!n.ok) return n.error;
1319
+ const s = FormulaHelper.evalDouble(a[1], c);
1320
+ if (!s.ok) return s.error;
1321
+ if (s.value === 0) return FormulaValue.zero;
1322
+ return FormulaValue.number(Math.ceil(n.value / s.value) * s.value);
1323
+ }
1324
+ function floor(a, c) {
1325
+ const n = FormulaHelper.evalDouble(a[0], c);
1326
+ if (!n.ok) return n.error;
1327
+ const s = FormulaHelper.evalDouble(a[1], c);
1328
+ if (!s.ok) return s.error;
1329
+ if (s.value === 0) return FormulaValue.zero;
1330
+ return FormulaValue.number(Math.floor(n.value / s.value) * s.value);
1331
+ }
1332
+ function int_(a, c) {
1333
+ const r = FormulaHelper.evalDouble(a[0], c);
1334
+ return r.ok ? FormulaValue.number(Math.floor(r.value)) : r.error;
1335
+ }
1336
+ function trunc(a, c) {
1337
+ const n = FormulaHelper.evalDouble(a[0], c);
1338
+ if (!n.ok) return n.error;
1339
+ let digits = 0;
1340
+ if (a.length > 1) {
1341
+ const d = FormulaHelper.evalDouble(a[1], c);
1342
+ if (!d.ok) return d.error;
1343
+ digits = Math.round(d.value);
1344
+ }
1345
+ const factor = Math.pow(10, digits);
1346
+ return FormulaValue.number(Math.trunc(n.value * factor) / factor);
1347
+ }
1348
+ function mod(a, c) {
1349
+ const n = FormulaHelper.evalDouble(a[0], c);
1350
+ if (!n.ok) return n.error;
1351
+ const d = FormulaHelper.evalDouble(a[1], c);
1352
+ if (!d.ok) return d.error;
1353
+ if (d.value === 0) return FormulaValue.errorDiv0;
1354
+ return FormulaValue.number(n.value - d.value * Math.floor(n.value / d.value));
1355
+ }
1356
+ function quotient(a, c) {
1357
+ const n = FormulaHelper.evalDouble(a[0], c);
1358
+ if (!n.ok) return n.error;
1359
+ const d = FormulaHelper.evalDouble(a[1], c);
1360
+ if (!d.ok) return d.error;
1361
+ if (d.value === 0) return FormulaValue.errorDiv0;
1362
+ return FormulaValue.number(Math.trunc(n.value / d.value));
1363
+ }
1364
+ function power(a, c) {
1365
+ const b = FormulaHelper.evalDouble(a[0], c);
1366
+ if (!b.ok) return b.error;
1367
+ const e = FormulaHelper.evalDouble(a[1], c);
1368
+ if (!e.ok) return e.error;
1369
+ return FormulaValue.number(Math.pow(b.value, e.value));
1370
+ }
1371
+ function sqrt(a, c) {
1372
+ const r = FormulaHelper.evalDouble(a[0], c);
1373
+ if (!r.ok) return r.error;
1374
+ if (r.value < 0) return FormulaValue.errorNum;
1375
+ return FormulaValue.number(Math.sqrt(r.value));
1376
+ }
1377
+ function sign(a, c) {
1378
+ const r = FormulaHelper.evalDouble(a[0], c);
1379
+ return r.ok ? FormulaValue.number(Math.sign(r.value)) : r.error;
1380
+ }
1381
+ function pi() {
1382
+ return FormulaValue.number(Math.PI);
1383
+ }
1384
+ function rand() {
1385
+ return FormulaValue.number(Math.random());
1386
+ }
1387
+ function randBetween(a, c) {
1388
+ const lo = FormulaHelper.evalDouble(a[0], c);
1389
+ if (!lo.ok) return lo.error;
1390
+ const hi = FormulaHelper.evalDouble(a[1], c);
1391
+ if (!hi.ok) return hi.error;
1392
+ return FormulaValue.number(Math.floor(lo.value + Math.random() * (hi.value - lo.value + 1)));
1393
+ }
1394
+ function log(a, c) {
1395
+ const n = FormulaHelper.evalDouble(a[0], c);
1396
+ if (!n.ok) return n.error;
1397
+ if (n.value <= 0) return FormulaValue.errorNum;
1398
+ let base = 10;
1399
+ if (a.length > 1) {
1400
+ const b = FormulaHelper.evalDouble(a[1], c);
1401
+ if (!b.ok) return b.error;
1402
+ base = b.value;
1403
+ }
1404
+ if (base <= 0 || base === 1) return FormulaValue.errorNum;
1405
+ return FormulaValue.number(Math.log(n.value) / Math.log(base));
1406
+ }
1407
+ function log10(a, c) {
1408
+ const r = FormulaHelper.evalDouble(a[0], c);
1409
+ if (!r.ok) return r.error;
1410
+ if (r.value <= 0) return FormulaValue.errorNum;
1411
+ return FormulaValue.number(Math.log10(r.value));
1412
+ }
1413
+ function ln(a, c) {
1414
+ const r = FormulaHelper.evalDouble(a[0], c);
1415
+ if (!r.ok) return r.error;
1416
+ if (r.value <= 0) return FormulaValue.errorNum;
1417
+ return FormulaValue.number(Math.log(r.value));
1418
+ }
1419
+ function exp(a, c) {
1420
+ const r = FormulaHelper.evalDouble(a[0], c);
1421
+ return r.ok ? FormulaValue.number(Math.exp(r.value)) : r.error;
1422
+ }
1423
+ function fact(a, c) {
1424
+ const r = FormulaHelper.evalDouble(a[0], c);
1425
+ if (!r.ok) return r.error;
1426
+ const n = Math.round(r.value);
1427
+ if (n < 0) return FormulaValue.errorNum;
1428
+ if (n > 170) return FormulaValue.errorNum;
1429
+ let f = 1;
1430
+ for (let i = 2; i <= n; i++) f *= i;
1431
+ return FormulaValue.number(f);
1432
+ }
1433
+ function combin(a, c) {
1434
+ const n = FormulaHelper.evalDouble(a[0], c);
1435
+ if (!n.ok) return n.error;
1436
+ const k = FormulaHelper.evalDouble(a[1], c);
1437
+ if (!k.ok) return k.error;
1438
+ const N = Math.round(n.value);
1439
+ const K = Math.round(k.value);
1440
+ if (N < 0 || K < 0 || K > N) return FormulaValue.errorNum;
1441
+ let result = 1;
1442
+ for (let i = 0; i < K; i++) result = result * (N - i) / (i + 1);
1443
+ return FormulaValue.number(Math.round(result));
1444
+ }
1445
+ function registerText(r) {
1446
+ r.register("LEFT", left, 1, 2);
1447
+ r.register("RIGHT", right, 1, 2);
1448
+ r.register("MID", mid, 3, 3);
1449
+ r.register("LEN", len, 1, 1);
1450
+ r.register("UPPER", upper, 1, 1);
1451
+ r.register("LOWER", lower, 1, 1);
1452
+ r.register("PROPER", proper, 1, 1);
1453
+ r.register("TRIM", trim, 1, 1);
1454
+ r.register("CLEAN", clean, 1, 1);
1455
+ r.register("SUBSTITUTE", substitute, 3, 4);
1456
+ r.register("REPLACE", replace, 4, 4);
1457
+ r.register("CONCATENATE", concatenate, 1);
1458
+ r.register("CONCAT", concatenate, 1);
1459
+ r.register("TEXTJOIN", textJoin, 3);
1460
+ r.register("TEXT", text_, 2, 2);
1461
+ r.register("VALUE", value, 1, 1);
1462
+ r.register("FIND", find, 2, 3);
1463
+ r.register("SEARCH", search, 2, 3);
1464
+ r.register("REPT", rept, 2, 2);
1465
+ r.register("EXACT", exact, 2, 2);
1466
+ r.register("CHAR", char_, 1, 1);
1467
+ r.register("CODE", code, 1, 1);
1468
+ r.register("T", t_, 1, 1);
1469
+ }
1470
+ function str(a, c, idx) {
1471
+ const r = FormulaHelper.evalString(a[idx], c);
1472
+ return r.ok ? { ok: true, s: r.value } : { ok: false, e: r.error };
1473
+ }
1474
+ function num(a, c, idx) {
1475
+ const r = FormulaHelper.evalDouble(a[idx], c);
1476
+ return r.ok ? { ok: true, n: r.value } : { ok: false, e: r.error };
1477
+ }
1478
+ function left(a, c) {
1479
+ const s = str(a, c, 0);
1480
+ if (!s.ok) return s.e;
1481
+ let n = 1;
1482
+ if (a.length > 1) {
1483
+ const r = num(a, c, 1);
1484
+ if (!r.ok) return r.e;
1485
+ n = Math.round(r.n);
1486
+ }
1487
+ if (n < 0) return FormulaValue.errorValue;
1488
+ return FormulaValue.text(s.s.slice(0, n));
1489
+ }
1490
+ function right(a, c) {
1491
+ const s = str(a, c, 0);
1492
+ if (!s.ok) return s.e;
1493
+ let n = 1;
1494
+ if (a.length > 1) {
1495
+ const r = num(a, c, 1);
1496
+ if (!r.ok) return r.e;
1497
+ n = Math.round(r.n);
1498
+ }
1499
+ if (n < 0) return FormulaValue.errorValue;
1500
+ return FormulaValue.text(n >= s.s.length ? s.s : s.s.slice(-n));
1501
+ }
1502
+ function mid(a, c) {
1503
+ const s = str(a, c, 0);
1504
+ if (!s.ok) return s.e;
1505
+ const sv = num(a, c, 1);
1506
+ if (!sv.ok) return sv.e;
1507
+ const nv = num(a, c, 2);
1508
+ if (!nv.ok) return nv.e;
1509
+ const start = Math.round(sv.n) - 1;
1510
+ const count2 = Math.round(nv.n);
1511
+ if (start < 0 || count2 < 0) return FormulaValue.errorValue;
1512
+ return FormulaValue.text(s.s.slice(start, start + count2));
1513
+ }
1514
+ function len(a, c) {
1515
+ const s = str(a, c, 0);
1516
+ if (!s.ok) return s.e;
1517
+ return FormulaValue.number(s.s.length);
1518
+ }
1519
+ function upper(a, c) {
1520
+ const s = str(a, c, 0);
1521
+ if (!s.ok) return s.e;
1522
+ return FormulaValue.text(s.s.toUpperCase());
1523
+ }
1524
+ function lower(a, c) {
1525
+ const s = str(a, c, 0);
1526
+ if (!s.ok) return s.e;
1527
+ return FormulaValue.text(s.s.toLowerCase());
1528
+ }
1529
+ function proper(a, c) {
1530
+ const s = str(a, c, 0);
1531
+ if (!s.ok) return s.e;
1532
+ let capitalise = true;
1533
+ let result = "";
1534
+ for (const ch of s.s) {
1535
+ result += capitalise ? ch.toUpperCase() : ch.toLowerCase();
1536
+ capitalise = !/[a-zA-Z]/.test(ch);
1537
+ }
1538
+ return FormulaValue.text(result);
1539
+ }
1540
+ function trim(a, c) {
1541
+ const s = str(a, c, 0);
1542
+ if (!s.ok) return s.e;
1543
+ return FormulaValue.text(s.s.trim().replace(/\s+/g, " "));
1544
+ }
1545
+ function clean(a, c) {
1546
+ const s = str(a, c, 0);
1547
+ if (!s.ok) return s.e;
1548
+ return FormulaValue.text([...s.s].filter((ch) => ch.charCodeAt(0) >= 32).join(""));
1549
+ }
1550
+ function substitute(a, c) {
1551
+ const s = str(a, c, 0);
1552
+ if (!s.ok) return s.e;
1553
+ const old = str(a, c, 1);
1554
+ if (!old.ok) return old.e;
1555
+ const nw = str(a, c, 2);
1556
+ if (!nw.ok) return nw.e;
1557
+ if (a.length > 3) {
1558
+ const iv = num(a, c, 3);
1559
+ if (!iv.ok) return iv.e;
1560
+ const inst = Math.round(iv.n);
1561
+ let count2 = 0, pos = 0, result = "";
1562
+ while (pos < s.s.length) {
1563
+ const idx = s.s.indexOf(old.s, pos);
1564
+ if (idx < 0) {
1565
+ result += s.s.slice(pos);
1566
+ break;
1567
+ }
1568
+ count2++;
1569
+ if (count2 === inst) {
1570
+ result += s.s.slice(pos, idx) + nw.s;
1571
+ pos = idx + old.s.length;
1572
+ result += s.s.slice(pos);
1573
+ break;
1574
+ }
1575
+ result += s.s.slice(pos, idx + old.s.length);
1576
+ pos = idx + old.s.length;
1577
+ }
1578
+ return FormulaValue.text(result);
1579
+ }
1580
+ return FormulaValue.text(s.s.split(old.s).join(nw.s));
1581
+ }
1582
+ function replace(a, c) {
1583
+ const s = str(a, c, 0);
1584
+ if (!s.ok) return s.e;
1585
+ const sv = num(a, c, 1);
1586
+ if (!sv.ok) return sv.e;
1587
+ const nv = num(a, c, 2);
1588
+ if (!nv.ok) return nv.e;
1589
+ const nw = str(a, c, 3);
1590
+ if (!nw.ok) return nw.e;
1591
+ const start = Math.max(0, Math.round(sv.n) - 1);
1592
+ const count2 = Math.max(0, Math.round(nv.n));
1593
+ return FormulaValue.text(s.s.slice(0, start) + nw.s + s.s.slice(start + count2));
1594
+ }
1595
+ function concatenate(a, c) {
1596
+ let result = "";
1597
+ for (const arg of a) {
1598
+ const v = arg.evaluate(c);
1599
+ if (v.isError) return v;
1600
+ result += v.asText();
1601
+ }
1602
+ return FormulaValue.text(result);
1603
+ }
1604
+ function textJoin(a, c) {
1605
+ const delim = str(a, c, 0);
1606
+ if (!delim.ok) return delim.e;
1607
+ const ignV = a[1].evaluate(c);
1608
+ if (ignV.isError) return ignV;
1609
+ const ignoreEmpty = ignV.coerceToBool().booleanValue;
1610
+ const parts = [];
1611
+ for (let i = 2; i < a.length; i++) {
1612
+ const v = a[i].evaluate(c);
1613
+ if (v.isError) return v;
1614
+ if (v.isArray) {
1615
+ for (const item of v.arrayVal.values()) {
1616
+ const t = item.asText();
1617
+ if (!ignoreEmpty || t !== "") parts.push(t);
1618
+ }
1619
+ } else {
1620
+ const t = v.asText();
1621
+ if (!ignoreEmpty || t !== "") parts.push(t);
1622
+ }
1623
+ }
1624
+ const result = parts.join(delim.s);
1625
+ if (result.length > 32767) return FormulaValue.errorValue;
1626
+ return FormulaValue.text(result);
1627
+ }
1628
+ function text_(a, c) {
1629
+ const n = FormulaHelper.evalDouble(a[0], c);
1630
+ if (!n.ok) return n.error;
1631
+ const f = str(a, c, 1);
1632
+ if (!f.ok) return f.e;
1633
+ try {
1634
+ return FormulaValue.text(formatNumber(n.value, f.s));
1635
+ } catch {
1636
+ return FormulaValue.errorValue;
1637
+ }
1638
+ }
1639
+ function formatNumber(value2, fmt) {
1640
+ if (fmt === "0") return String(Math.round(value2));
1641
+ if (fmt === "0.00") return value2.toFixed(2);
1642
+ if (fmt === "#,##0") return Math.round(value2).toLocaleString("en-US");
1643
+ if (fmt === "#,##0.00") return value2.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
1644
+ if (fmt === "0%") return `${Math.round(value2 * 100)}%`;
1645
+ if (fmt === "0.00%") return `${(value2 * 100).toFixed(2)}%`;
1646
+ if (/[yYmMdD]/.test(fmt)) {
1647
+ try {
1648
+ const date = fromOADate(value2);
1649
+ return date.toLocaleDateString();
1650
+ } catch {
1651
+ }
1652
+ }
1653
+ return String(value2);
1654
+ }
1655
+ function value(a, c) {
1656
+ const s = str(a, c, 0);
1657
+ if (!s.ok) return s.e;
1658
+ const n = parseFloat(s.s.replace(/,/g, "").replace(/%$/, (m) => {
1659
+ return m ? String(parseFloat(s.s) / 100) : "";
1660
+ }));
1661
+ if (isNaN(n)) return FormulaValue.errorValue;
1662
+ return FormulaValue.number(n);
1663
+ }
1664
+ function find(a, c) {
1665
+ const needle = str(a, c, 0);
1666
+ if (!needle.ok) return needle.e;
1667
+ const haystack = str(a, c, 1);
1668
+ if (!haystack.ok) return haystack.e;
1669
+ let start = 0;
1670
+ if (a.length > 2) {
1671
+ const r = num(a, c, 2);
1672
+ if (!r.ok) return r.e;
1673
+ start = Math.round(r.n) - 1;
1674
+ }
1675
+ const idx = haystack.s.indexOf(needle.s, start);
1676
+ return idx < 0 ? FormulaValue.errorValue : FormulaValue.number(idx + 1);
1677
+ }
1678
+ function search(a, c) {
1679
+ const needle = str(a, c, 0);
1680
+ if (!needle.ok) return needle.e;
1681
+ const haystack = str(a, c, 1);
1682
+ if (!haystack.ok) return haystack.e;
1683
+ let start = 0;
1684
+ if (a.length > 2) {
1685
+ const r = num(a, c, 2);
1686
+ if (!r.ok) return r.e;
1687
+ start = Math.round(r.n) - 1;
1688
+ }
1689
+ const idx = haystack.s.toLowerCase().indexOf(needle.s.toLowerCase(), start);
1690
+ return idx < 0 ? FormulaValue.errorValue : FormulaValue.number(idx + 1);
1691
+ }
1692
+ function rept(a, c) {
1693
+ const s = str(a, c, 0);
1694
+ if (!s.ok) return s.e;
1695
+ const n = num(a, c, 1);
1696
+ if (!n.ok) return n.e;
1697
+ const count2 = Math.round(n.n);
1698
+ if (count2 < 0) return FormulaValue.errorValue;
1699
+ return FormulaValue.text(s.s.repeat(count2));
1700
+ }
1701
+ function exact(a, c) {
1702
+ const s1 = str(a, c, 0);
1703
+ if (!s1.ok) return s1.e;
1704
+ const s2 = str(a, c, 1);
1705
+ if (!s2.ok) return s2.e;
1706
+ return FormulaValue.boolean(s1.s === s2.s);
1707
+ }
1708
+ function char_(a, c) {
1709
+ const r = num(a, c, 0);
1710
+ if (!r.ok) return r.e;
1711
+ const code2 = Math.round(r.n);
1712
+ if (code2 < 1 || code2 > 255) return FormulaValue.errorValue;
1713
+ return FormulaValue.text(String.fromCharCode(code2));
1714
+ }
1715
+ function code(a, c) {
1716
+ const s = str(a, c, 0);
1717
+ if (!s.ok) return s.e;
1718
+ if (s.s.length === 0) return FormulaValue.errorValue;
1719
+ return FormulaValue.number(s.s.charCodeAt(0));
1720
+ }
1721
+ function t_(a, c) {
1722
+ const v = a[0].evaluate(c);
1723
+ return v.isText ? v : FormulaValue.emptyString;
1724
+ }
1725
+
1726
+ // src/functions/logical-functions.ts
1727
+ function registerLogical(r) {
1728
+ r.register("IF", if_, 2, 3);
1729
+ r.register("AND", and, 1);
1730
+ r.register("OR", or, 1);
1731
+ r.register("NOT", not, 1, 1);
1732
+ r.register("XOR", xor, 1);
1733
+ r.register("IFERROR", ifError, 2, 2);
1734
+ r.register("IFNA", ifNa, 2, 2);
1735
+ r.register("IFS", ifs, 2);
1736
+ r.register("SWITCH", switch_, 3);
1737
+ r.register("TRUE", trueFn, 0, 0);
1738
+ r.register("FALSE", falseFn, 0, 0);
1739
+ }
1740
+ function if_(a, c) {
1741
+ const cond = a[0].evaluate(c);
1742
+ if (cond.isError) return cond;
1743
+ const b = cond.coerceToBool();
1744
+ if (b.isError) return b;
1745
+ return b.booleanValue ? a[1].evaluate(c) : a.length > 2 ? a[2].evaluate(c) : FormulaValue.false_;
1746
+ }
1747
+ function and(a, c) {
1748
+ let hasValue = false;
1749
+ for (const arg of a) {
1750
+ const v = arg.evaluate(c);
1751
+ if (v.isError) return v;
1752
+ if (v.isArray) {
1753
+ for (const item of v.arrayVal.values()) {
1754
+ if (item.isBlank) continue;
1755
+ if (item.isError) return item;
1756
+ hasValue = true;
1757
+ const bv = item.coerceToBool();
1758
+ if (bv.isError) return bv;
1759
+ if (!bv.booleanValue) return FormulaValue.false_;
1760
+ }
1761
+ } else {
1762
+ if (v.isBlank) {
1763
+ hasValue = true;
1764
+ continue;
1765
+ }
1766
+ hasValue = true;
1767
+ const bv = v.coerceToBool();
1768
+ if (bv.isError) return bv;
1769
+ if (!bv.booleanValue) return FormulaValue.false_;
1770
+ }
1771
+ }
1772
+ return hasValue ? FormulaValue.true_ : FormulaValue.errorValue;
1773
+ }
1774
+ function or(a, c) {
1775
+ let hasValue = false;
1776
+ for (const arg of a) {
1777
+ const v = arg.evaluate(c);
1778
+ if (v.isError) return v;
1779
+ if (v.isArray) {
1780
+ for (const item of v.arrayVal.values()) {
1781
+ if (item.isBlank) continue;
1782
+ if (item.isError) return item;
1783
+ hasValue = true;
1784
+ const bv = item.coerceToBool();
1785
+ if (bv.isError) return bv;
1786
+ if (bv.booleanValue) return FormulaValue.true_;
1787
+ }
1788
+ } else {
1789
+ if (v.isBlank) {
1790
+ hasValue = true;
1791
+ continue;
1792
+ }
1793
+ hasValue = true;
1794
+ const bv = v.coerceToBool();
1795
+ if (bv.isError) return bv;
1796
+ if (bv.booleanValue) return FormulaValue.true_;
1797
+ }
1798
+ }
1799
+ return hasValue ? FormulaValue.false_ : FormulaValue.errorValue;
1800
+ }
1801
+ function not(a, c) {
1802
+ const v = a[0].evaluate(c);
1803
+ if (v.isError) return v;
1804
+ const bv = v.coerceToBool();
1805
+ if (bv.isError) return bv;
1806
+ return FormulaValue.boolean(!bv.booleanValue);
1807
+ }
1808
+ function xor(a, c) {
1809
+ let trueCount = 0;
1810
+ for (const arg of a) {
1811
+ const v = arg.evaluate(c);
1812
+ if (v.isError) return v;
1813
+ const bv = v.coerceToBool();
1814
+ if (bv.isError) return bv;
1815
+ if (bv.booleanValue) trueCount++;
1816
+ }
1817
+ return FormulaValue.boolean(trueCount % 2 === 1);
1818
+ }
1819
+ function ifError(a, c) {
1820
+ const v = a[0].evaluate(c);
1821
+ return v.isError ? a[1].evaluate(c) : v;
1822
+ }
1823
+ function ifNa(a, c) {
1824
+ const v = a[0].evaluate(c);
1825
+ return v.isError && v.errorCode === 7 /* NA */ ? a[1].evaluate(c) : v;
1826
+ }
1827
+ function ifs(a, c) {
1828
+ for (let i = 0; i + 1 < a.length; i += 2) {
1829
+ const cond = a[i].evaluate(c);
1830
+ if (cond.isError) return cond;
1831
+ const bv = cond.coerceToBool();
1832
+ if (bv.isError) return bv;
1833
+ if (bv.booleanValue) return a[i + 1].evaluate(c);
1834
+ }
1835
+ return FormulaValue.errorNA;
1836
+ }
1837
+ function switch_(a, c) {
1838
+ const expr = a[0].evaluate(c);
1839
+ if (expr.isError) return expr;
1840
+ for (let i = 1; i + 1 < a.length; i += 2) {
1841
+ const cv = a[i].evaluate(c);
1842
+ if (cv.isError) return cv;
1843
+ if (FormulaValue.areEqual(expr, cv)) return a[i + 1].evaluate(c);
1844
+ }
1845
+ return a.length % 2 === 0 ? a[a.length - 1].evaluate(c) : FormulaValue.errorNA;
1846
+ }
1847
+ function trueFn() {
1848
+ return FormulaValue.true_;
1849
+ }
1850
+ function falseFn() {
1851
+ return FormulaValue.false_;
1852
+ }
1853
+
1854
+ // src/functions/date-functions.ts
1855
+ var OA_EPOCH_MS = Date.UTC(1899, 11, 30, 0, 0, 0, 0);
1856
+ var MS_PER_DAY = 864e5;
1857
+ function toOA(date) {
1858
+ return (Date.UTC(
1859
+ date.getFullYear(),
1860
+ date.getMonth(),
1861
+ date.getDate(),
1862
+ date.getHours(),
1863
+ date.getMinutes(),
1864
+ date.getSeconds()
1865
+ ) - OA_EPOCH_MS) / MS_PER_DAY;
1866
+ }
1867
+ function fromOA(oa) {
1868
+ const ms = OA_EPOCH_MS + oa * MS_PER_DAY;
1869
+ const d = new Date(ms);
1870
+ return new Date(
1871
+ d.getUTCFullYear(),
1872
+ d.getUTCMonth(),
1873
+ d.getUTCDate(),
1874
+ d.getUTCHours(),
1875
+ d.getUTCMinutes(),
1876
+ d.getUTCSeconds()
1877
+ );
1878
+ }
1879
+ function registerDate(r) {
1880
+ r.register("NOW", now, 0, 0, true);
1881
+ r.register("TODAY", today, 0, 0, true);
1882
+ r.register("DATE", date_, 3, 3);
1883
+ r.register("YEAR", year, 1, 1);
1884
+ r.register("MONTH", month, 1, 1);
1885
+ r.register("DAY", day, 1, 1);
1886
+ r.register("HOUR", hour, 1, 1);
1887
+ r.register("MINUTE", minute, 1, 1);
1888
+ r.register("SECOND", second, 1, 1);
1889
+ r.register("DATEVALUE", dateValue, 1, 1);
1890
+ r.register("DAYS", days, 2, 2);
1891
+ r.register("EDATE", edate, 2, 2);
1892
+ r.register("EOMONTH", eomonth, 2, 2);
1893
+ r.register("WEEKDAY", weekday, 1, 2);
1894
+ r.register("WEEKNUM", weeknum, 1, 2);
1895
+ r.register("NETWORKDAYS", networkdays, 2, 3);
1896
+ r.register("DATEDIF", datedif, 3, 3);
1897
+ }
1898
+ function evalDate(a, c, idx) {
1899
+ const r = FormulaHelper.evalDouble(a[idx], c);
1900
+ if (!r.ok) return r;
1901
+ try {
1902
+ return { ok: true, date: fromOA(r.value) };
1903
+ } catch {
1904
+ return { ok: false, error: FormulaValue.errorValue };
1905
+ }
1906
+ }
1907
+ function now() {
1908
+ return FormulaValue.number(toOA(/* @__PURE__ */ new Date()));
1909
+ }
1910
+ function today() {
1911
+ const d = /* @__PURE__ */ new Date();
1912
+ return FormulaValue.number(toOA(new Date(d.getFullYear(), d.getMonth(), d.getDate())));
1913
+ }
1914
+ function date_(a, c) {
1915
+ const y = FormulaHelper.evalDouble(a[0], c);
1916
+ if (!y.ok) return y.error;
1917
+ const m = FormulaHelper.evalDouble(a[1], c);
1918
+ if (!m.ok) return m.error;
1919
+ const d = FormulaHelper.evalDouble(a[2], c);
1920
+ if (!d.ok) return d.error;
1921
+ try {
1922
+ return FormulaValue.number(toOA(new Date(Math.round(y.value), Math.round(m.value) - 1, Math.round(d.value))));
1923
+ } catch {
1924
+ return FormulaValue.errorValue;
1925
+ }
1926
+ }
1927
+ function year(a, c) {
1928
+ const r = evalDate(a, c, 0);
1929
+ return r.ok ? FormulaValue.number(r.date.getFullYear()) : r.error;
1930
+ }
1931
+ function month(a, c) {
1932
+ const r = evalDate(a, c, 0);
1933
+ return r.ok ? FormulaValue.number(r.date.getMonth() + 1) : r.error;
1934
+ }
1935
+ function day(a, c) {
1936
+ const r = evalDate(a, c, 0);
1937
+ return r.ok ? FormulaValue.number(r.date.getDate()) : r.error;
1938
+ }
1939
+ function hour(a, c) {
1940
+ const r = evalDate(a, c, 0);
1941
+ return r.ok ? FormulaValue.number(r.date.getHours()) : r.error;
1942
+ }
1943
+ function minute(a, c) {
1944
+ const r = evalDate(a, c, 0);
1945
+ return r.ok ? FormulaValue.number(r.date.getMinutes()) : r.error;
1946
+ }
1947
+ function second(a, c) {
1948
+ const r = evalDate(a, c, 0);
1949
+ return r.ok ? FormulaValue.number(r.date.getSeconds()) : r.error;
1950
+ }
1951
+ function dateValue(a, c) {
1952
+ const r = FormulaHelper.evalString(a[0], c);
1953
+ if (!r.ok) return r.error;
1954
+ const d = new Date(r.value);
1955
+ if (isNaN(d.getTime())) return FormulaValue.errorValue;
1956
+ return FormulaValue.number(toOA(d));
1957
+ }
1958
+ function days(a, c) {
1959
+ const d1 = evalDate(a, c, 0);
1960
+ if (!d1.ok) return d1.error;
1961
+ const d2 = evalDate(a, c, 1);
1962
+ if (!d2.ok) return d2.error;
1963
+ return FormulaValue.number(Math.round((d1.date.getTime() - d2.date.getTime()) / MS_PER_DAY));
1964
+ }
1965
+ function edate(a, c) {
1966
+ const d = evalDate(a, c, 0);
1967
+ if (!d.ok) return d.error;
1968
+ const m = FormulaHelper.evalDouble(a[1], c);
1969
+ if (!m.ok) return m.error;
1970
+ const result = new Date(d.date.getFullYear(), d.date.getMonth() + Math.round(m.value), d.date.getDate());
1971
+ return isNaN(result.getTime()) ? FormulaValue.errorNum : FormulaValue.number(toOA(result));
1972
+ }
1973
+ function eomonth(a, c) {
1974
+ const d = evalDate(a, c, 0);
1975
+ if (!d.ok) return d.error;
1976
+ const m = FormulaHelper.evalDouble(a[1], c);
1977
+ if (!m.ok) return m.error;
1978
+ const target = new Date(d.date.getFullYear(), d.date.getMonth() + Math.round(m.value) + 1, 0);
1979
+ return isNaN(target.getTime()) ? FormulaValue.errorNum : FormulaValue.number(toOA(target));
1980
+ }
1981
+ function weekday(a, c) {
1982
+ const d = evalDate(a, c, 0);
1983
+ if (!d.ok) return d.error;
1984
+ let type = 1;
1985
+ if (a.length > 1) {
1986
+ const r = FormulaHelper.evalDouble(a[1], c);
1987
+ if (!r.ok) return r.error;
1988
+ type = Math.round(r.value);
1989
+ }
1990
+ const dow = d.date.getDay();
1991
+ switch (type) {
1992
+ case 1:
1993
+ return FormulaValue.number(dow === 0 ? 1 : dow + 1);
1994
+ // Sun=1
1995
+ case 2:
1996
+ return FormulaValue.number(dow === 0 ? 7 : dow);
1997
+ // Mon=1
1998
+ case 3:
1999
+ return FormulaValue.number(dow === 0 ? 6 : dow - 1);
2000
+ // Mon=0
2001
+ default:
2002
+ return FormulaValue.errorNum;
2003
+ }
2004
+ }
2005
+ function weeknum(a, c) {
2006
+ const d = evalDate(a, c, 0);
2007
+ if (!d.ok) return d.error;
2008
+ const jan1 = new Date(d.date.getFullYear(), 0, 1);
2009
+ const days_ = Math.floor((d.date.getTime() - jan1.getTime()) / MS_PER_DAY);
2010
+ return FormulaValue.number(Math.ceil((days_ + jan1.getDay() + 1) / 7));
2011
+ }
2012
+ function networkdays(a, c) {
2013
+ const start = evalDate(a, c, 0);
2014
+ if (!start.ok) return start.error;
2015
+ const end = evalDate(a, c, 1);
2016
+ if (!end.ok) return end.error;
2017
+ const holidays = /* @__PURE__ */ new Set();
2018
+ if (a.length > 2) {
2019
+ const hv = a[2].evaluate(c);
2020
+ if (hv.isError) return hv;
2021
+ const items = hv.isArray ? [...hv.arrayVal.values()] : [hv];
2022
+ for (const item of items) {
2023
+ if (item.isBlank) continue;
2024
+ const r = item.tryAsDouble();
2025
+ if (!r.ok) return FormulaValue.errorValue;
2026
+ holidays.add(Math.floor(r.value));
2027
+ }
2028
+ }
2029
+ const dir = start.date <= end.date ? 1 : -1;
2030
+ let count2 = 0;
2031
+ const cur = new Date(start.date);
2032
+ while (dir > 0 ? cur <= end.date : cur >= end.date) {
2033
+ const dow = cur.getDay();
2034
+ const oa = Math.floor(toOA(cur));
2035
+ if (dow !== 0 && dow !== 6 && !holidays.has(oa)) count2++;
2036
+ cur.setDate(cur.getDate() + dir);
2037
+ }
2038
+ return FormulaValue.number(count2 * dir);
2039
+ }
2040
+ function datedif(a, c) {
2041
+ const start = evalDate(a, c, 0);
2042
+ if (!start.ok) return start.error;
2043
+ const end = evalDate(a, c, 1);
2044
+ if (!end.ok) return end.error;
2045
+ const unit = FormulaHelper.evalString(a[2], c);
2046
+ if (!unit.ok) return unit.error;
2047
+ const s = start.date, e = end.date;
2048
+ if (s > e) return FormulaValue.errorNum;
2049
+ switch (unit.value.toUpperCase()) {
2050
+ case "Y":
2051
+ return FormulaValue.number(e.getFullYear() - s.getFullYear() - (e.getMonth() < s.getMonth() || e.getMonth() === s.getMonth() && e.getDate() < s.getDate() ? 1 : 0));
2052
+ case "M":
2053
+ return FormulaValue.number((e.getFullYear() - s.getFullYear()) * 12 + e.getMonth() - s.getMonth() - (e.getDate() < s.getDate() ? 1 : 0));
2054
+ case "D":
2055
+ return FormulaValue.number(Math.round((e.getTime() - s.getTime()) / MS_PER_DAY));
2056
+ case "MD":
2057
+ return FormulaValue.number(e.getDate() >= s.getDate() ? e.getDate() - s.getDate() : new Date(s.getFullYear(), s.getMonth() + 1, 0).getDate() - s.getDate() + e.getDate());
2058
+ case "YM":
2059
+ return FormulaValue.number((e.getMonth() - s.getMonth() + 12) % 12 - (e.getDate() < s.getDate() ? 1 : 0));
2060
+ case "YD": {
2061
+ const sameYearEnd = new Date(e.getFullYear(), s.getMonth(), s.getDate());
2062
+ return FormulaValue.number(Math.round((e.getTime() - sameYearEnd.getTime()) / MS_PER_DAY));
2063
+ }
2064
+ default:
2065
+ return FormulaValue.errorNum;
2066
+ }
2067
+ }
2068
+ function registerLookup(r) {
2069
+ r.register("VLOOKUP", vlookup, 3, 4);
2070
+ r.register("HLOOKUP", hlookup, 3, 4);
2071
+ r.register("INDEX", index_, 2, 3);
2072
+ r.register("MATCH", match, 2, 3);
2073
+ r.register("CHOOSE", choose, 2);
2074
+ r.register("ROW", row, 0, 1);
2075
+ r.register("COLUMN", column, 0, 1);
2076
+ r.register("ROWS", rows, 1, 1);
2077
+ r.register("COLUMNS", columns, 1, 1);
2078
+ r.register("OFFSET", offset, 3, 5, true);
2079
+ }
2080
+ function num2(a, c, i) {
2081
+ const r = FormulaHelper.evalDouble(a[i], c);
2082
+ return r.ok ? { ok: true, n: r.value } : { ok: false, e: r.error };
2083
+ }
2084
+ function vlookup(a, c) {
2085
+ const lookupVal = a[0].evaluate(c);
2086
+ if (lookupVal.isError) return lookupVal;
2087
+ const tableVal = a[1].evaluate(c);
2088
+ if (tableVal.isError) return tableVal;
2089
+ if (!tableVal.isArray) return FormulaValue.errorRef;
2090
+ const ci = num2(a, c, 2);
2091
+ if (!ci.ok) return ci.e;
2092
+ const colIdx = Math.round(ci.n) - 1;
2093
+ let exactMatch = true;
2094
+ if (a.length > 3) {
2095
+ const mv = a[3].evaluate(c);
2096
+ if (mv.isError) return mv;
2097
+ exactMatch = !mv.coerceToBool().booleanValue;
2098
+ }
2099
+ const tbl = tableVal.arrayVal;
2100
+ if (colIdx < 0 || colIdx >= tbl.columns) return FormulaValue.errorRef;
2101
+ if (exactMatch) {
2102
+ for (let r = 0; r < tbl.rows; r++) {
2103
+ if (FormulaValue.areEqual(tbl.get(r, 0), lookupVal)) return tbl.get(r, colIdx);
2104
+ }
2105
+ return FormulaValue.errorNA;
2106
+ }
2107
+ let best = -1;
2108
+ for (let r = 0; r < tbl.rows; r++) {
2109
+ if (FormulaValue.compare(tbl.get(r, 0), lookupVal) <= 0) best = r;
2110
+ else break;
2111
+ }
2112
+ return best >= 0 ? tbl.get(best, colIdx) : FormulaValue.errorNA;
2113
+ }
2114
+ function hlookup(a, c) {
2115
+ const lookupVal = a[0].evaluate(c);
2116
+ if (lookupVal.isError) return lookupVal;
2117
+ const tableVal = a[1].evaluate(c);
2118
+ if (tableVal.isError) return tableVal;
2119
+ if (!tableVal.isArray) return FormulaValue.errorRef;
2120
+ const ri = num2(a, c, 2);
2121
+ if (!ri.ok) return ri.e;
2122
+ const rowIdx = Math.round(ri.n) - 1;
2123
+ let exactMatch = true;
2124
+ if (a.length > 3) {
2125
+ const mv = a[3].evaluate(c);
2126
+ if (mv.isError) return mv;
2127
+ exactMatch = !mv.coerceToBool().booleanValue;
2128
+ }
2129
+ const tbl = tableVal.arrayVal;
2130
+ if (rowIdx < 0 || rowIdx >= tbl.rows) return FormulaValue.errorRef;
2131
+ if (exactMatch) {
2132
+ for (let col = 0; col < tbl.columns; col++) {
2133
+ if (FormulaValue.areEqual(tbl.get(0, col), lookupVal)) return tbl.get(rowIdx, col);
2134
+ }
2135
+ return FormulaValue.errorNA;
2136
+ }
2137
+ let best = -1;
2138
+ for (let col = 0; col < tbl.columns; col++) {
2139
+ if (FormulaValue.compare(tbl.get(0, col), lookupVal) <= 0) best = col;
2140
+ else break;
2141
+ }
2142
+ return best >= 0 ? tbl.get(rowIdx, best) : FormulaValue.errorNA;
2143
+ }
2144
+ function index_(a, c) {
2145
+ const arrVal = a[0].evaluate(c);
2146
+ if (arrVal.isError) return arrVal;
2147
+ const rv = num2(a, c, 1);
2148
+ if (!rv.ok) return rv.e;
2149
+ const rowIdx = Math.round(rv.n) - 1;
2150
+ let colIdx = 0;
2151
+ if (a.length > 2) {
2152
+ const cv = num2(a, c, 2);
2153
+ if (!cv.ok) return cv.e;
2154
+ colIdx = Math.round(cv.n) - 1;
2155
+ }
2156
+ if (!arrVal.isArray) return rowIdx === 0 && colIdx === 0 ? arrVal : FormulaValue.errorRef;
2157
+ const arr = arrVal.arrayVal;
2158
+ if (rowIdx < 0 || rowIdx >= arr.rows || colIdx < 0 || colIdx >= arr.columns) {
2159
+ return FormulaValue.errorRef;
2160
+ }
2161
+ return arr.get(rowIdx, colIdx);
2162
+ }
2163
+ function match(a, c) {
2164
+ const lookupVal = a[0].evaluate(c);
2165
+ if (lookupVal.isError) return lookupVal;
2166
+ const arrVal = a[1].evaluate(c);
2167
+ if (arrVal.isError) return arrVal;
2168
+ let matchType = 1;
2169
+ if (a.length > 2) {
2170
+ const r = num2(a, c, 2);
2171
+ if (!r.ok) return r.e;
2172
+ matchType = Math.round(r.n);
2173
+ }
2174
+ if (!arrVal.isArray) {
2175
+ return FormulaValue.areEqual(arrVal, lookupVal) ? FormulaValue.one : FormulaValue.errorNA;
2176
+ }
2177
+ const arr = arrVal.arrayVal;
2178
+ const len2 = arr.length;
2179
+ if (matchType === 0) {
2180
+ for (let i = 0; i < len2; i++) {
2181
+ if (FormulaValue.areEqual(arr.getFlat(i), lookupVal)) return FormulaValue.number(i + 1);
2182
+ }
2183
+ return FormulaValue.errorNA;
2184
+ }
2185
+ if (matchType === 1) {
2186
+ let best2 = -1;
2187
+ for (let i = 0; i < len2; i++) {
2188
+ if (FormulaValue.compare(arr.getFlat(i), lookupVal) <= 0) best2 = i;
2189
+ else break;
2190
+ }
2191
+ return best2 >= 0 ? FormulaValue.number(best2 + 1) : FormulaValue.errorNA;
2192
+ }
2193
+ let best = -1;
2194
+ for (let i = 0; i < len2; i++) {
2195
+ if (FormulaValue.compare(arr.getFlat(i), lookupVal) >= 0) best = i;
2196
+ else break;
2197
+ }
2198
+ return best >= 0 ? FormulaValue.number(best + 1) : FormulaValue.errorNA;
2199
+ }
2200
+ function choose(a, c) {
2201
+ const iv = num2(a, c, 0);
2202
+ if (!iv.ok) return iv.e;
2203
+ const idx = Math.round(iv.n);
2204
+ if (idx < 1 || idx >= a.length) return FormulaValue.errorValue;
2205
+ return a[idx].evaluate(c);
2206
+ }
2207
+ function row(a, c) {
2208
+ if (a.length === 0) return FormulaValue.number(c.formulaRow || 1);
2209
+ const node = a[0];
2210
+ if (node instanceof CellReferenceNode) {
2211
+ return FormulaValue.number(parseCellRef(node.reference).row);
2212
+ }
2213
+ if (node instanceof RangeReferenceNode) {
2214
+ return FormulaValue.number(parseCellRef(node.startRef).row);
2215
+ }
2216
+ return FormulaValue.errorValue;
2217
+ }
2218
+ function column(a, c) {
2219
+ if (a.length === 0) return FormulaValue.number(c.formulaCol || 1);
2220
+ const node = a[0];
2221
+ if (node instanceof CellReferenceNode) {
2222
+ return FormulaValue.number(parseCellRef(node.reference).column);
2223
+ }
2224
+ if (node instanceof RangeReferenceNode) {
2225
+ return FormulaValue.number(parseCellRef(node.startRef).column);
2226
+ }
2227
+ return FormulaValue.errorValue;
2228
+ }
2229
+ function rows(a, c) {
2230
+ if (a[0] instanceof RangeReferenceNode) {
2231
+ const b = c.getRangeBounds(a[0].startRef, a[0].endRef);
2232
+ return FormulaValue.number(b.endRow - b.startRow + 1);
2233
+ }
2234
+ const v = a[0].evaluate(c);
2235
+ return v.isArray ? FormulaValue.number(v.arrayVal.rows) : FormulaValue.one;
2236
+ }
2237
+ function columns(a, c) {
2238
+ if (a[0] instanceof RangeReferenceNode) {
2239
+ const b = c.getRangeBounds(a[0].startRef, a[0].endRef);
2240
+ return FormulaValue.number(b.endCol - b.startCol + 1);
2241
+ }
2242
+ const v = a[0].evaluate(c);
2243
+ return v.isArray ? FormulaValue.number(v.arrayVal.columns) : FormulaValue.one;
2244
+ }
2245
+ function offset(a, c) {
2246
+ const baseNode = a[0];
2247
+ let baseRef;
2248
+ if (baseNode instanceof CellReferenceNode) baseRef = baseNode.reference;
2249
+ else if (baseNode instanceof RangeReferenceNode) baseRef = baseNode.startRef;
2250
+ else return FormulaValue.errorValue;
2251
+ const base = parseCellRef(baseRef);
2252
+ const ro = FormulaHelper.evalDouble(a[1], c);
2253
+ if (!ro.ok) return ro.error;
2254
+ const co = FormulaHelper.evalDouble(a[2], c);
2255
+ if (!co.ok) return co.error;
2256
+ const newRow = base.row + Math.round(ro.value);
2257
+ const newCol = base.column + Math.round(co.value);
2258
+ if (newRow < 1 || newCol < 1) return FormulaValue.errorRef;
2259
+ let height = 1, width = 1;
2260
+ if (a.length > 3) {
2261
+ const h = FormulaHelper.evalDouble(a[3], c);
2262
+ if (!h.ok) return h.error;
2263
+ height = Math.round(h.value);
2264
+ }
2265
+ if (a.length > 4) {
2266
+ const w = FormulaHelper.evalDouble(a[4], c);
2267
+ if (!w.ok) return w.error;
2268
+ width = Math.round(w.value);
2269
+ }
2270
+ if (height === 1 && width === 1) return c.getCellValue(cellRefFromRowCol(newRow, newCol));
2271
+ return c.getRangeValues(
2272
+ cellRefFromRowCol(newRow, newCol),
2273
+ cellRefFromRowCol(newRow + height - 1, newCol + width - 1)
2274
+ );
2275
+ }
2276
+
2277
+ // src/functions/statistical-functions.ts
2278
+ function registerStatistical(r) {
2279
+ r.register("MEDIAN", median, 1);
2280
+ r.register("MODE", mode, 1);
2281
+ r.register("MODE.SNGL", mode, 1);
2282
+ r.register("STDEV", stdev, 1);
2283
+ r.register("STDEV.S", stdev, 1);
2284
+ r.register("STDEVP", stdevp, 1);
2285
+ r.register("STDEV.P", stdevp, 1);
2286
+ r.register("VAR", var_, 1);
2287
+ r.register("VAR.S", var_, 1);
2288
+ r.register("VARP", varp, 1);
2289
+ r.register("VAR.P", varp, 1);
2290
+ r.register("LARGE", large, 2, 2);
2291
+ r.register("SMALL", small, 2, 2);
2292
+ r.register("RANK", rank, 2, 3);
2293
+ r.register("RANK.EQ", rank, 2, 3);
2294
+ r.register("PERCENTILE", percentile, 2, 2);
2295
+ r.register("PERCENTILE.INC", percentile, 2, 2);
2296
+ r.register("MAXIFS", maxIfs, 3);
2297
+ r.register("MINIFS", minIfs, 3);
2298
+ }
2299
+ function variance(nums, population) {
2300
+ const mean = nums.reduce((s, n) => s + n, 0) / nums.length;
2301
+ const sumSq = nums.reduce((s, n) => s + (n - mean) ** 2, 0);
2302
+ return sumSq / (population ? nums.length : nums.length - 1);
2303
+ }
2304
+ function numsFromArray(v) {
2305
+ if (v.isArray) {
2306
+ return [...v.arrayVal.values()].filter((i) => i.isNumber).map((i) => i.numberValue);
2307
+ }
2308
+ return v.isNumber ? [v.numberValue] : [];
2309
+ }
2310
+ function num3(a, c, i) {
2311
+ const r = FormulaHelper.evalDouble(a[i], c);
2312
+ return r.ok ? { ok: true, n: r.value } : { ok: false, e: r.error };
2313
+ }
2314
+ function median(a, c) {
2315
+ const r = FormulaHelper.collectNumbers(a, c);
2316
+ if (!r.ok) return r.error;
2317
+ if (r.values.length === 0) return FormulaValue.errorNum;
2318
+ const sorted = [...r.values].sort((a2, b) => a2 - b);
2319
+ const mid2 = sorted.length >> 1;
2320
+ return FormulaValue.number(
2321
+ sorted.length % 2 === 0 ? (sorted[mid2 - 1] + sorted[mid2]) / 2 : sorted[mid2]
2322
+ );
2323
+ }
2324
+ function mode(a, c) {
2325
+ const r = FormulaHelper.collectNumbers(a, c);
2326
+ if (!r.ok) return r.error;
2327
+ if (r.values.length === 0) return FormulaValue.errorNA;
2328
+ const freq = /* @__PURE__ */ new Map();
2329
+ let maxCnt = 0;
2330
+ for (const n of r.values) {
2331
+ const cnt = (freq.get(n) ?? 0) + 1;
2332
+ freq.set(n, cnt);
2333
+ if (cnt > maxCnt) maxCnt = cnt;
2334
+ }
2335
+ if (maxCnt === 1) return FormulaValue.errorNA;
2336
+ for (const n of r.values) {
2337
+ if ((freq.get(n) ?? 0) === maxCnt) return FormulaValue.number(n);
2338
+ }
2339
+ return FormulaValue.errorNA;
2340
+ }
2341
+ function stdev(a, c) {
2342
+ const r = FormulaHelper.collectNumbers(a, c);
2343
+ if (!r.ok) return r.error;
2344
+ if (r.values.length < 2) return FormulaValue.errorDiv0;
2345
+ return FormulaValue.number(Math.sqrt(variance(r.values, false)));
2346
+ }
2347
+ function stdevp(a, c) {
2348
+ const r = FormulaHelper.collectNumbers(a, c);
2349
+ if (!r.ok) return r.error;
2350
+ if (r.values.length === 0) return FormulaValue.errorDiv0;
2351
+ return FormulaValue.number(Math.sqrt(variance(r.values, true)));
2352
+ }
2353
+ function var_(a, c) {
2354
+ const r = FormulaHelper.collectNumbers(a, c);
2355
+ if (!r.ok) return r.error;
2356
+ if (r.values.length < 2) return FormulaValue.errorDiv0;
2357
+ return FormulaValue.number(variance(r.values, false));
2358
+ }
2359
+ function varp(a, c) {
2360
+ const r = FormulaHelper.collectNumbers(a, c);
2361
+ if (!r.ok) return r.error;
2362
+ if (r.values.length === 0) return FormulaValue.errorDiv0;
2363
+ return FormulaValue.number(variance(r.values, true));
2364
+ }
2365
+ function large(a, c) {
2366
+ const arrV = a[0].evaluate(c);
2367
+ if (arrV.isError) return arrV;
2368
+ const kv = num3(a, c, 1);
2369
+ if (!kv.ok) return kv.e;
2370
+ const nums = numsFromArray(arrV).sort((a2, b) => b - a2);
2371
+ const k = Math.round(kv.n);
2372
+ if (k < 1 || k > nums.length) return FormulaValue.errorNum;
2373
+ return FormulaValue.number(nums[k - 1]);
2374
+ }
2375
+ function small(a, c) {
2376
+ const arrV = a[0].evaluate(c);
2377
+ if (arrV.isError) return arrV;
2378
+ const kv = num3(a, c, 1);
2379
+ if (!kv.ok) return kv.e;
2380
+ const nums = numsFromArray(arrV).sort((a2, b) => a2 - b);
2381
+ const k = Math.round(kv.n);
2382
+ if (k < 1 || k > nums.length) return FormulaValue.errorNum;
2383
+ return FormulaValue.number(nums[k - 1]);
2384
+ }
2385
+ function rank(a, c) {
2386
+ const nv = FormulaHelper.evalDouble(a[0], c);
2387
+ if (!nv.ok) return nv.error;
2388
+ const arrV = a[1].evaluate(c);
2389
+ if (arrV.isError) return arrV;
2390
+ let order = 0;
2391
+ if (a.length > 2) {
2392
+ const ov = num3(a, c, 2);
2393
+ if (!ov.ok) return ov.e;
2394
+ order = Math.round(ov.n);
2395
+ }
2396
+ const nums = numsFromArray(arrV).sort((a2, b) => order === 0 ? b - a2 : a2 - b);
2397
+ const idx = nums.indexOf(nv.value);
2398
+ return idx < 0 ? FormulaValue.errorNA : FormulaValue.number(idx + 1);
2399
+ }
2400
+ function percentile(a, c) {
2401
+ const arrV = a[0].evaluate(c);
2402
+ if (arrV.isError) return arrV;
2403
+ const kv = FormulaHelper.evalDouble(a[1], c);
2404
+ if (!kv.ok) return kv.error;
2405
+ if (kv.value < 0 || kv.value > 1) return FormulaValue.errorNum;
2406
+ const nums = numsFromArray(arrV).sort((a2, b) => a2 - b);
2407
+ if (nums.length === 0) return FormulaValue.errorNum;
2408
+ const n = (nums.length - 1) * kv.value;
2409
+ const lo = Math.floor(n), hi = Math.ceil(n);
2410
+ if (lo === hi) return FormulaValue.number(nums[lo]);
2411
+ return FormulaValue.number(nums[lo] + (nums[hi] - nums[lo]) * (n - lo));
2412
+ }
2413
+ function maxIfs(a, c) {
2414
+ return ifsAggregate(a, c, "max");
2415
+ }
2416
+ function minIfs(a, c) {
2417
+ return ifsAggregate(a, c, "min");
2418
+ }
2419
+ function ifsAggregate(a, c, mode2) {
2420
+ if (a.length < 3 || (a.length - 1) % 2 !== 0) return FormulaValue.errorValue;
2421
+ const mainRange = a[0].evaluate(c);
2422
+ if (mainRange.isError) return mainRange;
2423
+ if (!mainRange.isArray) return FormulaValue.errorValue;
2424
+ const arr = mainRange.arrayVal;
2425
+ const len2 = arr.length;
2426
+ const mask = new Uint8Array(len2).fill(1);
2427
+ for (let p = 1; p + 1 < a.length; p += 2) {
2428
+ const cr = a[p].evaluate(c);
2429
+ if (cr.isError) return cr;
2430
+ const criteria = a[p + 1].evaluate(c).asText();
2431
+ const crArr = cr.isArray ? cr.arrayVal : null;
2432
+ for (let i = 0; i < len2; i++) {
2433
+ if (!mask[i]) continue;
2434
+ const cv = crArr ? crArr.getFlat(i) : cr;
2435
+ if (!FormulaHelper.matchesCriteria(cv, criteria)) mask[i] = 0;
2436
+ }
2437
+ }
2438
+ let result = mode2 === "max" ? -Infinity : Infinity;
2439
+ let found = false;
2440
+ for (let i = 0; i < len2; i++) {
2441
+ if (!mask[i]) continue;
2442
+ const r = arr.getFlat(i).tryAsDouble();
2443
+ if (!r.ok) continue;
2444
+ if (mode2 === "max" ? r.value > result : r.value < result) {
2445
+ result = r.value;
2446
+ found = true;
2447
+ }
2448
+ }
2449
+ return found ? FormulaValue.number(result) : FormulaValue.zero;
2450
+ }
2451
+
2452
+ // src/functions/info-functions.ts
2453
+ function registerInfo(r) {
2454
+ r.register("ISBLANK", isBlank, 1, 1);
2455
+ r.register("ISNUMBER", isNumber, 1, 1);
2456
+ r.register("ISTEXT", isText, 1, 1);
2457
+ r.register("ISERROR", isError, 1, 1);
2458
+ r.register("ISERR", isErr, 1, 1);
2459
+ r.register("ISLOGICAL", isLogical, 1, 1);
2460
+ r.register("ISNA", isNa, 1, 1);
2461
+ r.register("ISNONTEXT", isNonText, 1, 1);
2462
+ r.register("NA", na, 0, 0);
2463
+ r.register("TYPE", type_, 1, 1);
2464
+ r.register("N", n_, 1, 1);
2465
+ r.register("ISODD", isOdd, 1, 1);
2466
+ r.register("ISEVEN", isEven, 1, 1);
2467
+ r.register("ERROR.TYPE", errorType, 1, 1);
2468
+ }
2469
+ function isBlank(a, c) {
2470
+ return FormulaValue.boolean(a[0].evaluate(c).isBlank);
2471
+ }
2472
+ function isNumber(a, c) {
2473
+ return FormulaValue.boolean(a[0].evaluate(c).isNumber);
2474
+ }
2475
+ function isText(a, c) {
2476
+ const v = a[0].evaluate(c);
2477
+ return FormulaValue.boolean(v.isText && v.textValue.length > 0);
2478
+ }
2479
+ function isError(a, c) {
2480
+ return FormulaValue.boolean(a[0].evaluate(c).isError);
2481
+ }
2482
+ function isErr(a, c) {
2483
+ const v = a[0].evaluate(c);
2484
+ return FormulaValue.boolean(v.isError && v.errorCode !== 7 /* NA */);
2485
+ }
2486
+ function isLogical(a, c) {
2487
+ return FormulaValue.boolean(a[0].evaluate(c).isBoolean);
2488
+ }
2489
+ function isNa(a, c) {
2490
+ const v = a[0].evaluate(c);
2491
+ return FormulaValue.boolean(v.isError && v.errorCode === 7 /* NA */);
2492
+ }
2493
+ function isNonText(a, c) {
2494
+ return FormulaValue.boolean(!a[0].evaluate(c).isText);
2495
+ }
2496
+ function na() {
2497
+ return FormulaValue.errorNA;
2498
+ }
2499
+ function type_(a, c) {
2500
+ const v = a[0].evaluate(c);
2501
+ const t = v.isNumber || v.isBlank ? 1 : v.isText ? 2 : v.isBoolean ? 4 : v.isError ? 16 : v.isArray ? 64 : 1;
2502
+ return FormulaValue.number(t);
2503
+ }
2504
+ function n_(a, c) {
2505
+ const v = a[0].evaluate(c);
2506
+ if (v.isNumber) return v;
2507
+ if (v.isBoolean) return FormulaValue.number(v.booleanValue ? 1 : 0);
2508
+ return FormulaValue.zero;
2509
+ }
2510
+ function isOdd(a, c) {
2511
+ const r = FormulaHelper.evalDouble(a[0], c);
2512
+ if (!r.ok) return r.error;
2513
+ return FormulaValue.boolean(Math.abs(Math.trunc(r.value)) % 2 === 1);
2514
+ }
2515
+ function isEven(a, c) {
2516
+ const r = FormulaHelper.evalDouble(a[0], c);
2517
+ if (!r.ok) return r.error;
2518
+ return FormulaValue.boolean(Math.trunc(r.value) % 2 === 0);
2519
+ }
2520
+ function errorType(a, c) {
2521
+ const v = a[0].evaluate(c);
2522
+ if (!v.isError) return FormulaValue.errorNA;
2523
+ const map = {
2524
+ [1 /* Null */]: 1,
2525
+ [2 /* Div0 */]: 2,
2526
+ [3 /* Value */]: 3,
2527
+ [4 /* Ref */]: 4,
2528
+ [5 /* Name */]: 5,
2529
+ [6 /* Num */]: 6,
2530
+ [7 /* NA */]: 7
2531
+ };
2532
+ return FormulaValue.number(map[v.errorCode] ?? 7);
2533
+ }
2534
+
2535
+ // src/function-registry.ts
2536
+ var _default, _functions, _FunctionRegistry_instances, registerBuiltIns_fn;
2537
+ var _FunctionRegistry = class _FunctionRegistry {
2538
+ constructor() {
2539
+ __privateAdd(this, _FunctionRegistry_instances);
2540
+ __privateAdd(this, _functions, /* @__PURE__ */ new Map());
2541
+ }
2542
+ /** Lazily-created default registry with all built-in functions registered. */
2543
+ static get default() {
2544
+ var _a;
2545
+ if (!__privateGet(_FunctionRegistry, _default)) {
2546
+ __privateSet(_FunctionRegistry, _default, new _FunctionRegistry());
2547
+ __privateMethod(_a = __privateGet(_FunctionRegistry, _default), _FunctionRegistry_instances, registerBuiltIns_fn).call(_a);
2548
+ }
2549
+ return __privateGet(_FunctionRegistry, _default);
2550
+ }
2551
+ /** Registers a function. Name is normalised to UPPERCASE. */
2552
+ register(name, handler, minArgs = 0, maxArgs = -1, isVolatile = false) {
2553
+ __privateGet(this, _functions).set(name.toUpperCase(), {
2554
+ name: name.toUpperCase(),
2555
+ minArgs,
2556
+ maxArgs,
2557
+ isVolatile,
2558
+ handler
2559
+ });
2560
+ }
2561
+ /** Executes a function by name with argument validation. */
2562
+ execute(name, args, ctx) {
2563
+ const def = __privateGet(this, _functions).get(name.toUpperCase());
2564
+ if (!def) return FormulaValue.errorName;
2565
+ if (args.length < def.minArgs) return FormulaValue.errorValue;
2566
+ if (def.maxArgs >= 0 && args.length > def.maxArgs) return FormulaValue.errorValue;
2567
+ try {
2568
+ return def.handler(args, ctx);
2569
+ } catch {
2570
+ return FormulaValue.errorValue;
2571
+ }
2572
+ }
2573
+ /** Returns true if the named function is volatile (NOW, RAND, etc.). */
2574
+ isVolatile(name) {
2575
+ return __privateGet(this, _functions).get(name.toUpperCase())?.isVolatile ?? false;
2576
+ }
2577
+ /** Returns true if the function is registered. */
2578
+ has(name) {
2579
+ return __privateGet(this, _functions).has(name.toUpperCase());
2580
+ }
2581
+ };
2582
+ _default = new WeakMap();
2583
+ _functions = new WeakMap();
2584
+ _FunctionRegistry_instances = new WeakSet();
2585
+ registerBuiltIns_fn = function() {
2586
+ registerMath(this);
2587
+ registerText(this);
2588
+ registerLogical(this);
2589
+ registerDate(this);
2590
+ registerLookup(this);
2591
+ registerStatistical(this);
2592
+ registerInfo(this);
2593
+ };
2594
+ __privateAdd(_FunctionRegistry, _default);
2595
+ var FunctionRegistry = _FunctionRegistry;
2596
+ var FormulaHelper;
2597
+ ((FormulaHelper2) => {
2598
+ function evalDouble(node, ctx) {
2599
+ const v = node.evaluate(ctx);
2600
+ if (v.isError) return { ok: false, error: v };
2601
+ const r = v.tryAsDouble();
2602
+ if (!r.ok) return { ok: false, error: FormulaValue.errorValue };
2603
+ return { ok: true, value: r.value };
2604
+ }
2605
+ FormulaHelper2.evalDouble = evalDouble;
2606
+ function evalString(node, ctx) {
2607
+ const v = node.evaluate(ctx);
2608
+ if (v.isError) return { ok: false, error: v };
2609
+ return { ok: true, value: v.asText() };
2610
+ }
2611
+ FormulaHelper2.evalString = evalString;
2612
+ function collectNumbers(args, ctx) {
2613
+ const nums = [];
2614
+ for (const arg of args) {
2615
+ const v = arg.evaluate(ctx);
2616
+ if (v.isError) return { ok: false, error: v };
2617
+ if (v.isArray) {
2618
+ for (const item of v.arrayVal.values()) {
2619
+ if (item.isBlank || item.isText) continue;
2620
+ if (item.isError) return { ok: false, error: item };
2621
+ const r = item.tryAsDouble();
2622
+ if (r.ok) nums.push(r.value);
2623
+ }
2624
+ } else if (!v.isBlank && !v.isText) {
2625
+ const r = v.tryAsDouble();
2626
+ if (!r.ok) return { ok: false, error: FormulaValue.errorValue };
2627
+ nums.push(r.value);
2628
+ }
2629
+ }
2630
+ return { ok: true, values: nums };
2631
+ }
2632
+ FormulaHelper2.collectNumbers = collectNumbers;
2633
+ function flattenArgs(args, ctx) {
2634
+ const result = [];
2635
+ for (const arg of args) {
2636
+ const v = arg.evaluate(ctx);
2637
+ if (v.isArray) {
2638
+ for (const item of v.arrayVal.values()) result.push(item);
2639
+ } else {
2640
+ result.push(v);
2641
+ }
2642
+ }
2643
+ return result;
2644
+ }
2645
+ FormulaHelper2.flattenArgs = flattenArgs;
2646
+ function matchesCriteria(value2, criteria) {
2647
+ criteria = criteria.trim();
2648
+ const opMatch = /^(>=|<=|<>|>|<|=)(.*)$/.exec(criteria);
2649
+ if (opMatch) {
2650
+ const op = opMatch[1];
2651
+ const rhs = opMatch[2];
2652
+ const rhsVal = parseFloat(rhs);
2653
+ const rhsNum = isNaN(rhsVal) ? null : rhsVal;
2654
+ const cmp = rhsNum !== null ? FormulaValue.compare(value2, FormulaValue.number(rhsNum)) : FormulaValue.compare(value2, FormulaValue.text(rhs));
2655
+ switch (op) {
2656
+ case ">":
2657
+ return cmp > 0;
2658
+ case ">=":
2659
+ return cmp >= 0;
2660
+ case "<":
2661
+ return cmp < 0;
2662
+ case "<=":
2663
+ return cmp <= 0;
2664
+ case "<>":
2665
+ return !FormulaValue.areEqual(value2, rhsNum !== null ? FormulaValue.number(rhsNum) : FormulaValue.text(rhs));
2666
+ case "=":
2667
+ return FormulaValue.areEqual(value2, rhsNum !== null ? FormulaValue.number(rhsNum) : FormulaValue.text(rhs));
2668
+ }
2669
+ }
2670
+ if (criteria.includes("*") || criteria.includes("?")) {
2671
+ const pattern = wildcardToRegex(criteria);
2672
+ return pattern.test(value2.asText());
2673
+ }
2674
+ const num4 = parseFloat(criteria);
2675
+ if (!isNaN(num4)) {
2676
+ return FormulaValue.areEqual(value2, FormulaValue.number(num4));
2677
+ }
2678
+ return value2.asText().toUpperCase() === criteria.toUpperCase();
2679
+ }
2680
+ FormulaHelper2.matchesCriteria = matchesCriteria;
2681
+ function wildcardToRegex(pattern) {
2682
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
2683
+ return new RegExp(`^${escaped}$`, "i");
2684
+ }
2685
+ })(FormulaHelper || (FormulaHelper = {}));
2686
+
2687
+ // src/formula-context.ts
2688
+ var _sheet, _functions2, _evaluating;
2689
+ var _FormulaContext = class _FormulaContext {
2690
+ constructor(sheet, formulaRow = 0, formulaCol = 0, evaluating, registry) {
2691
+ __privateAdd(this, _sheet);
2692
+ __privateAdd(this, _functions2);
2693
+ __privateAdd(this, _evaluating);
2694
+ __privateSet(this, _sheet, sheet);
2695
+ this.formulaRow = formulaRow;
2696
+ this.formulaCol = formulaCol;
2697
+ __privateSet(this, _evaluating, evaluating ?? /* @__PURE__ */ new Set());
2698
+ __privateSet(this, _functions2, registry ?? FunctionRegistry.default);
2699
+ }
2700
+ get worksheet() {
2701
+ return __privateGet(this, _sheet);
2702
+ }
2703
+ // ── Cell/Range resolution ─────────────────────────────────────────────────
2704
+ getCellValue(cellReference) {
2705
+ const norm = cellReference.replace(/\$/g, "").toUpperCase();
2706
+ if (__privateGet(this, _evaluating).has(norm)) return FormulaValue.errorRef;
2707
+ __privateGet(this, _evaluating).add(norm);
2708
+ try {
2709
+ const raw = __privateGet(this, _sheet).getCellValue(cellReference);
2710
+ return FormulaValue.fromObjectSync(raw);
2711
+ } finally {
2712
+ __privateGet(this, _evaluating).delete(norm);
2713
+ }
2714
+ }
2715
+ getRangeValues(startRef, endRef) {
2716
+ const s = parseCellRef(startRef);
2717
+ const e = parseCellRef(endRef);
2718
+ const rows2 = e.row - s.row + 1;
2719
+ const cols = e.column - s.column + 1;
2720
+ const arr = new ArrayValue(rows2, cols);
2721
+ for (let r = 0; r < rows2; r++) {
2722
+ for (let c = 0; c < cols; c++) {
2723
+ const ref = cellRefFromRowCol(s.row + r, s.column + c);
2724
+ arr.set(r, c, this.getCellValue(ref));
2725
+ }
2726
+ }
2727
+ return FormulaValue.array(arr);
2728
+ }
2729
+ getSheetCellValue(sheetName, cellReference) {
2730
+ if (!this.workbook) return FormulaValue.errorRef;
2731
+ try {
2732
+ const sheet = this.workbook.getWorksheet(sheetName);
2733
+ const ctx = new _FormulaContext(sheet, this.formulaRow, this.formulaCol, __privateGet(this, _evaluating), __privateGet(this, _functions2));
2734
+ ctx.workbook = this.workbook;
2735
+ return ctx.getCellValue(cellReference);
2736
+ } catch {
2737
+ return FormulaValue.errorRef;
2738
+ }
2739
+ }
2740
+ getSheetRangeValues(sheetName, startRef, endRef) {
2741
+ if (!this.workbook) return FormulaValue.errorRef;
2742
+ try {
2743
+ const sheet = this.workbook.getWorksheet(sheetName);
2744
+ const ctx = new _FormulaContext(sheet, this.formulaRow, this.formulaCol, __privateGet(this, _evaluating), __privateGet(this, _functions2));
2745
+ ctx.workbook = this.workbook;
2746
+ return ctx.getRangeValues(startRef, endRef);
2747
+ } catch {
2748
+ return FormulaValue.errorRef;
2749
+ }
2750
+ }
2751
+ resolveNamedRange(_name) {
2752
+ return FormulaValue.errorName;
2753
+ }
2754
+ getRangeBounds(startRef, endRef) {
2755
+ const s = parseCellRef(startRef);
2756
+ const e = parseCellRef(endRef);
2757
+ return { startRow: s.row, startCol: s.column, endRow: e.row, endCol: e.column };
2758
+ }
2759
+ // ── Function dispatch ─────────────────────────────────────────────────────
2760
+ evaluateFunction(name, args) {
2761
+ return __privateGet(this, _functions2).execute(name, args, this);
2762
+ }
2763
+ };
2764
+ _sheet = new WeakMap();
2765
+ _functions2 = new WeakMap();
2766
+ _evaluating = new WeakMap();
2767
+ var FormulaContext = _FormulaContext;
2768
+
2769
+ // src/lru-cache.ts
2770
+ var _map, _capacity, _hits, _misses, _evictions;
2771
+ var LruCache = class {
2772
+ constructor(capacity) {
2773
+ __privateAdd(this, _map);
2774
+ __privateAdd(this, _capacity);
2775
+ __privateAdd(this, _hits, 0);
2776
+ __privateAdd(this, _misses, 0);
2777
+ __privateAdd(this, _evictions, 0);
2778
+ if (capacity <= 0) throw new RangeError("LruCache capacity must be > 0.");
2779
+ __privateSet(this, _capacity, capacity);
2780
+ __privateSet(this, _map, /* @__PURE__ */ new Map());
2781
+ }
2782
+ get capacity() {
2783
+ return __privateGet(this, _capacity);
2784
+ }
2785
+ get size() {
2786
+ return __privateGet(this, _map).size;
2787
+ }
2788
+ get hits() {
2789
+ return __privateGet(this, _hits);
2790
+ }
2791
+ get misses() {
2792
+ return __privateGet(this, _misses);
2793
+ }
2794
+ get evictions() {
2795
+ return __privateGet(this, _evictions);
2796
+ }
2797
+ get hitRate() {
2798
+ const total = __privateGet(this, _hits) + __privateGet(this, _misses);
2799
+ return total === 0 ? 0 : __privateGet(this, _hits) / total;
2800
+ }
2801
+ /**
2802
+ * Returns the value for key, or undefined if not present.
2803
+ * Moves the accessed key to the "most recently used" end.
2804
+ */
2805
+ get(key) {
2806
+ const value2 = __privateGet(this, _map).get(key);
2807
+ if (value2 === void 0) {
2808
+ __privateWrapper(this, _misses)._++;
2809
+ return void 0;
2810
+ }
2811
+ __privateGet(this, _map).delete(key);
2812
+ __privateGet(this, _map).set(key, value2);
2813
+ __privateWrapper(this, _hits)._++;
2814
+ return value2;
2815
+ }
2816
+ /**
2817
+ * Inserts or updates a key-value pair.
2818
+ * Evicts the least-recently-used entry if over capacity.
2819
+ */
2820
+ set(key, value2) {
2821
+ if (__privateGet(this, _map).has(key)) {
2822
+ __privateGet(this, _map).delete(key);
2823
+ } else if (__privateGet(this, _map).size >= __privateGet(this, _capacity)) {
2824
+ const oldest = __privateGet(this, _map).keys().next().value;
2825
+ __privateGet(this, _map).delete(oldest);
2826
+ __privateWrapper(this, _evictions)._++;
2827
+ }
2828
+ __privateGet(this, _map).set(key, value2);
2829
+ }
2830
+ /** Removes a key from the cache. Returns true if it existed. */
2831
+ delete(key) {
2832
+ return __privateGet(this, _map).delete(key);
2833
+ }
2834
+ /** Returns true if the key is present (does NOT update LRU order). */
2835
+ has(key) {
2836
+ return __privateGet(this, _map).has(key);
2837
+ }
2838
+ /** Removes all entries and resets statistics. */
2839
+ clear() {
2840
+ __privateGet(this, _map).clear();
2841
+ __privateSet(this, _hits, __privateSet(this, _misses, __privateSet(this, _evictions, 0)));
2842
+ }
2843
+ /** Resizes the cache, evicting oldest entries if necessary. */
2844
+ resize(newCapacity) {
2845
+ if (newCapacity <= 0) throw new RangeError("Capacity must be > 0.");
2846
+ __privateSet(this, _capacity, newCapacity);
2847
+ while (__privateGet(this, _map).size > newCapacity) {
2848
+ const oldest = __privateGet(this, _map).keys().next().value;
2849
+ __privateGet(this, _map).delete(oldest);
2850
+ __privateWrapper(this, _evictions)._++;
2851
+ }
2852
+ }
2853
+ };
2854
+ _map = new WeakMap();
2855
+ _capacity = new WeakMap();
2856
+ _hits = new WeakMap();
2857
+ _misses = new WeakMap();
2858
+ _evictions = new WeakMap();
2859
+
2860
+ // src/formula-evaluator.ts
2861
+ var DEFAULT_CACHE_CAPACITY = 1e4;
2862
+ var astCache = new LruCache(DEFAULT_CACHE_CAPACITY);
2863
+ function parseFormula(formula) {
2864
+ const stripped = formula.startsWith("=") ? formula.slice(1) : formula;
2865
+ const cached = astCache.get(stripped);
2866
+ if (cached !== void 0) return cached;
2867
+ const lexer = new FormulaLexer(stripped);
2868
+ const tokens = lexer.tokenize();
2869
+ const ast = new FormulaParser(tokens).parse();
2870
+ astCache.set(stripped, ast);
2871
+ return ast;
2872
+ }
2873
+ function evaluateFormula(formula, sheet, options) {
2874
+ if (!formula) return FormulaValue.blank;
2875
+ try {
2876
+ const ast = parseFormula(formula);
2877
+ const ctx = new FormulaContext(
2878
+ sheet,
2879
+ options?.formulaRow ?? 0,
2880
+ options?.formulaCol ?? 0
2881
+ );
2882
+ if (options?.workbook) ctx.workbook = options.workbook;
2883
+ return ast.evaluate(ctx);
2884
+ } catch {
2885
+ return FormulaValue.errorValue;
2886
+ }
2887
+ }
2888
+ function clearAstCache() {
2889
+ astCache.clear();
2890
+ }
2891
+ function getAstCacheStats() {
2892
+ return {
2893
+ size: astCache.size,
2894
+ hits: astCache.hits,
2895
+ misses: astCache.misses,
2896
+ hitRate: astCache.hitRate
2897
+ };
2898
+ }
2899
+ function setAstCacheCapacity(capacity) {
2900
+ astCache.resize(capacity);
2901
+ }
2902
+
2903
+ export { ArrayValue, BinaryOpNode, BinaryOperator, BlankNode, BooleanNode, CellReferenceNode, ErrorNode, FormulaContext, FormulaError, FormulaException, FormulaHelper, FormulaLexer, FormulaNode, FormulaParser, FormulaValue, FunctionCallNode, FunctionRegistry, ImplicitIntersectionNode, LruCache, NamedRangeNode, NumberNode, RangeReferenceNode, SheetCellReferenceNode, SheetRangeReferenceNode, StringNode, TokenType, UnaryOpNode, UnaryOperator, clearAstCache, evaluateFormula, getAstCacheStats, parseFormula, registerDate, registerInfo, registerLogical, registerLookup, registerMath, registerStatistical, registerText, setAstCacheCapacity };
2904
+ //# sourceMappingURL=index.js.map
2905
+ //# sourceMappingURL=index.js.map