reamkit 1.14.0 → 1.15.1

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.
Files changed (67) hide show
  1. package/README.md +34 -8
  2. package/dist/esm/core/converter/facade.d.ts +8 -1
  3. package/dist/esm/core/converter/facade.js +34 -8
  4. package/dist/esm/core/converter/ream.d.ts +1 -0
  5. package/dist/esm/core/converter/ream.js +13 -8
  6. package/dist/esm/core/ir/features.d.ts +1 -0
  7. package/dist/esm/core/ir/features.js +1 -0
  8. package/dist/esm/core/ir/sheet.d.ts +7 -0
  9. package/dist/esm/core/ole/cfb.d.ts +19 -0
  10. package/dist/esm/core/ole/cfb.js +188 -0
  11. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  12. package/dist/esm/core/spreadsheet-model/types.d.ts +20 -1
  13. package/dist/esm/excel/activex-parser.d.ts +9 -0
  14. package/dist/esm/excel/activex-parser.js +188 -0
  15. package/dist/esm/excel/conditional-format.d.ts +4 -2
  16. package/dist/esm/excel/conditional-format.js +138 -4
  17. package/dist/esm/excel/formula/context.d.ts +11 -0
  18. package/dist/esm/excel/formula/dates.d.ts +11 -0
  19. package/dist/esm/excel/formula/dates.js +46 -0
  20. package/dist/esm/excel/formula/eval.d.ts +11 -0
  21. package/dist/esm/excel/formula/eval.js +196 -0
  22. package/dist/esm/excel/formula/functions.d.ts +7 -0
  23. package/dist/esm/excel/formula/functions.js +1359 -0
  24. package/dist/esm/excel/formula/index.d.ts +14 -0
  25. package/dist/esm/excel/formula/index.js +17 -0
  26. package/dist/esm/excel/formula/lexer.d.ts +8 -0
  27. package/dist/esm/excel/formula/lexer.js +163 -0
  28. package/dist/esm/excel/formula/parser.d.ts +57 -0
  29. package/dist/esm/excel/formula/parser.js +274 -0
  30. package/dist/esm/excel/formula/value.d.ts +52 -0
  31. package/dist/esm/excel/formula/value.js +102 -0
  32. package/dist/esm/excel/number-format.d.ts +2 -0
  33. package/dist/esm/excel/number-format.js +5 -1
  34. package/dist/esm/excel/print-model.d.ts +3 -0
  35. package/dist/esm/excel/print-model.js +1 -1
  36. package/dist/esm/excel/sheet-to-flow.d.ts +4 -1
  37. package/dist/esm/excel/sheet-to-flow.js +46 -2
  38. package/dist/esm/excel/worksheet-parser.js +66 -0
  39. package/dist/esm/excel/xls/biff-chart.d.ts +8 -0
  40. package/dist/esm/excel/xls/biff-chart.js +121 -0
  41. package/dist/esm/excel/xls/biff-reader.d.ts +4 -0
  42. package/dist/esm/excel/xls/biff-reader.js +1418 -0
  43. package/dist/esm/excel/xls/biff-styles.d.ts +8 -0
  44. package/dist/esm/excel/xls/biff-styles.js +299 -0
  45. package/dist/esm/excel/xls/escher.d.ts +24 -0
  46. package/dist/esm/excel/xls/escher.js +171 -0
  47. package/dist/esm/excel/xls/xls-reader.d.ts +3 -0
  48. package/dist/esm/excel/xls/xls-reader.js +30 -0
  49. package/dist/esm/excel/xlsx-reader.d.ts +2 -1
  50. package/dist/esm/excel/xlsx-reader.js +28 -3
  51. package/dist/esm/excel/xlsx-to-pdf.d.ts +1 -0
  52. package/dist/esm/excel/xlsx-to-pdf.js +2 -2
  53. package/dist/esm/excel/xlsx-writer.js +2 -0
  54. package/dist/esm/pdf-reader/flow-build.d.ts +4 -2
  55. package/dist/esm/pdf-reader/flow-build.js +25 -2
  56. package/dist/esm/pdf-reader/layout.js +2 -2
  57. package/dist/esm/pdf-reader/tagged.js +2 -2
  58. package/dist/esm/pptx/ppt/ppt-reader.d.ts +4 -0
  59. package/dist/esm/pptx/ppt/ppt-reader.js +337 -0
  60. package/dist/esm/pptx/ppt/ppt-text.d.ts +69 -0
  61. package/dist/esm/pptx/ppt/ppt-text.js +756 -0
  62. package/dist/esm/pptx/pptx-reader.js +16 -1
  63. package/dist/esm/word/doc/doc-reader.d.ts +4 -0
  64. package/dist/esm/word/doc/doc-reader.js +427 -0
  65. package/dist/esm/word/doc/doc-text.d.ts +83 -0
  66. package/dist/esm/word/doc/doc-text.js +731 -0
  67. package/package.json +1 -1
@@ -0,0 +1,1359 @@
1
+ import { serialFromYmd, serialToParts } from "./dates.js";
2
+ import { arrEach, bool, deref, err, isErr, num, refEach, refGet, str, toBool, toNumber, toText } from "./value.js";
3
+ //#region src/excel/formula/functions.ts
4
+ function callFn(name, args, ev, ctx, shift) {
5
+ switch (name) {
6
+ case "TRUE": return bool(true);
7
+ case "FALSE": return bool(false);
8
+ case "NOT": {
9
+ if (args.length !== 1) return err("#VALUE!");
10
+ const b = toBool(ev(args[0]), ctx);
11
+ return typeof b === "string" ? err(b) : bool(!b);
12
+ }
13
+ case "AND":
14
+ case "OR": return andOr(name, args, ev, ctx);
15
+ case "IF": {
16
+ if (args.length < 2 || args.length > 3) return err("#VALUE!");
17
+ const c = toBool(ev(args[0]), ctx);
18
+ if (typeof c === "string") return err(c);
19
+ if (c) return ev(args[1]);
20
+ return args.length === 3 ? ev(args[2]) : bool(false);
21
+ }
22
+ case "IFERROR": {
23
+ if (args.length !== 2) return err("#VALUE!");
24
+ const v = ev(args[0]);
25
+ return isErr(deref(v, ctx)) ? ev(args[1]) : v;
26
+ }
27
+ case "ISBLANK": return is1(args, ev, ctx, (s) => s.t === "blank");
28
+ case "ISNUMBER": return is1(args, ev, ctx, (s) => s.t === "num");
29
+ case "ISTEXT": return is1(args, ev, ctx, (s) => s.t === "str");
30
+ case "ISLOGICAL": return is1(args, ev, ctx, (s) => s.t === "bool");
31
+ case "ISERROR": return is1(args, ev, ctx, (s) => s.t === "err");
32
+ case "ISERR": return is1(args, ev, ctx, (s) => s.t === "err" && s.v !== "#N/A");
33
+ case "ISNA": return is1(args, ev, ctx, (s) => s.t === "err" && s.v === "#N/A");
34
+ case "N": {
35
+ if (args.length !== 1) return err("#VALUE!");
36
+ const s = deref(ev(args[0]), ctx);
37
+ if (s.t === "num") return s;
38
+ if (s.t === "bool") return num(s.v ? 1 : 0);
39
+ if (s.t === "err") return s;
40
+ return num(0);
41
+ }
42
+ case "ABS": return math1(args, ev, ctx, Math.abs);
43
+ case "SIGN": return math1(args, ev, ctx, Math.sign);
44
+ case "SQRT": return math1(args, ev, ctx, (x) => x < 0 ? NaN : Math.sqrt(x));
45
+ case "INT": return math1(args, ev, ctx, Math.floor);
46
+ case "MOD": return mod(args, ev, ctx);
47
+ case "POWER": return power(args, ev, ctx);
48
+ case "ROUND": return roundFn(args, ev, ctx, "round");
49
+ case "ROUNDUP": return roundFn(args, ev, ctx, "up");
50
+ case "ROUNDDOWN":
51
+ case "TRUNC": return roundFn(args, ev, ctx, "down");
52
+ case "SUM": return aggregate(args, ev, ctx, (ns) => ns.reduce((a, b) => a + b, 0));
53
+ case "AVERAGE": return aggregate(args, ev, ctx, (ns) => ns.length ? ns.reduce((a, b) => a + b, 0) / ns.length : NaN, true);
54
+ case "MIN": return aggregate(args, ev, ctx, (ns) => ns.length ? Math.min(...ns) : 0);
55
+ case "MAX": return aggregate(args, ev, ctx, (ns) => ns.length ? Math.max(...ns) : 0);
56
+ case "COUNT": return countFn(args, ev, ctx, false);
57
+ case "COUNTA": return countFn(args, ev, ctx, true);
58
+ case "COUNTIF": return countSumIf(args, ev, ctx, false);
59
+ case "SUMIF": return countSumIf(args, ev, ctx, true);
60
+ case "LEN": {
61
+ const t = textArg(args, ev, ctx, 0);
62
+ return typeof t === "string" ? num(t.length) : err(t.v);
63
+ }
64
+ case "LEFT": return leftRight(args, ev, ctx, true);
65
+ case "RIGHT": return leftRight(args, ev, ctx, false);
66
+ case "MID": return mid(args, ev, ctx);
67
+ case "LOWER": return text1(args, ev, ctx, (s) => s.toLowerCase());
68
+ case "UPPER": return text1(args, ev, ctx, (s) => s.toUpperCase());
69
+ case "TRIM": return text1(args, ev, ctx, (s) => s.replace(/\s+/g, " ").trim());
70
+ case "CONCATENATE": return concat(args, ev, ctx);
71
+ case "EXACT": return exact(args, ev, ctx);
72
+ case "SEARCH": return findSearch(args, ev, ctx, false);
73
+ case "FIND": return findSearch(args, ev, ctx, true);
74
+ case "VALUE": {
75
+ const t = textArg(args, ev, ctx, 0);
76
+ if (typeof t !== "string") return err(t.v);
77
+ const n = Number(t.trim());
78
+ return t.trim() !== "" && Number.isFinite(n) ? num(n) : err("#VALUE!");
79
+ }
80
+ case "TODAY":
81
+ case "NOW": return ctx.nowSerial === void 0 ? err("#VALUE!") : num(ctx.nowSerial);
82
+ case "YEAR": return datePart(args, ev, ctx, (p) => p.year);
83
+ case "MONTH": return datePart(args, ev, ctx, (p) => p.month);
84
+ case "DAY": return datePart(args, ev, ctx, (p) => p.day);
85
+ case "WEEKDAY": return weekday(args, ev, ctx);
86
+ case "DATE": return dateFn(args, ev, ctx);
87
+ case "EDATE": return edate(args, ev, ctx, false);
88
+ case "EOMONTH": return edate(args, ev, ctx, true);
89
+ case "DAYS": return daysFn(args, ev, ctx);
90
+ case "HOUR": return timePart(args, ev, ctx, "h");
91
+ case "MINUTE": return timePart(args, ev, ctx, "m");
92
+ case "SECOND": return timePart(args, ev, ctx, "s");
93
+ case "TIME": return timeFn(args, ev, ctx);
94
+ case "WEEKNUM": return weekNum(args, ev, ctx, false);
95
+ case "ISOWEEKNUM": return weekNum(args, ev, ctx, true);
96
+ case "ISNONTEXT": return is1(args, ev, ctx, (s) => s.t !== "str");
97
+ case "ISREF": return args.length === 1 ? bool(ev(args[0]).t === "ref") : err("#VALUE!");
98
+ case "ISEVEN": return isParity(args, ev, ctx, true);
99
+ case "ISODD": return isParity(args, ev, ctx, false);
100
+ case "NA": return err("#N/A");
101
+ case "IFNA": {
102
+ if (args.length !== 2) return err("#VALUE!");
103
+ const v = ev(args[0]);
104
+ const d = deref(v, ctx);
105
+ return d.t === "err" && d.v === "#N/A" ? ev(args[1]) : v;
106
+ }
107
+ case "XOR": return xorFn(args, ev, ctx);
108
+ case "IFS": return ifsFn(args, ev, ctx);
109
+ case "SWITCH": return switchFn(args, ev, ctx);
110
+ case "PRODUCT": return aggregate(args, ev, ctx, (ns) => ns.length ? ns.reduce((a, b) => a * b, 1) : 0);
111
+ case "MEDIAN": return medianFn(args, ev, ctx);
112
+ case "LARGE": return largeSmall(args, ev, ctx, true);
113
+ case "SMALL": return largeSmall(args, ev, ctx, false);
114
+ case "QUOTIENT": return quotient(args, ev, ctx);
115
+ case "CEILING": return ceilingFloor(args, ev, ctx, "ceil");
116
+ case "FLOOR": return ceilingFloor(args, ev, ctx, "floor");
117
+ case "MROUND": return mround(args, ev, ctx);
118
+ case "EVEN": return evenOdd(args, ev, ctx, true);
119
+ case "ODD": return evenOdd(args, ev, ctx, false);
120
+ case "GCD": return gcdLcm(args, ev, ctx, "gcd");
121
+ case "LCM": return gcdLcm(args, ev, ctx, "lcm");
122
+ case "SUMPRODUCT": return sumProduct(args, ev, ctx);
123
+ case "COUNTBLANK": return countBlank(args, ev, ctx);
124
+ case "COUNTIFS": return countSumAvgIfs(args, ev, ctx, "count");
125
+ case "SUMIFS": return countSumAvgIfs(args, ev, ctx, "sum");
126
+ case "AVERAGEIFS": return countSumAvgIfs(args, ev, ctx, "avg");
127
+ case "AVERAGEIF": return averageIf(args, ev, ctx);
128
+ case "CONCAT": return concatFlatten(args, ev, ctx);
129
+ case "TEXTJOIN": return textJoin(args, ev, ctx);
130
+ case "SUBSTITUTE": return substitute(args, ev, ctx);
131
+ case "REPLACE": return replaceFn(args, ev, ctx);
132
+ case "REPT": return rept(args, ev, ctx);
133
+ case "PROPER": return text1(args, ev, ctx, properCase);
134
+ case "CHAR": return charFn(args, ev, ctx);
135
+ case "CODE": return codeFn(args, ev, ctx);
136
+ case "CLEAN": return text1(args, ev, ctx, stripControl);
137
+ case "T": return tFn(args, ev, ctx);
138
+ case "CHOOSE": return chooseFn(args, ev, ctx);
139
+ case "MATCH": return matchFn(args, ev, ctx);
140
+ case "INDEX": return indexFn(args, ev, ctx);
141
+ case "VLOOKUP": return lookupFn(args, ev, ctx, "v");
142
+ case "HLOOKUP": return lookupFn(args, ev, ctx, "h");
143
+ case "PI": return args.length === 0 ? num(Math.PI) : err("#VALUE!");
144
+ case "EXP": return math1(args, ev, ctx, Math.exp);
145
+ case "LN": return math1(args, ev, ctx, (x) => x <= 0 ? NaN : Math.log(x));
146
+ case "LOG10": return math1(args, ev, ctx, (x) => x <= 0 ? NaN : Math.log10(x));
147
+ case "LOG": return logFn(args, ev, ctx);
148
+ case "SIN": return math1(args, ev, ctx, Math.sin);
149
+ case "COS": return math1(args, ev, ctx, Math.cos);
150
+ case "TAN": return math1(args, ev, ctx, Math.tan);
151
+ case "ASIN": return math1(args, ev, ctx, (x) => Math.abs(x) > 1 ? NaN : Math.asin(x));
152
+ case "ACOS": return math1(args, ev, ctx, (x) => Math.abs(x) > 1 ? NaN : Math.acos(x));
153
+ case "ATAN": return math1(args, ev, ctx, Math.atan);
154
+ case "ATAN2": return math2(args, ev, ctx, (x, y) => x === 0 && y === 0 ? NaN : Math.atan2(y, x));
155
+ case "SINH": return math1(args, ev, ctx, Math.sinh);
156
+ case "COSH": return math1(args, ev, ctx, Math.cosh);
157
+ case "TANH": return math1(args, ev, ctx, Math.tanh);
158
+ case "DEGREES": return math1(args, ev, ctx, (x) => x * 180 / Math.PI);
159
+ case "RADIANS": return math1(args, ev, ctx, (x) => x * Math.PI / 180);
160
+ case "SQRTPI": return math1(args, ev, ctx, (x) => x < 0 ? NaN : Math.sqrt(x * Math.PI));
161
+ case "FACT": return factFn(args, ev, ctx);
162
+ case "COMBIN": return combinPermut(args, ev, ctx, false);
163
+ case "PERMUT": return combinPermut(args, ev, ctx, true);
164
+ case "SUMSQ": return aggregate(args, ev, ctx, (ns) => ns.reduce((a, b) => a + b * b, 0));
165
+ case "STDEV":
166
+ case "STDEV.S": return statSpread(args, ev, ctx, "stdev", true);
167
+ case "STDEVP":
168
+ case "STDEV.P": return statSpread(args, ev, ctx, "stdev", false);
169
+ case "VAR":
170
+ case "VAR.S": return statSpread(args, ev, ctx, "var", true);
171
+ case "VARP":
172
+ case "VAR.P": return statSpread(args, ev, ctx, "var", false);
173
+ case "AVEDEV": return statSpread(args, ev, ctx, "avedev", false);
174
+ case "DEVSQ": return statSpread(args, ev, ctx, "devsq", false);
175
+ case "GEOMEAN": return geoHarMean(args, ev, ctx, true);
176
+ case "HARMEAN": return geoHarMean(args, ev, ctx, false);
177
+ case "AVERAGEA": return aggregateA(args, ev, ctx, "avg");
178
+ case "MAXA": return aggregateA(args, ev, ctx, "max");
179
+ case "MINA": return aggregateA(args, ev, ctx, "min");
180
+ case "MODE":
181
+ case "MODE.SNGL": return modeFn(args, ev, ctx);
182
+ case "RANK":
183
+ case "RANK.EQ": return rankFn(args, ev, ctx);
184
+ case "PERCENTILE":
185
+ case "PERCENTILE.INC": return percentileFn(args, ev, ctx);
186
+ case "QUARTILE":
187
+ case "QUARTILE.INC": return quartileFn(args, ev, ctx);
188
+ case "ROW": return rowColFn(args, ev, shift, true);
189
+ case "COLUMN": return rowColFn(args, ev, shift, false);
190
+ case "ROWS": return rowsColsFn(args, ev, true);
191
+ case "COLUMNS": return rowsColsFn(args, ev, false);
192
+ case "TYPE": return typeFn(args, ev, ctx);
193
+ case "ERROR.TYPE": return errorTypeFn(args, ev, ctx);
194
+ case "UNICHAR": return unicharFn(args, ev, ctx);
195
+ case "UNICODE": return unicodeFn(args, ev, ctx);
196
+ default: return err("#NAME?");
197
+ }
198
+ }
199
+ function is1(args, ev, ctx, test) {
200
+ if (args.length !== 1) return err("#VALUE!");
201
+ return bool(test(deref(ev(args[0]), ctx)));
202
+ }
203
+ function numArg(args, ev, ctx, i) {
204
+ const n = toNumber(ev(args[i]), ctx);
205
+ return typeof n === "string" ? { e: n } : n;
206
+ }
207
+ function textArg(args, ev, ctx, i) {
208
+ const t = toText(ev(args[i]), ctx);
209
+ return typeof t === "string" ? t : { v: t };
210
+ }
211
+ function math1(args, ev, ctx, f) {
212
+ if (args.length !== 1) return err("#VALUE!");
213
+ const a = numArg(args, ev, ctx, 0);
214
+ if (typeof a !== "number") return err(a.e);
215
+ const r = f(a);
216
+ return Number.isNaN(r) ? err("#NUM!") : num(r);
217
+ }
218
+ function text1(args, ev, ctx, f) {
219
+ if (args.length !== 1) return err("#VALUE!");
220
+ const t = textArg(args, ev, ctx, 0);
221
+ return typeof t === "string" ? str(f(t)) : err(t.v);
222
+ }
223
+ function mod(args, ev, ctx) {
224
+ if (args.length !== 2) return err("#VALUE!");
225
+ const a = numArg(args, ev, ctx, 0);
226
+ if (typeof a !== "number") return err(a.e);
227
+ const b = numArg(args, ev, ctx, 1);
228
+ if (typeof b !== "number") return err(b.e);
229
+ if (b === 0) return err("#DIV/0!");
230
+ return num(a - b * Math.floor(a / b));
231
+ }
232
+ function power(args, ev, ctx) {
233
+ if (args.length !== 2) return err("#VALUE!");
234
+ const a = numArg(args, ev, ctx, 0);
235
+ if (typeof a !== "number") return err(a.e);
236
+ const b = numArg(args, ev, ctx, 1);
237
+ if (typeof b !== "number") return err(b.e);
238
+ const r = Math.pow(a, b);
239
+ return Number.isNaN(r) ? err("#NUM!") : num(r);
240
+ }
241
+ function roundFn(args, ev, ctx, mode) {
242
+ if (args.length < 1 || args.length > 2) return err("#VALUE!");
243
+ const a = numArg(args, ev, ctx, 0);
244
+ if (typeof a !== "number") return err(a.e);
245
+ let digits = 0;
246
+ if (args.length === 2) {
247
+ const d = numArg(args, ev, ctx, 1);
248
+ if (typeof d !== "number") return err(d.e);
249
+ digits = Math.trunc(d);
250
+ }
251
+ const f = Math.pow(10, digits);
252
+ const x = Math.abs(a) * f;
253
+ return num(Math.sign(a) * (mode === "round" ? Math.round(x) : mode === "up" ? Math.ceil(x) : Math.floor(x)) / f);
254
+ }
255
+ function andOr(name, args, ev, ctx) {
256
+ let any = false;
257
+ let acc = name === "AND";
258
+ for (const a of args) {
259
+ const v = ev(a);
260
+ if (v.t === "ref") {
261
+ let e;
262
+ refEach(v, ctx, (_r, _c, s) => {
263
+ if (s.t === "err") e ??= s.v;
264
+ else if (s.t === "num" || s.t === "bool") {
265
+ const b = s.t === "bool" ? s.v : s.v !== 0;
266
+ any = true;
267
+ acc = name === "AND" ? acc && b : acc || b;
268
+ }
269
+ });
270
+ if (e) return err(e);
271
+ } else if (v.t === "arr") {
272
+ let e;
273
+ arrEach(v.rows, (s) => {
274
+ if (s.t === "err") e ??= s.v;
275
+ else if (s.t === "num" || s.t === "bool") {
276
+ const b = s.t === "bool" ? s.v : s.v !== 0;
277
+ any = true;
278
+ acc = name === "AND" ? acc && b : acc || b;
279
+ }
280
+ });
281
+ if (e) return err(e);
282
+ } else {
283
+ const b = toBool(v, ctx);
284
+ if (typeof b === "string") return err(b);
285
+ any = true;
286
+ acc = name === "AND" ? acc && b : acc || b;
287
+ }
288
+ }
289
+ return any ? bool(acc) : err("#VALUE!");
290
+ }
291
+ function gatherNumbers(args, ev, ctx) {
292
+ const out = [];
293
+ for (const a of args) {
294
+ const v = ev(a);
295
+ if (v.t === "ref") {
296
+ let e;
297
+ refEach(v, ctx, (_r, _c, s) => {
298
+ if (s.t === "num") out.push(s.v);
299
+ else if (s.t === "err") e ??= s.v;
300
+ });
301
+ if (e) return e;
302
+ } else if (v.t === "arr") {
303
+ let e;
304
+ arrEach(v.rows, (s) => {
305
+ if (s.t === "num") out.push(s.v);
306
+ else if (s.t === "bool") out.push(s.v ? 1 : 0);
307
+ else if (s.t === "err") e ??= s.v;
308
+ });
309
+ if (e) return e;
310
+ } else {
311
+ const s = deref(v, ctx);
312
+ if (s.t === "err") return s.v;
313
+ if (s.t === "num") out.push(s.v);
314
+ else if (s.t === "bool") out.push(s.v ? 1 : 0);
315
+ }
316
+ }
317
+ return out;
318
+ }
319
+ function aggregate(args, ev, ctx, reduce, requireSome = false) {
320
+ const ns = gatherNumbers(args, ev, ctx);
321
+ if (!Array.isArray(ns)) return err(ns);
322
+ if (requireSome && ns.length === 0) return err("#DIV/0!");
323
+ const r = reduce(ns);
324
+ return Number.isNaN(r) ? err("#DIV/0!") : num(r);
325
+ }
326
+ function countFn(args, ev, ctx, nonBlank) {
327
+ let count = 0;
328
+ for (const a of args) {
329
+ const v = ev(a);
330
+ if (v.t === "ref") refEach(v, ctx, (_r, _c, s) => {
331
+ if (nonBlank ? s.t !== "blank" : s.t === "num") count++;
332
+ });
333
+ else if (v.t === "arr") arrEach(v.rows, (s) => {
334
+ if (nonBlank ? s.t !== "blank" : s.t === "num") count++;
335
+ });
336
+ else {
337
+ const s = deref(v, ctx);
338
+ if (nonBlank ? s.t !== "blank" : s.t === "num") count++;
339
+ }
340
+ }
341
+ return num(count);
342
+ }
343
+ function leftRight(args, ev, ctx, left) {
344
+ if (args.length < 1 || args.length > 2) return err("#VALUE!");
345
+ const t = textArg(args, ev, ctx, 0);
346
+ if (typeof t !== "string") return err(t.v);
347
+ let n = 1;
348
+ if (args.length === 2) {
349
+ const d = numArg(args, ev, ctx, 1);
350
+ if (typeof d !== "number") return err(d.e);
351
+ n = Math.trunc(d);
352
+ if (n < 0) return err("#VALUE!");
353
+ }
354
+ return str(left ? t.slice(0, n) : n === 0 ? "" : t.slice(Math.max(0, t.length - n)));
355
+ }
356
+ function mid(args, ev, ctx) {
357
+ if (args.length !== 3) return err("#VALUE!");
358
+ const t = textArg(args, ev, ctx, 0);
359
+ if (typeof t !== "string") return err(t.v);
360
+ const start = numArg(args, ev, ctx, 1);
361
+ if (typeof start !== "number") return err(start.e);
362
+ const len = numArg(args, ev, ctx, 2);
363
+ if (typeof len !== "number") return err(len.e);
364
+ if (start < 1 || len < 0) return err("#VALUE!");
365
+ const s = Math.trunc(start) - 1;
366
+ return str(t.slice(s, s + Math.trunc(len)));
367
+ }
368
+ function concat(args, ev, ctx) {
369
+ let out = "";
370
+ for (let i = 0; i < args.length; i++) {
371
+ const t = textArg(args, ev, ctx, i);
372
+ if (typeof t !== "string") return err(t.v);
373
+ out += t;
374
+ }
375
+ return str(out);
376
+ }
377
+ function exact(args, ev, ctx) {
378
+ if (args.length !== 2) return err("#VALUE!");
379
+ const a = textArg(args, ev, ctx, 0);
380
+ if (typeof a !== "string") return err(a.v);
381
+ const b = textArg(args, ev, ctx, 1);
382
+ if (typeof b !== "string") return err(b.v);
383
+ return bool(a === b);
384
+ }
385
+ function findSearch(args, ev, ctx, caseSensitive) {
386
+ if (args.length < 2 || args.length > 3) return err("#VALUE!");
387
+ let needle = textArg(args, ev, ctx, 0);
388
+ if (typeof needle !== "string") return err(needle.v);
389
+ let hay = textArg(args, ev, ctx, 1);
390
+ if (typeof hay !== "string") return err(hay.v);
391
+ let start = 1;
392
+ if (args.length === 3) {
393
+ const s = numArg(args, ev, ctx, 2);
394
+ if (typeof s !== "number") return err(s.e);
395
+ start = Math.trunc(s);
396
+ if (start < 1) return err("#VALUE!");
397
+ }
398
+ if (!caseSensitive) {
399
+ needle = needle.toLowerCase();
400
+ hay = hay.toLowerCase();
401
+ }
402
+ const idx = hay.indexOf(needle, start - 1);
403
+ return idx < 0 ? err("#VALUE!") : num(idx + 1);
404
+ }
405
+ function datePart(args, ev, ctx, pick) {
406
+ if (args.length !== 1) return err("#VALUE!");
407
+ const a = numArg(args, ev, ctx, 0);
408
+ if (typeof a !== "number") return err(a.e);
409
+ if (a < 0) return err("#NUM!");
410
+ return num(pick(serialToParts(a, ctx.date1904)));
411
+ }
412
+ function weekday(args, ev, ctx) {
413
+ if (args.length < 1 || args.length > 2) return err("#VALUE!");
414
+ const a = numArg(args, ev, ctx, 0);
415
+ if (typeof a !== "number") return err(a.e);
416
+ if (a < 0) return err("#NUM!");
417
+ let type = 1;
418
+ if (args.length === 2) {
419
+ const t = numArg(args, ev, ctx, 1);
420
+ if (typeof t !== "number") return err(t.e);
421
+ type = Math.trunc(t);
422
+ }
423
+ const dow = serialToParts(a, ctx.date1904).dow;
424
+ switch (type) {
425
+ case 1: return num(dow + 1);
426
+ case 2: return num((dow + 6) % 7 + 1);
427
+ case 3: return num((dow + 6) % 7);
428
+ default: return err("#NUM!");
429
+ }
430
+ }
431
+ function dateFn(args, ev, ctx) {
432
+ if (args.length !== 3) return err("#VALUE!");
433
+ const y = numArg(args, ev, ctx, 0);
434
+ if (typeof y !== "number") return err(y.e);
435
+ const m = numArg(args, ev, ctx, 1);
436
+ if (typeof m !== "number") return err(m.e);
437
+ const d = numArg(args, ev, ctx, 2);
438
+ if (typeof d !== "number") return err(d.e);
439
+ const serial = serialFromYmd(Math.trunc(y), Math.trunc(m), Math.trunc(d), ctx.date1904);
440
+ return serial < 0 ? err("#NUM!") : num(serial);
441
+ }
442
+ function edate(args, ev, ctx, endOfMonth) {
443
+ if (args.length !== 2) return err("#VALUE!");
444
+ const a = numArg(args, ev, ctx, 0);
445
+ if (typeof a !== "number") return err(a.e);
446
+ if (a < 0) return err("#NUM!");
447
+ const m = numArg(args, ev, ctx, 1);
448
+ if (typeof m !== "number") return err(m.e);
449
+ const p = serialToParts(a, ctx.date1904);
450
+ const idx = p.year * 12 + (p.month - 1) + Math.trunc(m);
451
+ const ty = Math.floor(idx / 12);
452
+ const tm = idx % 12 + 1;
453
+ const dim = daysInMonth(ty, tm);
454
+ const serial = serialFromYmd(ty, tm, endOfMonth ? dim : Math.min(p.day, dim), ctx.date1904);
455
+ return serial < 0 ? err("#NUM!") : num(serial);
456
+ }
457
+ function daysInMonth(year, month1) {
458
+ return new Date(Date.UTC(year, month1, 0)).getUTCDate();
459
+ }
460
+ function countSumIf(args, ev, ctx, sum) {
461
+ const minArgs = sum ? 2 : 2;
462
+ const maxArgs = sum ? 3 : 2;
463
+ if (args.length < minArgs || args.length > maxArgs) return err("#VALUE!");
464
+ const range = ev(args[0]);
465
+ if (range.t !== "ref") return err("#VALUE!");
466
+ const crit = parseCriteria(deref(ev(args[1]), ctx));
467
+ if ("e" in crit) return err(crit.e);
468
+ const sumRect = sum && args.length === 3 ? asRef(ev(args[2])) : void 0;
469
+ if (sum && args.length === 3 && !sumRect) return err("#VALUE!");
470
+ let count = 0;
471
+ let total = 0;
472
+ let e;
473
+ refEach(range, ctx, (r, c, s) => {
474
+ if (!matchCriteria(s, crit)) return;
475
+ count++;
476
+ if (!sum) return;
477
+ let target = s;
478
+ if (sumRect) {
479
+ const sr = sumRect.rect.r0 + (r - range.rect.r0);
480
+ const sc = sumRect.rect.c0 + (c - range.rect.c0);
481
+ target = refGet(sumRect.sheet, ctx, sr, sc);
482
+ }
483
+ if (target.t === "num") total += target.v;
484
+ else if (target.t === "err") e ??= target.v;
485
+ });
486
+ if (e) return err(e);
487
+ return num(sum ? total : count);
488
+ }
489
+ function asRef(v) {
490
+ return v.t === "ref" ? {
491
+ rect: v.rect,
492
+ ...v.sheet !== void 0 ? { sheet: v.sheet } : {}
493
+ } : void 0;
494
+ }
495
+ function parseCriteria(s) {
496
+ if (s.t === "err") return { e: s.v };
497
+ if (s.t === "num") return {
498
+ kind: "num",
499
+ op: "=",
500
+ n: s.v
501
+ };
502
+ if (s.t === "bool") return {
503
+ kind: "num",
504
+ op: "=",
505
+ n: s.v ? 1 : 0
506
+ };
507
+ if (s.t === "blank") return {
508
+ kind: "num",
509
+ op: "=",
510
+ n: 0
511
+ };
512
+ let text = s.v;
513
+ let op = "=";
514
+ const m = /^(<>|>=|<=|>|<|=)/.exec(text);
515
+ if (m) {
516
+ op = m[1];
517
+ text = text.slice(m[1].length);
518
+ }
519
+ const n = Number(text.trim());
520
+ if (text.trim() !== "" && Number.isFinite(n)) return {
521
+ kind: "num",
522
+ op,
523
+ n
524
+ };
525
+ return {
526
+ kind: "text",
527
+ negate: op === "<>",
528
+ re: wildcardToRegExp(text)
529
+ };
530
+ }
531
+ function matchCriteria(cell, crit) {
532
+ if (crit.kind === "num") {
533
+ const v = cell.t === "num" ? cell.v : cell.t === "bool" ? cell.v ? 1 : 0 : void 0;
534
+ if (v === void 0) return false;
535
+ switch (crit.op) {
536
+ case "=": return v === crit.n;
537
+ case "<>": return v !== crit.n;
538
+ case ">": return v > crit.n;
539
+ case ">=": return v >= crit.n;
540
+ case "<": return v < crit.n;
541
+ case "<=": return v <= crit.n;
542
+ }
543
+ }
544
+ const text = cell.t === "str" ? cell.v : cell.t === "blank" ? "" : void 0;
545
+ if (text === void 0) return false;
546
+ const hit = crit.re.test(text);
547
+ return crit.negate ? !hit : hit;
548
+ }
549
+ function wildcardToRegExp(pattern) {
550
+ let out = "^";
551
+ for (let i = 0; i < pattern.length; i++) {
552
+ const ch = pattern[i];
553
+ if (ch === "~" && (pattern[i + 1] === "*" || pattern[i + 1] === "?" || pattern[i + 1] === "~")) {
554
+ out += escapeRe(pattern[i + 1]);
555
+ i++;
556
+ } else if (ch === "*") out += ".*";
557
+ else if (ch === "?") out += ".";
558
+ else out += escapeRe(ch);
559
+ }
560
+ out += "$";
561
+ return new RegExp(out, "is");
562
+ }
563
+ function escapeRe(ch) {
564
+ return /[.*+?^${}()|[\]\\]/.test(ch) ? `\\${ch}` : ch;
565
+ }
566
+ var MAX_SCAN = 2e5;
567
+ function isParity(args, ev, ctx, even) {
568
+ if (args.length !== 1) return err("#VALUE!");
569
+ const a = numArg(args, ev, ctx, 0);
570
+ if (typeof a !== "number") return err(a.e);
571
+ const odd = Math.abs(Math.trunc(a)) % 2 === 1;
572
+ return bool(even ? !odd : odd);
573
+ }
574
+ function xorFn(args, ev, ctx) {
575
+ let trues = 0;
576
+ let any = false;
577
+ for (const a of args) {
578
+ const v = ev(a);
579
+ if (v.t === "ref") {
580
+ let e;
581
+ refEach(v, ctx, (_r, _c, s) => {
582
+ if (s.t === "err") e ??= s.v;
583
+ else if (s.t === "num" || s.t === "bool") {
584
+ any = true;
585
+ if (s.t === "bool" ? s.v : s.v !== 0) trues++;
586
+ }
587
+ });
588
+ if (e) return err(e);
589
+ } else {
590
+ const b = toBool(v, ctx);
591
+ if (typeof b === "string") return err(b);
592
+ any = true;
593
+ if (b) trues++;
594
+ }
595
+ }
596
+ return any ? bool(trues % 2 === 1) : err("#VALUE!");
597
+ }
598
+ function ifsFn(args, ev, ctx) {
599
+ if (args.length < 2 || args.length % 2 !== 0) return err("#VALUE!");
600
+ for (let i = 0; i < args.length; i += 2) {
601
+ const c = toBool(ev(args[i]), ctx);
602
+ if (typeof c === "string") return err(c);
603
+ if (c) return ev(args[i + 1]);
604
+ }
605
+ return err("#N/A");
606
+ }
607
+ function switchFn(args, ev, ctx) {
608
+ if (args.length < 3) return err("#VALUE!");
609
+ const target = deref(ev(args[0]), ctx);
610
+ if (target.t === "err") return target;
611
+ let i = 1;
612
+ for (; i + 1 < args.length; i += 2) {
613
+ const cand = deref(ev(args[i]), ctx);
614
+ if (cand.t === "err") return cand;
615
+ if (scalarEquals(target, cand)) return ev(args[i + 1]);
616
+ }
617
+ return i < args.length ? ev(args[i]) : err("#N/A");
618
+ }
619
+ function scalarEquals(a, b) {
620
+ if (a.t === "num" && b.t === "num") return a.v === b.v;
621
+ if (a.t === "str" && b.t === "str") return a.v.toLowerCase() === b.v.toLowerCase();
622
+ if (a.t === "bool" && b.t === "bool") return a.v === b.v;
623
+ return a.t === "blank" && b.t === "blank";
624
+ }
625
+ function cmpScalar(a, b) {
626
+ if (a.t === "num" && b.t === "num") return a.v < b.v ? -1 : a.v > b.v ? 1 : 0;
627
+ if (a.t === "str" && b.t === "str") {
628
+ const x = a.v.toLowerCase();
629
+ const y = b.v.toLowerCase();
630
+ return x < y ? -1 : x > y ? 1 : 0;
631
+ }
632
+ if (a.t === "bool" && b.t === "bool") return a.v === b.v ? 0 : a.v ? 1 : -1;
633
+ }
634
+ function quotient(args, ev, ctx) {
635
+ if (args.length !== 2) return err("#VALUE!");
636
+ const a = numArg(args, ev, ctx, 0);
637
+ if (typeof a !== "number") return err(a.e);
638
+ const b = numArg(args, ev, ctx, 1);
639
+ if (typeof b !== "number") return err(b.e);
640
+ if (b === 0) return err("#DIV/0!");
641
+ return num(Math.trunc(a / b));
642
+ }
643
+ function ceilingFloor(args, ev, ctx, mode) {
644
+ if (args.length !== 2) return err("#VALUE!");
645
+ const a = numArg(args, ev, ctx, 0);
646
+ if (typeof a !== "number") return err(a.e);
647
+ const sig = numArg(args, ev, ctx, 1);
648
+ if (typeof sig !== "number") return err(sig.e);
649
+ if (sig === 0) return num(0);
650
+ if (a !== 0 && a > 0 !== sig > 0) return err("#NUM!");
651
+ const q = Math.abs(a) / Math.abs(sig);
652
+ const snapped = Math.abs(q - Math.round(q)) < 1e-9 ? Math.round(q) : q;
653
+ const mag = (mode === "ceil" ? Math.ceil(snapped) : Math.floor(snapped)) * Math.abs(sig);
654
+ return num(a < 0 ? -mag : mag);
655
+ }
656
+ function roundHalfAway(q) {
657
+ const f = Math.floor(q);
658
+ return Math.abs(q - f - .5) < 1e-9 ? f + 1 : Math.round(q);
659
+ }
660
+ function mround(args, ev, ctx) {
661
+ if (args.length !== 2) return err("#VALUE!");
662
+ const n = numArg(args, ev, ctx, 0);
663
+ if (typeof n !== "number") return err(n.e);
664
+ const mult = numArg(args, ev, ctx, 1);
665
+ if (typeof mult !== "number") return err(mult.e);
666
+ if (mult === 0) return num(0);
667
+ if (n !== 0 && n > 0 !== mult > 0) return err("#NUM!");
668
+ const mag = roundHalfAway(Math.abs(n) / Math.abs(mult)) * Math.abs(mult);
669
+ return num(n < 0 ? -mag : mag);
670
+ }
671
+ function evenOdd(args, ev, ctx, even) {
672
+ if (args.length !== 1) return err("#VALUE!");
673
+ const a = numArg(args, ev, ctx, 0);
674
+ if (typeof a !== "number") return err(a.e);
675
+ let m = Math.ceil(Math.abs(a));
676
+ if (even) {
677
+ if (m % 2 !== 0) m++;
678
+ } else if (m % 2 === 0) m++;
679
+ return num(a < 0 ? -m : m);
680
+ }
681
+ function gcd2(a, b) {
682
+ a = Math.abs(a);
683
+ b = Math.abs(b);
684
+ while (b) {
685
+ const t = a % b;
686
+ a = b;
687
+ b = t;
688
+ }
689
+ return a;
690
+ }
691
+ function gcdLcm(args, ev, ctx, mode) {
692
+ const ns = gatherNumbers(args, ev, ctx);
693
+ if (!Array.isArray(ns)) return err(ns);
694
+ if (ns.length === 0) return err("#VALUE!");
695
+ const ints = [];
696
+ for (const n of ns) {
697
+ const t = Math.trunc(n);
698
+ if (t < 0) return err("#NUM!");
699
+ ints.push(t);
700
+ }
701
+ if (mode === "gcd") return num(ints.reduce((a, b) => gcd2(a, b)));
702
+ let l = ints[0];
703
+ for (let i = 1; i < ints.length; i++) {
704
+ const b = ints[i];
705
+ if (l === 0 || b === 0) {
706
+ l = 0;
707
+ continue;
708
+ }
709
+ l = l / gcd2(l, b) * b;
710
+ if (!Number.isSafeInteger(l)) return err("#NUM!");
711
+ }
712
+ return num(l);
713
+ }
714
+ function medianFn(args, ev, ctx) {
715
+ const ns = gatherNumbers(args, ev, ctx);
716
+ if (!Array.isArray(ns)) return err(ns);
717
+ if (ns.length === 0) return err("#NUM!");
718
+ const s = [...ns].sort((a, b) => a - b);
719
+ const midIdx = Math.floor(s.length / 2);
720
+ return num(s.length % 2 ? s[midIdx] : (s[midIdx - 1] + s[midIdx]) / 2);
721
+ }
722
+ function largeSmall(args, ev, ctx, large) {
723
+ if (args.length !== 2) return err("#VALUE!");
724
+ const ns = gatherNumbers([args[0]], ev, ctx);
725
+ if (!Array.isArray(ns)) return err(ns);
726
+ const k = numArg(args, ev, ctx, 1);
727
+ if (typeof k !== "number") return err(k.e);
728
+ const ki = Math.trunc(k);
729
+ if (ki < 1 || ki > ns.length) return err("#NUM!");
730
+ return num([...ns].sort((a, b) => large ? b - a : a - b)[ki - 1]);
731
+ }
732
+ function countBlank(args, ev, ctx) {
733
+ if (args.length !== 1) return err("#VALUE!");
734
+ const r = asRef(ev(args[0]));
735
+ if (!r) return err("#VALUE!");
736
+ const area = (r.rect.r1 - r.rect.r0 + 1) * (r.rect.c1 - r.rect.c0 + 1);
737
+ let filled = 0;
738
+ refEach(r, ctx, (_x, _y, s) => {
739
+ if (!(s.t === "blank" || s.t === "str" && s.v === "")) filled++;
740
+ });
741
+ return num(Math.max(0, area - filled));
742
+ }
743
+ function countSumAvgIfs(args, ev, ctx, mode) {
744
+ const isCount = mode === "count";
745
+ let valueRef;
746
+ let pairStart = 0;
747
+ if (!isCount) {
748
+ const vr = asRef(ev(args[0]));
749
+ if (!vr) return err("#VALUE!");
750
+ valueRef = vr;
751
+ pairStart = 1;
752
+ }
753
+ const pairs = args.length - pairStart;
754
+ if (pairs < 2 || pairs % 2 !== 0) return err("#VALUE!");
755
+ const ranges = [];
756
+ const crits = [];
757
+ for (let i = pairStart; i + 1 < args.length; i += 2) {
758
+ const rng = asRef(ev(args[i]));
759
+ if (!rng) return err("#VALUE!");
760
+ const crit = parseCriteria(deref(ev(args[i + 1]), ctx));
761
+ if ("e" in crit) return err(crit.e);
762
+ ranges.push(rng);
763
+ crits.push(crit);
764
+ }
765
+ const base = ranges[0].rect;
766
+ const h = base.r1 - base.r0;
767
+ const w = base.c1 - base.c0;
768
+ for (const r of ranges) if (r.rect.r1 - r.rect.r0 !== h || r.rect.c1 - r.rect.c0 !== w) return err("#VALUE!");
769
+ if (valueRef) {
770
+ const vr = valueRef.rect;
771
+ if (vr.r1 - vr.r0 !== h || vr.c1 - vr.c0 !== w) return err("#VALUE!");
772
+ }
773
+ let count = 0;
774
+ let total = 0;
775
+ let numCount = 0;
776
+ let e;
777
+ refEach(ranges[0], ctx, (r, c, s0) => {
778
+ if (!matchCriteria(s0, crits[0])) return;
779
+ for (let k = 1; k < ranges.length; k++) {
780
+ const rk = ranges[k];
781
+ if (!matchCriteria(refGet(rk.sheet, ctx, rk.rect.r0 + (r - base.r0), rk.rect.c0 + (c - base.c0)), crits[k])) return;
782
+ }
783
+ count++;
784
+ if (isCount) return;
785
+ const vref = valueRef;
786
+ const target = refGet(vref.sheet, ctx, vref.rect.r0 + (r - base.r0), vref.rect.c0 + (c - base.c0));
787
+ if (target.t === "num") {
788
+ total += target.v;
789
+ numCount++;
790
+ } else if (target.t === "err") e ??= target.v;
791
+ });
792
+ if (e) return err(e);
793
+ if (isCount) return num(count);
794
+ if (mode === "sum") return num(total);
795
+ return numCount === 0 ? err("#DIV/0!") : num(total / numCount);
796
+ }
797
+ function averageIf(args, ev, ctx) {
798
+ if (args.length < 2 || args.length > 3) return err("#VALUE!");
799
+ const range = asRef(ev(args[0]));
800
+ if (!range) return err("#VALUE!");
801
+ const crit = parseCriteria(deref(ev(args[1]), ctx));
802
+ if ("e" in crit) return err(crit.e);
803
+ const avgRef = args.length === 3 ? asRef(ev(args[2])) : range;
804
+ if (!avgRef) return err("#VALUE!");
805
+ const rr = range.rect;
806
+ const ar = avgRef.rect;
807
+ let total = 0;
808
+ let count = 0;
809
+ let e;
810
+ refEach(range, ctx, (r, c, s) => {
811
+ if (!matchCriteria(s, crit)) return;
812
+ const target = avgRef === range ? s : refGet(avgRef.sheet, ctx, ar.r0 + (r - rr.r0), ar.c0 + (c - rr.c0));
813
+ if (target.t === "num") {
814
+ total += target.v;
815
+ count++;
816
+ } else if (target.t === "err") e ??= target.v;
817
+ });
818
+ if (e) return err(e);
819
+ return count === 0 ? err("#DIV/0!") : num(total / count);
820
+ }
821
+ function sumProduct(args, ev, ctx) {
822
+ if (args.length === 0) return err("#VALUE!");
823
+ const vals = args.map((a) => ev(a));
824
+ const refs = vals.map((v) => asRef(v));
825
+ if (refs.every((r) => r === void 0)) {
826
+ let p = 1;
827
+ for (const v of vals) {
828
+ const n = toNumber(v, ctx);
829
+ if (typeof n === "string") return err(n);
830
+ p *= n;
831
+ }
832
+ return num(p);
833
+ }
834
+ if (refs.some((r) => r === void 0)) return err("#VALUE!");
835
+ const base = refs[0].rect;
836
+ const h = base.r1 - base.r0;
837
+ const w = base.c1 - base.c0;
838
+ for (const r of refs) if (r.rect.r1 - r.rect.r0 !== h || r.rect.c1 - r.rect.c0 !== w) return err("#VALUE!");
839
+ let total = 0;
840
+ let e;
841
+ refEach(refs[0], ctx, (r, c, s0) => {
842
+ if (s0.t === "err") {
843
+ e ??= s0.v;
844
+ return;
845
+ }
846
+ if (s0.t !== "num") return;
847
+ let term = s0.v;
848
+ for (let k = 1; k < refs.length && term !== 0; k++) {
849
+ const rk = refs[k];
850
+ const cell = refGet(rk.sheet, ctx, rk.rect.r0 + (r - base.r0), rk.rect.c0 + (c - base.c0));
851
+ if (cell.t === "num") term *= cell.v;
852
+ else if (cell.t === "err") {
853
+ e ??= cell.v;
854
+ term = 0;
855
+ } else term = 0;
856
+ }
857
+ total += term;
858
+ });
859
+ return e ? err(e) : num(total);
860
+ }
861
+ function concatFlatten(args, ev, ctx) {
862
+ let out = "";
863
+ for (const a of args) {
864
+ const v = ev(a);
865
+ if (v.t === "ref") {
866
+ const { r0, c0, r1, c1 } = v.rect;
867
+ if ((r1 - r0 + 1) * (c1 - c0 + 1) > MAX_SCAN) return err("#VALUE!");
868
+ for (let r = r0; r <= r1; r++) for (let c = c0; c <= c1; c++) {
869
+ const t = toText(refGet(v.sheet, ctx, r, c), ctx);
870
+ if (typeof t !== "string") return err(t);
871
+ out += t;
872
+ if (out.length > 32767) return err("#VALUE!");
873
+ }
874
+ } else {
875
+ const t = toText(v, ctx);
876
+ if (typeof t !== "string") return err(t);
877
+ out += t;
878
+ }
879
+ }
880
+ return str(out);
881
+ }
882
+ function textJoin(args, ev, ctx) {
883
+ if (args.length < 3) return err("#VALUE!");
884
+ const delim = textArg(args, ev, ctx, 0);
885
+ if (typeof delim !== "string") return err(delim.v);
886
+ const ignore = toBool(ev(args[1]), ctx);
887
+ if (typeof ignore === "string") return err(ignore);
888
+ const parts = [];
889
+ for (let i = 2; i < args.length; i++) {
890
+ const v = ev(args[i]);
891
+ if (v.t === "ref") {
892
+ const { r0, c0, r1, c1 } = v.rect;
893
+ if ((r1 - r0 + 1) * (c1 - c0 + 1) > MAX_SCAN) return err("#VALUE!");
894
+ for (let r = r0; r <= r1; r++) for (let c = c0; c <= c1; c++) {
895
+ const t = toText(refGet(v.sheet, ctx, r, c), ctx);
896
+ if (typeof t !== "string") return err(t);
897
+ if (!(ignore && t === "")) parts.push(t);
898
+ }
899
+ } else {
900
+ const t = toText(v, ctx);
901
+ if (typeof t !== "string") return err(t);
902
+ if (!(ignore && t === "")) parts.push(t);
903
+ }
904
+ }
905
+ return str(parts.join(delim));
906
+ }
907
+ function substitute(args, ev, ctx) {
908
+ if (args.length < 3 || args.length > 4) return err("#VALUE!");
909
+ const text = textArg(args, ev, ctx, 0);
910
+ if (typeof text !== "string") return err(text.v);
911
+ const oldT = textArg(args, ev, ctx, 1);
912
+ if (typeof oldT !== "string") return err(oldT.v);
913
+ const newT = textArg(args, ev, ctx, 2);
914
+ if (typeof newT !== "string") return err(newT.v);
915
+ if (oldT === "") return str(text);
916
+ if (args.length === 3) return str(text.split(oldT).join(newT));
917
+ const inst = numArg(args, ev, ctx, 3);
918
+ if (typeof inst !== "number") return err(inst.e);
919
+ const k = Math.trunc(inst);
920
+ if (k < 1) return err("#VALUE!");
921
+ let idx = -1;
922
+ let count = 0;
923
+ for (;;) {
924
+ idx = text.indexOf(oldT, idx + 1);
925
+ if (idx < 0) return str(text);
926
+ if (++count === k) return str(text.slice(0, idx) + newT + text.slice(idx + oldT.length));
927
+ }
928
+ }
929
+ function replaceFn(args, ev, ctx) {
930
+ if (args.length !== 4) return err("#VALUE!");
931
+ const text = textArg(args, ev, ctx, 0);
932
+ if (typeof text !== "string") return err(text.v);
933
+ const start = numArg(args, ev, ctx, 1);
934
+ if (typeof start !== "number") return err(start.e);
935
+ const len = numArg(args, ev, ctx, 2);
936
+ if (typeof len !== "number") return err(len.e);
937
+ const newT = textArg(args, ev, ctx, 3);
938
+ if (typeof newT !== "string") return err(newT.v);
939
+ const s = Math.trunc(start);
940
+ const l = Math.trunc(len);
941
+ if (s < 1 || l < 0) return err("#VALUE!");
942
+ return str(text.slice(0, s - 1) + newT + text.slice(s - 1 + l));
943
+ }
944
+ function rept(args, ev, ctx) {
945
+ if (args.length !== 2) return err("#VALUE!");
946
+ const text = textArg(args, ev, ctx, 0);
947
+ if (typeof text !== "string") return err(text.v);
948
+ const n = numArg(args, ev, ctx, 1);
949
+ if (typeof n !== "number") return err(n.e);
950
+ const k = Math.trunc(n);
951
+ if (k < 0) return err("#VALUE!");
952
+ if (text.length * k > 32767) return err("#VALUE!");
953
+ return str(text.repeat(k));
954
+ }
955
+ function properCase(s) {
956
+ return s.replace(/[A-Za-z]+/g, (w) => w[0].toUpperCase() + w.slice(1).toLowerCase());
957
+ }
958
+ function charFn(args, ev, ctx) {
959
+ if (args.length !== 1) return err("#VALUE!");
960
+ const n = numArg(args, ev, ctx, 0);
961
+ if (typeof n !== "number") return err(n.e);
962
+ const code = Math.trunc(n);
963
+ if (code < 1 || code > 255) return err("#VALUE!");
964
+ return str(String.fromCharCode(code));
965
+ }
966
+ function codeFn(args, ev, ctx) {
967
+ const t = textArg(args, ev, ctx, 0);
968
+ if (typeof t !== "string") return err(t.v);
969
+ if (t.length === 0) return err("#VALUE!");
970
+ return num(t.charCodeAt(0));
971
+ }
972
+ function stripControl(s) {
973
+ let out = "";
974
+ for (let i = 0; i < s.length; i++) if (s.charCodeAt(i) >= 32) out += s[i];
975
+ return out;
976
+ }
977
+ function tFn(args, ev, ctx) {
978
+ if (args.length !== 1) return err("#VALUE!");
979
+ const s = deref(ev(args[0]), ctx);
980
+ if (s.t === "err") return s;
981
+ return s.t === "str" ? s : str("");
982
+ }
983
+ function daysFn(args, ev, ctx) {
984
+ if (args.length !== 2) return err("#VALUE!");
985
+ const end = numArg(args, ev, ctx, 0);
986
+ if (typeof end !== "number") return err(end.e);
987
+ const start = numArg(args, ev, ctx, 1);
988
+ if (typeof start !== "number") return err(start.e);
989
+ return num(Math.trunc(end) - Math.trunc(start));
990
+ }
991
+ function timePart(args, ev, ctx, part) {
992
+ if (args.length !== 1) return err("#VALUE!");
993
+ const a = numArg(args, ev, ctx, 0);
994
+ if (typeof a !== "number") return err(a.e);
995
+ if (a < 0) return err("#NUM!");
996
+ let secs = Math.round((a - Math.floor(a)) * 86400);
997
+ if (secs >= 86400) secs -= 86400;
998
+ if (part === "h") return num(Math.floor(secs / 3600));
999
+ if (part === "m") return num(Math.floor(secs / 60) % 60);
1000
+ return num(secs % 60);
1001
+ }
1002
+ function timeFn(args, ev, ctx) {
1003
+ if (args.length !== 3) return err("#VALUE!");
1004
+ const h = numArg(args, ev, ctx, 0);
1005
+ if (typeof h !== "number") return err(h.e);
1006
+ const m = numArg(args, ev, ctx, 1);
1007
+ if (typeof m !== "number") return err(m.e);
1008
+ const s = numArg(args, ev, ctx, 2);
1009
+ if (typeof s !== "number") return err(s.e);
1010
+ return num(((Math.trunc(h) * 3600 + Math.trunc(m) * 60 + Math.trunc(s)) % 86400 + 86400) % 86400 / 86400);
1011
+ }
1012
+ function weekStartDow(type) {
1013
+ switch (type) {
1014
+ case 1:
1015
+ case 17: return 0;
1016
+ case 2:
1017
+ case 11: return 1;
1018
+ case 12: return 2;
1019
+ case 13: return 3;
1020
+ case 14: return 4;
1021
+ case 15: return 5;
1022
+ case 16: return 6;
1023
+ default: return;
1024
+ }
1025
+ }
1026
+ function weekNum(args, ev, ctx, iso) {
1027
+ if (args.length < 1 || args.length > 2) return err("#VALUE!");
1028
+ const a = numArg(args, ev, ctx, 0);
1029
+ if (typeof a !== "number") return err(a.e);
1030
+ if (a < 0) return err("#NUM!");
1031
+ const serial = Math.floor(a);
1032
+ if (iso) return num(isoWeek(serial, ctx.date1904));
1033
+ let type = 1;
1034
+ if (args.length === 2) {
1035
+ const t = numArg(args, ev, ctx, 1);
1036
+ if (typeof t !== "number") return err(t.e);
1037
+ type = Math.trunc(t);
1038
+ }
1039
+ if (type === 21) return num(isoWeek(serial, ctx.date1904));
1040
+ const firstDow = weekStartDow(type);
1041
+ if (firstDow === void 0) return err("#NUM!");
1042
+ const jan1 = serialFromYmd(serialToParts(serial, ctx.date1904).year, 1, 1, ctx.date1904);
1043
+ const offset = (serialToParts(jan1, ctx.date1904).dow - firstDow + 7) % 7;
1044
+ const dayOfYear = serial - jan1 + 1;
1045
+ return num(Math.floor((dayOfYear + offset - 1) / 7) + 1);
1046
+ }
1047
+ function isoWeek(serial, date1904) {
1048
+ const thursday = serial - (serialToParts(serial, date1904).dow + 6) % 7 + 3;
1049
+ const ty = serialToParts(thursday, date1904).year;
1050
+ const jan1 = serialFromYmd(ty, 1, 1, date1904);
1051
+ return Math.floor((thursday - jan1) / 7) + 1;
1052
+ }
1053
+ function chooseFn(args, ev, ctx) {
1054
+ if (args.length < 2) return err("#VALUE!");
1055
+ const i = numArg(args, ev, ctx, 0);
1056
+ if (typeof i !== "number") return err(i.e);
1057
+ const k = Math.trunc(i);
1058
+ if (k < 1 || k > args.length - 1) return err("#VALUE!");
1059
+ return ev(args[k]);
1060
+ }
1061
+ function matchFn(args, ev, ctx) {
1062
+ if (args.length < 2 || args.length > 3) return err("#VALUE!");
1063
+ const target = deref(ev(args[0]), ctx);
1064
+ if (target.t === "err") return target;
1065
+ const range = asRef(ev(args[1]));
1066
+ if (!range) return err("#VALUE!");
1067
+ const rect = range.rect;
1068
+ let type = 1;
1069
+ if (args.length === 3) {
1070
+ const t = numArg(args, ev, ctx, 2);
1071
+ if (typeof t !== "number") return err(t.e);
1072
+ type = Math.trunc(t);
1073
+ }
1074
+ const horizontal = rect.r0 === rect.r1;
1075
+ const vertical = rect.c0 === rect.c1;
1076
+ if (!horizontal && !vertical) return err("#N/A");
1077
+ const len = horizontal ? rect.c1 - rect.c0 + 1 : rect.r1 - rect.r0 + 1;
1078
+ if (len > MAX_SCAN) return err("#N/A");
1079
+ const at = (i) => horizontal ? refGet(range.sheet, ctx, rect.r0, rect.c0 + i) : refGet(range.sheet, ctx, rect.r0 + i, rect.c0);
1080
+ if (type === 0) {
1081
+ const re = target.t === "str" ? wildcardToRegExp(target.v) : void 0;
1082
+ for (let i = 0; i < len; i++) {
1083
+ const cell = at(i);
1084
+ if (re ? cell.t === "str" && re.test(cell.v) : scalarEquals(cell, target)) return num(i + 1);
1085
+ }
1086
+ return err("#N/A");
1087
+ }
1088
+ let best = -1;
1089
+ for (let i = 0; i < len; i++) {
1090
+ const cmp = cmpScalar(at(i), target);
1091
+ if (cmp === void 0) continue;
1092
+ if (type === 1 ? cmp <= 0 : cmp >= 0) best = i;
1093
+ else break;
1094
+ }
1095
+ return best < 0 ? err("#N/A") : num(best + 1);
1096
+ }
1097
+ function indexFn(args, ev, ctx) {
1098
+ if (args.length < 2 || args.length > 3) return err("#VALUE!");
1099
+ const range = asRef(ev(args[0]));
1100
+ if (!range) return err("#VALUE!");
1101
+ const rect = range.rect;
1102
+ const rn = numArg(args, ev, ctx, 1);
1103
+ if (typeof rn !== "number") return err(rn.e);
1104
+ let r = Math.trunc(rn);
1105
+ let cn = 1;
1106
+ if (args.length === 3) {
1107
+ const c = numArg(args, ev, ctx, 2);
1108
+ if (typeof c !== "number") return err(c.e);
1109
+ cn = Math.trunc(c);
1110
+ }
1111
+ const rows = rect.r1 - rect.r0 + 1;
1112
+ const cols = rect.c1 - rect.c0 + 1;
1113
+ if (args.length === 2 && rows === 1 && cols > 1) {
1114
+ cn = r;
1115
+ r = 1;
1116
+ }
1117
+ if (r < 0 || cn < 0 || r > rows || cn > cols) return err("#REF!");
1118
+ if (r === 0 || cn === 0) return err("#VALUE!");
1119
+ return refGet(range.sheet, ctx, rect.r0 + r - 1, rect.c0 + cn - 1);
1120
+ }
1121
+ function lookupFn(args, ev, ctx, vh) {
1122
+ if (args.length < 3 || args.length > 4) return err("#VALUE!");
1123
+ const target = deref(ev(args[0]), ctx);
1124
+ if (target.t === "err") return target;
1125
+ const table = asRef(ev(args[1]));
1126
+ if (!table) return err("#VALUE!");
1127
+ const rect = table.rect;
1128
+ const sh = table.sheet;
1129
+ const idx = numArg(args, ev, ctx, 2);
1130
+ if (typeof idx !== "number") return err(idx.e);
1131
+ const line = Math.trunc(idx);
1132
+ let approx = true;
1133
+ if (args.length === 4) {
1134
+ const b = toBool(ev(args[3]), ctx);
1135
+ if (typeof b === "string") return err(b);
1136
+ approx = b;
1137
+ }
1138
+ const rows = rect.r1 - rect.r0 + 1;
1139
+ const cols = rect.c1 - rect.c0 + 1;
1140
+ const vertical = vh === "v";
1141
+ const vecLen = vertical ? rows : cols;
1142
+ if (line < 1 || line > (vertical ? cols : rows)) return err("#REF!");
1143
+ if (vecLen > MAX_SCAN) return err("#N/A");
1144
+ const keyAt = (i) => vertical ? refGet(sh, ctx, rect.r0 + i, rect.c0) : refGet(sh, ctx, rect.r0, rect.c0 + i);
1145
+ const resultAt = (i) => vertical ? refGet(sh, ctx, rect.r0 + i, rect.c0 + line - 1) : refGet(sh, ctx, rect.r0 + line - 1, rect.c0 + i);
1146
+ if (!approx) {
1147
+ const re = target.t === "str" ? wildcardToRegExp(target.v) : void 0;
1148
+ for (let i = 0; i < vecLen; i++) {
1149
+ const k = keyAt(i);
1150
+ if (re ? k.t === "str" && re.test(k.v) : scalarEquals(k, target)) return resultAt(i);
1151
+ }
1152
+ return err("#N/A");
1153
+ }
1154
+ let best = -1;
1155
+ for (let i = 0; i < vecLen; i++) {
1156
+ const cmp = cmpScalar(keyAt(i), target);
1157
+ if (cmp === void 0) continue;
1158
+ if (cmp <= 0) best = i;
1159
+ else break;
1160
+ }
1161
+ return best < 0 ? err("#N/A") : resultAt(best);
1162
+ }
1163
+ function math2(args, ev, ctx, f) {
1164
+ if (args.length !== 2) return err("#VALUE!");
1165
+ const a = numArg(args, ev, ctx, 0);
1166
+ if (typeof a !== "number") return err(a.e);
1167
+ const b = numArg(args, ev, ctx, 1);
1168
+ if (typeof b !== "number") return err(b.e);
1169
+ const r = f(a, b);
1170
+ return Number.isNaN(r) ? err("#NUM!") : num(r);
1171
+ }
1172
+ function logFn(args, ev, ctx) {
1173
+ if (args.length < 1 || args.length > 2) return err("#VALUE!");
1174
+ const x = numArg(args, ev, ctx, 0);
1175
+ if (typeof x !== "number") return err(x.e);
1176
+ let base = 10;
1177
+ if (args.length === 2) {
1178
+ const b = numArg(args, ev, ctx, 1);
1179
+ if (typeof b !== "number") return err(b.e);
1180
+ base = b;
1181
+ }
1182
+ if (x <= 0 || base <= 0 || base === 1) return err("#NUM!");
1183
+ return num(Math.log(x) / Math.log(base));
1184
+ }
1185
+ function factFn(args, ev, ctx) {
1186
+ if (args.length !== 1) return err("#VALUE!");
1187
+ const n = numArg(args, ev, ctx, 0);
1188
+ if (typeof n !== "number") return err(n.e);
1189
+ const k = Math.trunc(n);
1190
+ if (k < 0 || k > 170) return err("#NUM!");
1191
+ let r = 1;
1192
+ for (let i = 2; i <= k; i++) r *= i;
1193
+ return num(r);
1194
+ }
1195
+ function combinPermut(args, ev, ctx, perm) {
1196
+ if (args.length !== 2) return err("#VALUE!");
1197
+ const nN = numArg(args, ev, ctx, 0);
1198
+ if (typeof nN !== "number") return err(nN.e);
1199
+ const kN = numArg(args, ev, ctx, 1);
1200
+ if (typeof kN !== "number") return err(kN.e);
1201
+ const n = Math.trunc(nN);
1202
+ const k = Math.trunc(kN);
1203
+ if (n < 0 || k < 0 || k > n) return err("#NUM!");
1204
+ let p = 1;
1205
+ for (let i = 0; i < k; i++) p *= n - i;
1206
+ if (perm) return num(p);
1207
+ let kf = 1;
1208
+ for (let i = 2; i <= k; i++) kf *= i;
1209
+ return num(Math.round(p / kf));
1210
+ }
1211
+ function statSpread(args, ev, ctx, kind, sample) {
1212
+ const ns = gatherNumbers(args, ev, ctx);
1213
+ if (!Array.isArray(ns)) return err(ns);
1214
+ const n = ns.length;
1215
+ if (n === 0 || sample && n < 2) return err("#DIV/0!");
1216
+ const mean = ns.reduce((a, b) => a + b, 0) / n;
1217
+ if (kind === "avedev") return num(ns.reduce((a, b) => a + Math.abs(b - mean), 0) / n);
1218
+ const ss = ns.reduce((a, b) => a + (b - mean) * (b - mean), 0);
1219
+ if (kind === "devsq") return num(ss);
1220
+ const variance = ss / (sample ? n - 1 : n);
1221
+ return num(kind === "var" ? variance : Math.sqrt(variance));
1222
+ }
1223
+ function geoHarMean(args, ev, ctx, geo) {
1224
+ const ns = gatherNumbers(args, ev, ctx);
1225
+ if (!Array.isArray(ns)) return err(ns);
1226
+ if (ns.length === 0 || ns.some((x) => x <= 0)) return err("#NUM!");
1227
+ if (geo) return num(Math.exp(ns.reduce((a, b) => a + Math.log(b), 0) / ns.length));
1228
+ return num(ns.length / ns.reduce((a, b) => a + 1 / b, 0));
1229
+ }
1230
+ function aggregateA(args, ev, ctx, kind) {
1231
+ const ns = [];
1232
+ let e;
1233
+ const take = (s) => {
1234
+ if (s.t === "num") ns.push(s.v);
1235
+ else if (s.t === "bool") ns.push(s.v ? 1 : 0);
1236
+ else if (s.t === "str") ns.push(0);
1237
+ else if (s.t === "err") e ??= s.v;
1238
+ };
1239
+ for (const a of args) {
1240
+ const v = ev(a);
1241
+ if (v.t === "ref") refEach(v, ctx, (_r, _c, s) => take(s));
1242
+ else take(deref(v, ctx));
1243
+ }
1244
+ if (e) return err(e);
1245
+ if (ns.length === 0) return kind === "avg" ? err("#DIV/0!") : num(0);
1246
+ if (kind === "avg") return num(ns.reduce((a, b) => a + b, 0) / ns.length);
1247
+ return num(kind === "max" ? Math.max(...ns) : Math.min(...ns));
1248
+ }
1249
+ function modeFn(args, ev, ctx) {
1250
+ const ns = gatherNumbers(args, ev, ctx);
1251
+ if (!Array.isArray(ns)) return err(ns);
1252
+ const counts = /* @__PURE__ */ new Map();
1253
+ for (const x of ns) counts.set(x, (counts.get(x) ?? 0) + 1);
1254
+ let maxCount = 1;
1255
+ for (const c of counts.values()) if (c > maxCount) maxCount = c;
1256
+ if (maxCount < 2) return err("#N/A");
1257
+ for (const x of ns) if (counts.get(x) === maxCount) return num(x);
1258
+ return err("#N/A");
1259
+ }
1260
+ function rankFn(args, ev, ctx) {
1261
+ if (args.length < 2 || args.length > 3) return err("#VALUE!");
1262
+ const x = numArg(args, ev, ctx, 0);
1263
+ if (typeof x !== "number") return err(x.e);
1264
+ const ns = gatherNumbers([args[1]], ev, ctx);
1265
+ if (!Array.isArray(ns)) return err(ns);
1266
+ let asc = false;
1267
+ if (args.length === 3) {
1268
+ const o = numArg(args, ev, ctx, 2);
1269
+ if (typeof o !== "number") return err(o.e);
1270
+ asc = o !== 0;
1271
+ }
1272
+ if (!ns.includes(x)) return err("#N/A");
1273
+ let rank = 1;
1274
+ for (const v of ns) if (asc ? v < x : v > x) rank++;
1275
+ return num(rank);
1276
+ }
1277
+ function percentileFn(args, ev, ctx) {
1278
+ if (args.length !== 2) return err("#VALUE!");
1279
+ const ns = gatherNumbers([args[0]], ev, ctx);
1280
+ if (!Array.isArray(ns)) return err(ns);
1281
+ const k = numArg(args, ev, ctx, 1);
1282
+ if (typeof k !== "number") return err(k.e);
1283
+ return percentile(ns, k);
1284
+ }
1285
+ function quartileFn(args, ev, ctx) {
1286
+ if (args.length !== 2) return err("#VALUE!");
1287
+ const ns = gatherNumbers([args[0]], ev, ctx);
1288
+ if (!Array.isArray(ns)) return err(ns);
1289
+ const q = numArg(args, ev, ctx, 1);
1290
+ if (typeof q !== "number") return err(q.e);
1291
+ const qi = Math.trunc(q);
1292
+ if (qi < 0 || qi > 4) return err("#NUM!");
1293
+ return percentile(ns, qi / 4);
1294
+ }
1295
+ function percentile(ns, k) {
1296
+ if (ns.length === 0 || k < 0 || k > 1) return err("#NUM!");
1297
+ const sorted = [...ns].sort((a, b) => a - b);
1298
+ const pos = k * (sorted.length - 1);
1299
+ const lo = Math.floor(pos);
1300
+ const hi = Math.ceil(pos);
1301
+ return num(sorted[lo] + (sorted[hi] - sorted[lo]) * (pos - lo));
1302
+ }
1303
+ function rectArg(arg, ev) {
1304
+ const v = ev(arg);
1305
+ return v.t === "ref" ? v.rect : void 0;
1306
+ }
1307
+ function rowColFn(args, ev, shift, isRow) {
1308
+ if (args.length === 0) {
1309
+ const cur = isRow ? shift.curRow : shift.curCol;
1310
+ return cur === void 0 ? err("#VALUE!") : num(cur + 1);
1311
+ }
1312
+ if (args.length !== 1) return err("#VALUE!");
1313
+ const rect = rectArg(args[0], ev);
1314
+ return rect ? num((isRow ? rect.r0 : rect.c0) + 1) : err("#VALUE!");
1315
+ }
1316
+ function rowsColsFn(args, ev, isRows) {
1317
+ if (args.length !== 1) return err("#VALUE!");
1318
+ const rect = rectArg(args[0], ev);
1319
+ if (!rect) return err("#VALUE!");
1320
+ return num(isRows ? rect.r1 - rect.r0 + 1 : rect.c1 - rect.c0 + 1);
1321
+ }
1322
+ function typeFn(args, ev, ctx) {
1323
+ if (args.length !== 1) return err("#VALUE!");
1324
+ const s = deref(ev(args[0]), ctx);
1325
+ if (s.t === "str") return num(2);
1326
+ if (s.t === "bool") return num(4);
1327
+ if (s.t === "err") return num(16);
1328
+ return num(1);
1329
+ }
1330
+ var ERROR_TYPE_CODES = {
1331
+ "#NULL!": 1,
1332
+ "#DIV/0!": 2,
1333
+ "#VALUE!": 3,
1334
+ "#REF!": 4,
1335
+ "#NAME?": 5,
1336
+ "#NUM!": 6,
1337
+ "#N/A": 7
1338
+ };
1339
+ function errorTypeFn(args, ev, ctx) {
1340
+ if (args.length !== 1) return err("#VALUE!");
1341
+ const s = deref(ev(args[0]), ctx);
1342
+ return s.t === "err" ? num(ERROR_TYPE_CODES[s.v]) : err("#N/A");
1343
+ }
1344
+ function unicharFn(args, ev, ctx) {
1345
+ if (args.length !== 1) return err("#VALUE!");
1346
+ const n = numArg(args, ev, ctx, 0);
1347
+ if (typeof n !== "number") return err(n.e);
1348
+ const cp = Math.trunc(n);
1349
+ if (cp < 1 || cp > 1114111) return err("#VALUE!");
1350
+ return str(String.fromCodePoint(cp));
1351
+ }
1352
+ function unicodeFn(args, ev, ctx) {
1353
+ const t = textArg(args, ev, ctx, 0);
1354
+ if (typeof t !== "string") return err(t.v);
1355
+ if (args.length !== 1 || t.length === 0) return err("#VALUE!");
1356
+ return num(t.codePointAt(0));
1357
+ }
1358
+ //#endregion
1359
+ export { callFn };