@cj-tech-master/excelts 9.3.1 → 9.4.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/browser/index.d.ts +1 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/modules/excel/cell.d.ts +18 -0
- package/dist/browser/modules/excel/cell.js +21 -0
- package/dist/browser/modules/excel/utils/cell-format.js +85 -13
- package/dist/browser/modules/excel/workbook.browser.d.ts +57 -0
- package/dist/browser/modules/excel/workbook.browser.js +49 -0
- package/dist/browser/modules/excel/xlsx/defaultnumformats.js +3 -3
- package/dist/browser/modules/formula/compile/binder.js +48 -6
- package/dist/browser/modules/formula/compile/bound-ast.d.ts +16 -2
- package/dist/browser/modules/formula/compile/bound-ast.js +1 -0
- package/dist/browser/modules/formula/compile/compiled-formula.js +41 -8
- package/dist/browser/modules/formula/functions/_shared.d.ts +19 -0
- package/dist/browser/modules/formula/functions/_shared.js +47 -0
- package/dist/browser/modules/formula/functions/conditional.js +103 -22
- package/dist/browser/modules/formula/functions/date.js +105 -23
- package/dist/browser/modules/formula/functions/dynamic-array.js +173 -69
- package/dist/browser/modules/formula/functions/engineering.d.ts +2 -2
- package/dist/browser/modules/formula/functions/engineering.js +103 -151
- package/dist/browser/modules/formula/functions/financial.js +210 -184
- package/dist/browser/modules/formula/functions/lookup.js +224 -157
- package/dist/browser/modules/formula/functions/math.d.ts +26 -0
- package/dist/browser/modules/formula/functions/math.js +249 -69
- package/dist/browser/modules/formula/functions/statistical.js +221 -171
- package/dist/browser/modules/formula/functions/text.js +112 -52
- package/dist/browser/modules/formula/integration/calculate-formulas-impl.js +20 -1
- package/dist/browser/modules/formula/materialize/build-writeback-plan.js +10 -6
- package/dist/browser/modules/formula/materialize/types.d.ts +15 -0
- package/dist/browser/modules/formula/runtime/evaluator.d.ts +8 -0
- package/dist/browser/modules/formula/runtime/evaluator.js +582 -162
- package/dist/browser/modules/formula/runtime/function-registry.d.ts +5 -0
- package/dist/browser/modules/formula/runtime/function-registry.js +59 -13
- package/dist/browser/modules/formula/runtime/values.d.ts +13 -0
- package/dist/browser/modules/formula/runtime/values.js +20 -2
- package/dist/browser/modules/formula/syntax/ast.d.ts +14 -2
- package/dist/browser/modules/formula/syntax/ast.js +1 -0
- package/dist/browser/modules/formula/syntax/parser.js +29 -7
- package/dist/browser/modules/formula/syntax/token-types.d.ts +4 -0
- package/dist/browser/modules/formula/syntax/token-types.js +9 -0
- package/dist/browser/modules/formula/syntax/tokenizer.js +76 -19
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/modules/excel/cell.js +21 -0
- package/dist/cjs/modules/excel/utils/cell-format.js +85 -13
- package/dist/cjs/modules/excel/workbook.browser.js +49 -0
- package/dist/cjs/modules/excel/xlsx/defaultnumformats.js +3 -3
- package/dist/cjs/modules/formula/compile/binder.js +48 -6
- package/dist/cjs/modules/formula/compile/compiled-formula.js +41 -8
- package/dist/cjs/modules/formula/functions/_shared.js +48 -0
- package/dist/cjs/modules/formula/functions/conditional.js +103 -22
- package/dist/cjs/modules/formula/functions/date.js +104 -22
- package/dist/cjs/modules/formula/functions/dynamic-array.js +173 -69
- package/dist/cjs/modules/formula/functions/engineering.js +109 -157
- package/dist/cjs/modules/formula/functions/financial.js +209 -183
- package/dist/cjs/modules/formula/functions/lookup.js +224 -157
- package/dist/cjs/modules/formula/functions/math.js +254 -70
- package/dist/cjs/modules/formula/functions/statistical.js +222 -172
- package/dist/cjs/modules/formula/functions/text.js +112 -52
- package/dist/cjs/modules/formula/integration/calculate-formulas-impl.js +20 -1
- package/dist/cjs/modules/formula/materialize/build-writeback-plan.js +10 -6
- package/dist/cjs/modules/formula/runtime/evaluator.js +581 -161
- package/dist/cjs/modules/formula/runtime/function-registry.js +57 -11
- package/dist/cjs/modules/formula/runtime/values.js +21 -2
- package/dist/cjs/modules/formula/syntax/parser.js +29 -7
- package/dist/cjs/modules/formula/syntax/token-types.js +9 -0
- package/dist/cjs/modules/formula/syntax/tokenizer.js +76 -19
- package/dist/esm/index.js +2 -0
- package/dist/esm/modules/excel/cell.js +21 -0
- package/dist/esm/modules/excel/utils/cell-format.js +85 -13
- package/dist/esm/modules/excel/workbook.browser.js +49 -0
- package/dist/esm/modules/excel/xlsx/defaultnumformats.js +3 -3
- package/dist/esm/modules/formula/compile/binder.js +48 -6
- package/dist/esm/modules/formula/compile/bound-ast.js +1 -0
- package/dist/esm/modules/formula/compile/compiled-formula.js +41 -8
- package/dist/esm/modules/formula/functions/_shared.js +47 -0
- package/dist/esm/modules/formula/functions/conditional.js +103 -22
- package/dist/esm/modules/formula/functions/date.js +105 -23
- package/dist/esm/modules/formula/functions/dynamic-array.js +173 -69
- package/dist/esm/modules/formula/functions/engineering.js +103 -151
- package/dist/esm/modules/formula/functions/financial.js +210 -184
- package/dist/esm/modules/formula/functions/lookup.js +224 -157
- package/dist/esm/modules/formula/functions/math.js +249 -69
- package/dist/esm/modules/formula/functions/statistical.js +221 -171
- package/dist/esm/modules/formula/functions/text.js +112 -52
- package/dist/esm/modules/formula/integration/calculate-formulas-impl.js +20 -1
- package/dist/esm/modules/formula/materialize/build-writeback-plan.js +10 -6
- package/dist/esm/modules/formula/runtime/evaluator.js +582 -162
- package/dist/esm/modules/formula/runtime/function-registry.js +59 -13
- package/dist/esm/modules/formula/runtime/values.js +20 -2
- package/dist/esm/modules/formula/syntax/ast.js +1 -0
- package/dist/esm/modules/formula/syntax/parser.js +29 -7
- package/dist/esm/modules/formula/syntax/token-types.js +9 -0
- package/dist/esm/modules/formula/syntax/tokenizer.js +76 -19
- package/dist/iife/excelts.iife.js +1502 -1379
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +26 -26
- package/dist/types/index.d.ts +1 -0
- package/dist/types/modules/excel/cell.d.ts +18 -0
- package/dist/types/modules/excel/workbook.browser.d.ts +57 -0
- package/dist/types/modules/formula/compile/bound-ast.d.ts +16 -2
- package/dist/types/modules/formula/functions/_shared.d.ts +19 -0
- package/dist/types/modules/formula/functions/engineering.d.ts +2 -2
- package/dist/types/modules/formula/functions/math.d.ts +26 -0
- package/dist/types/modules/formula/materialize/types.d.ts +15 -0
- package/dist/types/modules/formula/runtime/evaluator.d.ts +8 -0
- package/dist/types/modules/formula/runtime/function-registry.d.ts +5 -0
- package/dist/types/modules/formula/runtime/values.d.ts +13 -0
- package/dist/types/modules/formula/syntax/ast.d.ts +14 -2
- package/dist/types/modules/formula/syntax/token-types.d.ts +4 -0
- package/package.json +1 -1
|
@@ -78,32 +78,73 @@ function fnFILTER(args) {
|
|
|
78
78
|
if (!dataArr || !includeArr) {
|
|
79
79
|
return values_1.ERRORS.VALUE;
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
|
|
81
|
+
const ifEmpty = args.length > 2 && args[2].kind !== 0 /* RVKind.Blank */ ? (0, values_1.topLeft)(args[2]) : null;
|
|
82
|
+
// Decide filter orientation from the include vector's shape:
|
|
83
|
+
// - N×1 vector matching data.height → ROW filter (classic).
|
|
84
|
+
// - 1×N vector matching data.width → COL filter (Excel supports
|
|
85
|
+
// both; previously we hard-required the row shape and silently
|
|
86
|
+
// rejected column filters with #VALUE!).
|
|
87
|
+
// A 1×1 include vector is treated as a row filter over 1 row.
|
|
88
|
+
const isRowFilter = includeArr.width === 1 && includeArr.height === dataArr.height;
|
|
89
|
+
const isColFilter = !isRowFilter && includeArr.height === 1 && includeArr.width === dataArr.width;
|
|
90
|
+
if (!isRowFilter && !isColFilter) {
|
|
86
91
|
return values_1.ERRORS.VALUE;
|
|
87
92
|
}
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
const cellIsTruthy = (cell) => {
|
|
94
|
+
if (cell.kind === 4 /* RVKind.Error */) {
|
|
95
|
+
return cell;
|
|
96
|
+
}
|
|
97
|
+
if (cell.kind === 3 /* RVKind.Boolean */) {
|
|
98
|
+
return cell.value;
|
|
99
|
+
}
|
|
100
|
+
if (cell.kind === 1 /* RVKind.Number */) {
|
|
101
|
+
return cell.value !== 0;
|
|
102
|
+
}
|
|
103
|
+
// Blank / String / anything else → treated as FALSE.
|
|
104
|
+
return false;
|
|
105
|
+
};
|
|
106
|
+
if (isRowFilter) {
|
|
107
|
+
const resultRows = [];
|
|
108
|
+
for (let r = 0; r < dataArr.height; r++) {
|
|
109
|
+
const truthy = cellIsTruthy((0, _shared_1.getCell)(includeArr, r, 0));
|
|
110
|
+
if (typeof truthy !== "boolean") {
|
|
111
|
+
return truthy;
|
|
100
112
|
}
|
|
101
|
-
|
|
113
|
+
if (truthy) {
|
|
114
|
+
const row = [];
|
|
115
|
+
for (let c = 0; c < dataArr.width; c++) {
|
|
116
|
+
row.push((0, _shared_1.getCell)(dataArr, r, c));
|
|
117
|
+
}
|
|
118
|
+
resultRows.push(row);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (resultRows.length === 0) {
|
|
122
|
+
return ifEmpty !== null ? (0, values_1.rvArray)([[ifEmpty]]) : values_1.ERRORS.CALC;
|
|
123
|
+
}
|
|
124
|
+
return (0, values_1.rvArray)(resultRows);
|
|
125
|
+
}
|
|
126
|
+
// Column filter — pick a subset of columns across every row.
|
|
127
|
+
const keepCols = [];
|
|
128
|
+
for (let c = 0; c < dataArr.width; c++) {
|
|
129
|
+
const truthy = cellIsTruthy((0, _shared_1.getCell)(includeArr, 0, c));
|
|
130
|
+
if (typeof truthy !== "boolean") {
|
|
131
|
+
return truthy;
|
|
132
|
+
}
|
|
133
|
+
if (truthy) {
|
|
134
|
+
keepCols.push(c);
|
|
102
135
|
}
|
|
103
136
|
}
|
|
104
|
-
if (
|
|
137
|
+
if (keepCols.length === 0) {
|
|
105
138
|
return ifEmpty !== null ? (0, values_1.rvArray)([[ifEmpty]]) : values_1.ERRORS.CALC;
|
|
106
139
|
}
|
|
140
|
+
const resultRows = [];
|
|
141
|
+
for (let r = 0; r < dataArr.height; r++) {
|
|
142
|
+
const row = new Array(keepCols.length);
|
|
143
|
+
for (let i = 0; i < keepCols.length; i++) {
|
|
144
|
+
row[i] = (0, _shared_1.getCell)(dataArr, r, keepCols[i]);
|
|
145
|
+
}
|
|
146
|
+
resultRows.push(row);
|
|
147
|
+
}
|
|
107
148
|
return (0, values_1.rvArray)(resultRows);
|
|
108
149
|
}
|
|
109
150
|
function fnSORT(args) {
|
|
@@ -119,15 +160,26 @@ function fnSORT(args) {
|
|
|
119
160
|
}
|
|
120
161
|
rows.push(row);
|
|
121
162
|
}
|
|
122
|
-
const sortIndexV = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(1);
|
|
163
|
+
const sortIndexV = args.length > 1 && args[1].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(1);
|
|
123
164
|
if ((0, values_1.isError)(sortIndexV)) {
|
|
124
165
|
return sortIndexV;
|
|
125
166
|
}
|
|
126
|
-
|
|
167
|
+
// Blank `sort_order` → Excel's default 1 (ascending). Without this
|
|
168
|
+
// guard the blank coerces through `toNumberRV` to 0, which multiplies
|
|
169
|
+
// the comparator output and produces a no-op sort — every pair is
|
|
170
|
+
// treated as equal and the output order is engine-defined noise.
|
|
171
|
+
const sortOrderV = args.length > 2 && args[2].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[2])) : (0, values_1.rvNumber)(1);
|
|
127
172
|
if ((0, values_1.isError)(sortOrderV)) {
|
|
128
173
|
return sortOrderV;
|
|
129
174
|
}
|
|
130
|
-
|
|
175
|
+
// Excel restricts `sort_order` to exactly 1 or -1; any other integer
|
|
176
|
+
// (0, 2, 3, …) is #VALUE!. Previously zero silently disabled the sort.
|
|
177
|
+
if (sortOrderV.value !== 1 && sortOrderV.value !== -1) {
|
|
178
|
+
return values_1.ERRORS.VALUE;
|
|
179
|
+
}
|
|
180
|
+
const byColV = args.length > 3
|
|
181
|
+
? (0, values_1.toBooleanRV)((0, values_1.topLeft)(args[3]))
|
|
182
|
+
: { kind: 3 /* RVKind.Boolean */, value: false };
|
|
131
183
|
if ((0, values_1.isError)(byColV)) {
|
|
132
184
|
return byColV;
|
|
133
185
|
}
|
|
@@ -161,11 +213,15 @@ function fnUNIQUE(args) {
|
|
|
161
213
|
if (!dataArr) {
|
|
162
214
|
return values_1.ERRORS.VALUE;
|
|
163
215
|
}
|
|
164
|
-
const byColV = args.length > 1
|
|
216
|
+
const byColV = args.length > 1
|
|
217
|
+
? (0, values_1.toBooleanRV)((0, values_1.topLeft)(args[1]))
|
|
218
|
+
: { kind: 3 /* RVKind.Boolean */, value: false };
|
|
165
219
|
if ((0, values_1.isError)(byColV)) {
|
|
166
220
|
return byColV;
|
|
167
221
|
}
|
|
168
|
-
const exactlyOnceV = args.length > 2
|
|
222
|
+
const exactlyOnceV = args.length > 2
|
|
223
|
+
? (0, values_1.toBooleanRV)((0, values_1.topLeft)(args[2]))
|
|
224
|
+
: { kind: 3 /* RVKind.Boolean */, value: false };
|
|
169
225
|
if ((0, values_1.isError)(exactlyOnceV)) {
|
|
170
226
|
return exactlyOnceV;
|
|
171
227
|
}
|
|
@@ -266,10 +322,18 @@ function fnSORTBY(args) {
|
|
|
266
322
|
if (!keyArr) {
|
|
267
323
|
return values_1.ERRORS.VALUE;
|
|
268
324
|
}
|
|
269
|
-
|
|
325
|
+
// Blank order → default 1 (ascending); anything other than ±1 is
|
|
326
|
+
// #VALUE!. Mirrors the SORT validation — a blank used to produce
|
|
327
|
+
// 0 via `toNumberRV`, silently disabling the sort key.
|
|
328
|
+
const orderV = i + 1 < args.length && args[i + 1].kind !== 0 /* RVKind.Blank */
|
|
329
|
+
? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[i + 1]))
|
|
330
|
+
: (0, values_1.rvNumber)(1);
|
|
270
331
|
if ((0, values_1.isError)(orderV)) {
|
|
271
332
|
return orderV;
|
|
272
333
|
}
|
|
334
|
+
if (orderV.value !== 1 && orderV.value !== -1) {
|
|
335
|
+
return values_1.ERRORS.VALUE;
|
|
336
|
+
}
|
|
273
337
|
sortKeys.push({ arr: keyArr, order: orderV.value });
|
|
274
338
|
}
|
|
275
339
|
data.sort((a, b) => {
|
|
@@ -286,7 +350,7 @@ function fnSORTBY(args) {
|
|
|
286
350
|
return (0, values_1.rvArray)(data.map(d => d.row));
|
|
287
351
|
}
|
|
288
352
|
function fnSUBTOTAL(args) {
|
|
289
|
-
const funcNumV = (0, values_1.toNumberRV)(args[0]);
|
|
353
|
+
const funcNumV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
|
|
290
354
|
if ((0, values_1.isError)(funcNumV)) {
|
|
291
355
|
return funcNumV;
|
|
292
356
|
}
|
|
@@ -338,7 +402,7 @@ function fnSUBTOTAL(args) {
|
|
|
338
402
|
}
|
|
339
403
|
}
|
|
340
404
|
function fnAGGREGATE(args) {
|
|
341
|
-
const funcNumV = (0, values_1.toNumberRV)(args[0]);
|
|
405
|
+
const funcNumV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
|
|
342
406
|
if ((0, values_1.isError)(funcNumV)) {
|
|
343
407
|
return funcNumV;
|
|
344
408
|
}
|
|
@@ -352,7 +416,7 @@ function fnAGGREGATE(args) {
|
|
|
352
416
|
// 5 → ignore hidden rows (keep nested)
|
|
353
417
|
// 6 → ignore errors (keep nested)
|
|
354
418
|
// 7 → ignore hidden rows + errors (keep nested)
|
|
355
|
-
const optV = args[1] !== undefined ? (0, values_1.toNumberRV)(args[1]) : undefined;
|
|
419
|
+
const optV = args[1] !== undefined ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : undefined;
|
|
356
420
|
if (optV && (0, values_1.isError)(optV)) {
|
|
357
421
|
return optV;
|
|
358
422
|
}
|
|
@@ -417,19 +481,22 @@ function fnAGGREGATE(args) {
|
|
|
417
481
|
}
|
|
418
482
|
}
|
|
419
483
|
function fnSEQUENCE(args) {
|
|
420
|
-
const rowsV = (0, values_1.toNumberRV)(args[0]);
|
|
484
|
+
const rowsV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
|
|
421
485
|
if ((0, values_1.isError)(rowsV)) {
|
|
422
486
|
return rowsV;
|
|
423
487
|
}
|
|
424
|
-
|
|
488
|
+
// Blank `cols` / `start` / `step` → Excel defaults 1 / 1 / 1. Without
|
|
489
|
+
// the blank guards, `SEQUENCE(5, )` coerces blank → 0 → `colCount < 1`
|
|
490
|
+
// → #NUM! instead of Excel's single-column sequence.
|
|
491
|
+
const colsV = args.length > 1 && args[1].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(1);
|
|
425
492
|
if ((0, values_1.isError)(colsV)) {
|
|
426
493
|
return colsV;
|
|
427
494
|
}
|
|
428
|
-
const startV = args.length > 2 ? (0, values_1.toNumberRV)(args[2]) : (0, values_1.rvNumber)(1);
|
|
495
|
+
const startV = args.length > 2 && args[2].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[2])) : (0, values_1.rvNumber)(1);
|
|
429
496
|
if ((0, values_1.isError)(startV)) {
|
|
430
497
|
return startV;
|
|
431
498
|
}
|
|
432
|
-
const stepV = args.length > 3 ? (0, values_1.toNumberRV)(args[3]) : (0, values_1.rvNumber)(1);
|
|
499
|
+
const stepV = args.length > 3 && args[3].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[3])) : (0, values_1.rvNumber)(1);
|
|
433
500
|
if ((0, values_1.isError)(stepV)) {
|
|
434
501
|
return stepV;
|
|
435
502
|
}
|
|
@@ -461,23 +528,29 @@ function fnSEQUENCE(args) {
|
|
|
461
528
|
return (0, values_1.rvArray)(result);
|
|
462
529
|
}
|
|
463
530
|
function fnRANDARRAY(args) {
|
|
464
|
-
|
|
531
|
+
// Each arg has a distinct Excel default; blank must be distinguished
|
|
532
|
+
// from an explicit 0, which would cause rows/cols validation to
|
|
533
|
+
// reject the call. Blanks → engine defaults (rows=1, cols=1, min=0,
|
|
534
|
+
// max=1, whole=FALSE).
|
|
535
|
+
const rowsV = args.length > 0 && args[0].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0])) : (0, values_1.rvNumber)(1);
|
|
465
536
|
if ((0, values_1.isError)(rowsV)) {
|
|
466
537
|
return rowsV;
|
|
467
538
|
}
|
|
468
|
-
const colsV = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(1);
|
|
539
|
+
const colsV = args.length > 1 && args[1].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(1);
|
|
469
540
|
if ((0, values_1.isError)(colsV)) {
|
|
470
541
|
return colsV;
|
|
471
542
|
}
|
|
472
|
-
const minV = args.length > 2 ? (0, values_1.toNumberRV)(args[2]) : (0, values_1.rvNumber)(0);
|
|
543
|
+
const minV = args.length > 2 && args[2].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[2])) : (0, values_1.rvNumber)(0);
|
|
473
544
|
if ((0, values_1.isError)(minV)) {
|
|
474
545
|
return minV;
|
|
475
546
|
}
|
|
476
|
-
const maxV = args.length > 3 ? (0, values_1.toNumberRV)(args[3]) : (0, values_1.rvNumber)(1);
|
|
547
|
+
const maxV = args.length > 3 && args[3].kind !== 0 /* RVKind.Blank */ ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[3])) : (0, values_1.rvNumber)(1);
|
|
477
548
|
if ((0, values_1.isError)(maxV)) {
|
|
478
549
|
return maxV;
|
|
479
550
|
}
|
|
480
|
-
const wholeV = args.length > 4
|
|
551
|
+
const wholeV = args.length > 4 && args[4].kind !== 0 /* RVKind.Blank */
|
|
552
|
+
? (0, values_1.toBooleanRV)((0, values_1.topLeft)(args[4]))
|
|
553
|
+
: { kind: 3 /* RVKind.Boolean */, value: false };
|
|
481
554
|
if ((0, values_1.isError)(wholeV)) {
|
|
482
555
|
return wholeV;
|
|
483
556
|
}
|
|
@@ -524,11 +597,13 @@ function fnTOCOL(args) {
|
|
|
524
597
|
return (0, values_1.rvArray)([[(0, values_1.topLeft)(args[0])]]);
|
|
525
598
|
}
|
|
526
599
|
const arr = args[0];
|
|
527
|
-
const ignoreV = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
|
|
600
|
+
const ignoreV = args.length > 1 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(0);
|
|
528
601
|
if ((0, values_1.isError)(ignoreV)) {
|
|
529
602
|
return ignoreV;
|
|
530
603
|
}
|
|
531
|
-
const scanV = args.length > 2
|
|
604
|
+
const scanV = args.length > 2
|
|
605
|
+
? (0, values_1.toBooleanRV)((0, values_1.topLeft)(args[2]))
|
|
606
|
+
: { kind: 3 /* RVKind.Boolean */, value: false };
|
|
532
607
|
if ((0, values_1.isError)(scanV)) {
|
|
533
608
|
return scanV;
|
|
534
609
|
}
|
|
@@ -566,11 +641,13 @@ function fnTOROW(args) {
|
|
|
566
641
|
return (0, values_1.rvArray)([[(0, values_1.topLeft)(args[0])]]);
|
|
567
642
|
}
|
|
568
643
|
const arr = args[0];
|
|
569
|
-
const ignoreV = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
|
|
644
|
+
const ignoreV = args.length > 1 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(0);
|
|
570
645
|
if ((0, values_1.isError)(ignoreV)) {
|
|
571
646
|
return ignoreV;
|
|
572
647
|
}
|
|
573
|
-
const scanV = args.length > 2
|
|
648
|
+
const scanV = args.length > 2
|
|
649
|
+
? (0, values_1.toBooleanRV)((0, values_1.topLeft)(args[2]))
|
|
650
|
+
: { kind: 3 /* RVKind.Boolean */, value: false };
|
|
574
651
|
if ((0, values_1.isError)(scanV)) {
|
|
575
652
|
return scanV;
|
|
576
653
|
}
|
|
@@ -610,11 +687,18 @@ function fnCHOOSEROWS(args) {
|
|
|
610
687
|
}
|
|
611
688
|
const result = [];
|
|
612
689
|
for (let i = 1; i < args.length; i++) {
|
|
613
|
-
const nV = (0, values_1.toNumberRV)(args[i]);
|
|
690
|
+
const nV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[i]));
|
|
614
691
|
if ((0, values_1.isError)(nV)) {
|
|
615
692
|
return nV;
|
|
616
693
|
}
|
|
617
|
-
|
|
694
|
+
// Excel truncates toward zero before the bounds check; without this,
|
|
695
|
+
// `CHOOSEROWS(A1:A5, 2.5)` would compute `idx = 1.5` and end up
|
|
696
|
+
// reading `d.rows[1.5]` (= undefined), throwing on the next index.
|
|
697
|
+
const raw = Math.trunc(nV.value);
|
|
698
|
+
if (raw === 0) {
|
|
699
|
+
return values_1.ERRORS.VALUE;
|
|
700
|
+
}
|
|
701
|
+
const idx = raw > 0 ? raw - 1 : d.height + raw;
|
|
618
702
|
if (idx < 0 || idx >= d.height) {
|
|
619
703
|
return values_1.ERRORS.VALUE;
|
|
620
704
|
}
|
|
@@ -633,11 +717,17 @@ function fnCHOOSECOLS(args) {
|
|
|
633
717
|
}
|
|
634
718
|
const ci = [];
|
|
635
719
|
for (let i = 1; i < args.length; i++) {
|
|
636
|
-
const nV = (0, values_1.toNumberRV)(args[i]);
|
|
720
|
+
const nV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[i]));
|
|
637
721
|
if ((0, values_1.isError)(nV)) {
|
|
638
722
|
return nV;
|
|
639
723
|
}
|
|
640
|
-
|
|
724
|
+
// Truncate fractional indices before the bounds check — see CHOOSEROWS
|
|
725
|
+
// for the rationale (fractional indices silently crash getCell).
|
|
726
|
+
const raw = Math.trunc(nV.value);
|
|
727
|
+
if (raw === 0) {
|
|
728
|
+
return values_1.ERRORS.VALUE;
|
|
729
|
+
}
|
|
730
|
+
const idx = raw > 0 ? raw - 1 : d.width + raw;
|
|
641
731
|
if (idx < 0 || idx >= d.width) {
|
|
642
732
|
return values_1.ERRORS.VALUE;
|
|
643
733
|
}
|
|
@@ -727,18 +817,24 @@ function fnTAKE(args) {
|
|
|
727
817
|
if (!d) {
|
|
728
818
|
return values_1.ERRORS.VALUE;
|
|
729
819
|
}
|
|
730
|
-
const rowsV = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(d.height);
|
|
820
|
+
const rowsV = args.length > 1 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(d.height);
|
|
731
821
|
if ((0, values_1.isError)(rowsV)) {
|
|
732
822
|
return rowsV;
|
|
733
823
|
}
|
|
734
|
-
const colsV = args.length > 2 ? (0, values_1.toNumberRV)(args[2]) : (0, values_1.rvNumber)(d.width);
|
|
824
|
+
const colsV = args.length > 2 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[2])) : (0, values_1.rvNumber)(d.width);
|
|
735
825
|
if ((0, values_1.isError)(colsV)) {
|
|
736
826
|
return colsV;
|
|
737
827
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
828
|
+
// Truncate toward zero before using these as array indices. Without
|
|
829
|
+
// it, `TAKE(A1:A5, 2.7)` lands `rE = 2.7` in the slice bounds; V8
|
|
830
|
+
// silently walks the integer range `0..2` but a misuse of the value
|
|
831
|
+
// elsewhere (`d.rows[r]` with `r` fractional) would return undefined.
|
|
832
|
+
const rows = Math.trunc(rowsV.value);
|
|
833
|
+
const cols = Math.trunc(colsV.value);
|
|
834
|
+
const rS = rows >= 0 ? 0 : Math.max(0, d.height + rows);
|
|
835
|
+
const rE = rows >= 0 ? Math.min(rows, d.height) : d.height;
|
|
836
|
+
const cS = cols >= 0 ? 0 : Math.max(0, d.width + cols);
|
|
837
|
+
const cE = cols >= 0 ? Math.min(cols, d.width) : d.width;
|
|
742
838
|
const result = [];
|
|
743
839
|
for (let r = rS; r < rE; r++) {
|
|
744
840
|
const row = [];
|
|
@@ -754,18 +850,21 @@ function fnDROP(args) {
|
|
|
754
850
|
if (!d) {
|
|
755
851
|
return values_1.ERRORS.VALUE;
|
|
756
852
|
}
|
|
757
|
-
const rowsV = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
|
|
853
|
+
const rowsV = args.length > 1 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(0);
|
|
758
854
|
if ((0, values_1.isError)(rowsV)) {
|
|
759
855
|
return rowsV;
|
|
760
856
|
}
|
|
761
|
-
const colsV = args.length > 2 ? (0, values_1.toNumberRV)(args[2]) : (0, values_1.rvNumber)(0);
|
|
857
|
+
const colsV = args.length > 2 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[2])) : (0, values_1.rvNumber)(0);
|
|
762
858
|
if ((0, values_1.isError)(colsV)) {
|
|
763
859
|
return colsV;
|
|
764
860
|
}
|
|
765
|
-
|
|
766
|
-
const
|
|
767
|
-
const
|
|
768
|
-
const
|
|
861
|
+
// Truncate — see TAKE for rationale.
|
|
862
|
+
const rows = Math.trunc(rowsV.value);
|
|
863
|
+
const cols = Math.trunc(colsV.value);
|
|
864
|
+
const rS = rows >= 0 ? rows : 0;
|
|
865
|
+
const rE = rows >= 0 ? d.height : d.height + rows;
|
|
866
|
+
const cS = cols >= 0 ? cols : 0;
|
|
867
|
+
const cE = cols >= 0 ? d.width : d.width + cols;
|
|
769
868
|
const result = [];
|
|
770
869
|
for (let r = rS; r < rE; r++) {
|
|
771
870
|
const row = [];
|
|
@@ -789,18 +888,22 @@ function fnWRAPROWS(args) {
|
|
|
789
888
|
flat.push((0, _shared_1.getCell)(arr, r, c));
|
|
790
889
|
}
|
|
791
890
|
}
|
|
792
|
-
const wcV = (0, values_1.toNumberRV)(args[1]);
|
|
891
|
+
const wcV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
|
|
793
892
|
if ((0, values_1.isError)(wcV)) {
|
|
794
893
|
return wcV;
|
|
795
894
|
}
|
|
796
|
-
|
|
895
|
+
// Truncate toward zero before using as a stride — `i += 2.5` and
|
|
896
|
+
// `row.length < 2.5` work by accidental float coercion in V8, but the
|
|
897
|
+
// intent is an integer wrap width; encode it explicitly.
|
|
898
|
+
const wc = Math.trunc(wcV.value);
|
|
899
|
+
if (wc < 1) {
|
|
797
900
|
return values_1.ERRORS.VALUE;
|
|
798
901
|
}
|
|
799
902
|
const pad = args.length > 2 ? (0, values_1.topLeft)(args[2]) : values_1.ERRORS.NA;
|
|
800
903
|
const result = [];
|
|
801
|
-
for (let i = 0; i < flat.length; i +=
|
|
802
|
-
const row = flat.slice(i, i +
|
|
803
|
-
while (row.length <
|
|
904
|
+
for (let i = 0; i < flat.length; i += wc) {
|
|
905
|
+
const row = flat.slice(i, i + wc);
|
|
906
|
+
while (row.length < wc) {
|
|
804
907
|
row.push(pad);
|
|
805
908
|
}
|
|
806
909
|
result.push(row);
|
|
@@ -818,20 +921,21 @@ function fnWRAPCOLS(args) {
|
|
|
818
921
|
flat.push((0, _shared_1.getCell)(arr, r, c));
|
|
819
922
|
}
|
|
820
923
|
}
|
|
821
|
-
const wcV = (0, values_1.toNumberRV)(args[1]);
|
|
924
|
+
const wcV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
|
|
822
925
|
if ((0, values_1.isError)(wcV)) {
|
|
823
926
|
return wcV;
|
|
824
927
|
}
|
|
825
|
-
|
|
928
|
+
const wc = Math.trunc(wcV.value);
|
|
929
|
+
if (wc < 1) {
|
|
826
930
|
return values_1.ERRORS.VALUE;
|
|
827
931
|
}
|
|
828
932
|
const pad = args.length > 2 ? (0, values_1.topLeft)(args[2]) : values_1.ERRORS.NA;
|
|
829
|
-
const numCols = Math.ceil(flat.length /
|
|
933
|
+
const numCols = Math.ceil(flat.length / wc);
|
|
830
934
|
const result = [];
|
|
831
|
-
for (let r = 0; r <
|
|
935
|
+
for (let r = 0; r < wc; r++) {
|
|
832
936
|
const row = [];
|
|
833
937
|
for (let c = 0; c < numCols; c++) {
|
|
834
|
-
const idx = c *
|
|
938
|
+
const idx = c * wc + r;
|
|
835
939
|
row.push(idx < flat.length ? flat[idx] : pad);
|
|
836
940
|
}
|
|
837
941
|
result.push(row);
|
|
@@ -843,11 +947,11 @@ function fnEXPAND(args) {
|
|
|
843
947
|
if (!d) {
|
|
844
948
|
return values_1.ERRORS.VALUE;
|
|
845
949
|
}
|
|
846
|
-
const rowsV = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(d.height);
|
|
950
|
+
const rowsV = args.length > 1 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(d.height);
|
|
847
951
|
if ((0, values_1.isError)(rowsV)) {
|
|
848
952
|
return rowsV;
|
|
849
953
|
}
|
|
850
|
-
const colsV = args.length > 2 ? (0, values_1.toNumberRV)(args[2]) : (0, values_1.rvNumber)(d.width);
|
|
954
|
+
const colsV = args.length > 2 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[2])) : (0, values_1.rvNumber)(d.width);
|
|
851
955
|
if ((0, values_1.isError)(colsV)) {
|
|
852
956
|
return colsV;
|
|
853
957
|
}
|