@sheetxl/primitives 0.7.28-beta.4 → 0.8.0-beta.2
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/browser/cjs/index.cjs +1 -1
- package/browser/esm/index.mjs +95 -53
- package/node/esm/index.mjs +109 -67
- package/package.json +1 -1
- package/types/src/ErrorPolicy.d.ts +48 -57
- package/types/src/Flatten.d.ts +6 -3
- package/types/src/FormulaContext.d.ts +36 -5
- package/types/src/IFormulaContext.d.ts +101 -7
- package/types/src/IFunction.d.ts +339 -29
- package/types/src/IFunctionArguments.d.ts +192 -0
- package/types/src/IRange.d.ts +181 -40
- package/types/src/IRangeStats.d.ts +32 -2
- package/types/src/IRuntime.d.ts +24 -1
- package/types/src/Lazy.d.ts +76 -0
- package/types/src/NoFilter.d.ts +34 -0
- package/types/src/NoLift.d.ts +31 -0
- package/types/src/Repeating.d.ts +24 -4
- package/types/src/ReportType.d.ts +42 -0
- package/types/src/Scalar.d.ts +1 -1
- package/types/src/ValueKind.d.ts +43 -0
- package/types/src/Volatile.d.ts +12 -0
- package/types/src/WildCard.d.ts +13 -9
- package/types/src/index.d.ts +7 -0
|
@@ -3,6 +3,7 @@ import { FormulaError } from './FormulaError';
|
|
|
3
3
|
import { IRange } from './IRange';
|
|
4
4
|
import { IReferenceRange } from './IReferenceRange';
|
|
5
5
|
import { IFunction } from './IFunction';
|
|
6
|
+
import { IFunctionArguments } from './IFunctionArguments';
|
|
6
7
|
import { IFormulaContext } from './IFormulaContext';
|
|
7
8
|
import { IRuntime } from './IRuntime';
|
|
8
9
|
import { LocaleProfile } from './LocaleProfile';
|
|
@@ -20,6 +21,8 @@ import { LocaleProfile } from './LocaleProfile';
|
|
|
20
21
|
export declare class StubbedFormulaContext implements IFormulaContext {
|
|
21
22
|
/** @inheritdoc IFormulaContext.createRange */
|
|
22
23
|
createRange<TS extends Scalar = Scalar>(rows?: number, columns?: number, values?: Scalar | Scalar[][] | ((value: TS, coords: IRange.CellCoords, range: IRange<TS>) => TS)): IRange;
|
|
24
|
+
/** @inheritdoc IFormulaContext.flattenAreas */
|
|
25
|
+
flattenAreas(value: IRange | IRange[]): IRange;
|
|
23
26
|
/** @inheritdoc IFormulaContext.getReference */
|
|
24
27
|
getReference(coords?: Readonly<IRange.Coords>, r1c1?: boolean): IReferenceRange;
|
|
25
28
|
/** @inheritdoc IFormulaContext.getResizedReference */
|
|
@@ -36,6 +39,8 @@ export declare class StubbedFormulaContext implements IFormulaContext {
|
|
|
36
39
|
getSerialDate(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millis?: number): number;
|
|
37
40
|
/** @inheritdoc IFormulaContext.getNow */
|
|
38
41
|
getNow(): number;
|
|
42
|
+
/** @inheritdoc IFormulaContext.getRandom */
|
|
43
|
+
getRandom(): number;
|
|
39
44
|
/** @inheritdoc IFormulaContext.getValueAt */
|
|
40
45
|
getValueAt(row: number, column: number, sheetName?: string, options?: IRange.ValueOptions): Scalar | null;
|
|
41
46
|
/** @inheritdoc IFormulaContext.getEntireCoords */
|
|
@@ -46,6 +51,8 @@ export declare class StubbedFormulaContext implements IFormulaContext {
|
|
|
46
51
|
getRow(): number;
|
|
47
52
|
/** @inheritdoc IFormulaContext.getColumn */
|
|
48
53
|
getColumn(): number;
|
|
54
|
+
/** @inheritdoc IFormulaContext.isImplicitIntersect */
|
|
55
|
+
isImplicitIntersect(): boolean;
|
|
49
56
|
/** @inheritdoc IFormulaContext.getFormulaAt */
|
|
50
57
|
getFormulaAt(row: number, column: number, sheetName?: string): string | null;
|
|
51
58
|
/** @inheritdoc IFormulaContext.getSpillAt */
|
|
@@ -82,7 +89,7 @@ export declare class StubbedFormulaContext implements IFormulaContext {
|
|
|
82
89
|
* plausibly and wrongly, where throwing names the actual mistake (evaluating criteria outside an
|
|
83
90
|
* installed scope).
|
|
84
91
|
*/
|
|
85
|
-
createCriteria(criteria: Scalar): IFormulaContext.CriteriaEvaluator;
|
|
92
|
+
createCriteria(criteria: Scalar, options?: IFormulaContext.CriteriaOptions): IFormulaContext.CriteriaEvaluator;
|
|
86
93
|
/**
|
|
87
94
|
* Parses the canonical English boolean and error literals.
|
|
88
95
|
* See {@link IFormulaContext.parseAsLiteral}.
|
|
@@ -127,6 +134,8 @@ export declare class StubbedFormulaContext implements IFormulaContext {
|
|
|
127
134
|
compare(a: Scalar, b: Scalar, options?: Intl.CollatorOptions): number;
|
|
128
135
|
/** @inheritdoc IFormulaContext.getRuntime */
|
|
129
136
|
getRuntime(): IRuntime;
|
|
137
|
+
/** @inheritdoc IFormulaContext.getArgs */
|
|
138
|
+
getArgs(): IFunctionArguments;
|
|
130
139
|
}
|
|
131
140
|
/**
|
|
132
141
|
* The single, shared {@link IFormulaContext} that formula implementations use (via
|
|
@@ -144,6 +153,18 @@ export declare class ScopedFormulaContext implements IFormulaContext {
|
|
|
144
153
|
_setScope(scope: Partial<IFormulaContext> | null): void;
|
|
145
154
|
/** @hidden */
|
|
146
155
|
_getScope(): Partial<IFormulaContext>;
|
|
156
|
+
/**
|
|
157
|
+
* @hidden Installed ONCE by the runtime marshaller; answers {@link getArgs} for whichever call
|
|
158
|
+
* is currently dispatching, or `null` when none is.
|
|
159
|
+
*
|
|
160
|
+
* @remarks
|
|
161
|
+
* A provider rather than a stack because the marshaller already pools one view per dispatch
|
|
162
|
+
* DEPTH and knows the current depth. Reading a function pointer costs nothing for the ~99% of
|
|
163
|
+
* calls whose body never asks.
|
|
164
|
+
*/
|
|
165
|
+
protected _argsFn: (() => IFunctionArguments | null) | null;
|
|
166
|
+
/** @hidden */
|
|
167
|
+
_setArgsProvider(provider: (() => IFunctionArguments | null) | null): void;
|
|
147
168
|
/** @inheritdoc IFormulaContext.getNumberFormat */
|
|
148
169
|
getNumberFormat(formatText: string, value: Scalar): string | null;
|
|
149
170
|
/** @inheritdoc IFormulaContext.getEntireCoords */
|
|
@@ -156,7 +177,7 @@ export declare class ScopedFormulaContext implements IFormulaContext {
|
|
|
156
177
|
parseAsNumber(textOrNumber: Scalar, options?: IFormulaContext.ParseNumberOptions): number;
|
|
157
178
|
parseAsNumber(textOrNumber: Scalar | undefined, options?: IFormulaContext.ParseNumberOptions): number | undefined;
|
|
158
179
|
/** @inheritdoc IFormulaContext.createCriteria */
|
|
159
|
-
createCriteria(criteria: Scalar): IFormulaContext.CriteriaEvaluator;
|
|
180
|
+
createCriteria(criteria: Scalar, options?: IFormulaContext.CriteriaOptions): IFormulaContext.CriteriaEvaluator;
|
|
160
181
|
/** @inheritdoc IFormulaContext.parseAsLiteral */
|
|
161
182
|
parseAsLiteral(text: string): boolean | FormulaError.Known | undefined;
|
|
162
183
|
/** @inheritdoc IFormulaContext.toText */
|
|
@@ -173,12 +194,18 @@ export declare class ScopedFormulaContext implements IFormulaContext {
|
|
|
173
194
|
getSerialDate(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millis?: number): number;
|
|
174
195
|
/** @inheritdoc IFormulaContext.getNow */
|
|
175
196
|
getNow(): number;
|
|
197
|
+
/** @inheritdoc IFormulaContext.getRandom */
|
|
198
|
+
getRandom(): number;
|
|
176
199
|
/** @inheritdoc IFormulaContext.createRange */
|
|
177
200
|
createRange<TS extends Scalar = Scalar>(rows?: number, columns?: number, values?: Scalar | Scalar[][] | ((value: TS, coords: IRange.CellCoords, range: IRange<TS>) => TS)): IRange;
|
|
201
|
+
/** @inheritdoc IFormulaContext.flattenAreas */
|
|
202
|
+
flattenAreas(value: IRange | IRange[]): IRange;
|
|
178
203
|
/** @inheritdoc IFormulaContext.getRow */
|
|
179
204
|
getRow(): number;
|
|
180
205
|
/** @inheritdoc IFormulaContext.getColumn */
|
|
181
206
|
getColumn(): number;
|
|
207
|
+
/** @inheritdoc IFormulaContext.isImplicitIntersect */
|
|
208
|
+
isImplicitIntersect(): boolean;
|
|
182
209
|
/** @inheritdoc IFormulaContext.getReference */
|
|
183
210
|
getReference(coords?: Readonly<IRange.Coords>, r1c1?: boolean): IReferenceRange;
|
|
184
211
|
/** @inheritdoc IFormulaContext.getResizedReference */
|
|
@@ -209,19 +236,23 @@ export declare class ScopedFormulaContext implements IFormulaContext {
|
|
|
209
236
|
compare(a: Scalar, b: Scalar, options?: Intl.CollatorOptions): number;
|
|
210
237
|
/** @inheritdoc IFormulaContext.getRuntime */
|
|
211
238
|
getRuntime(): IRuntime;
|
|
239
|
+
/** @inheritdoc IFormulaContext.getArgs */
|
|
240
|
+
getArgs(): IFunctionArguments;
|
|
212
241
|
get [Symbol.toStringTag](): string;
|
|
213
242
|
toString(): string;
|
|
214
243
|
}
|
|
215
244
|
/**
|
|
216
245
|
* A plain en-US profile, for stubs and for environments without `Intl`.
|
|
217
246
|
*
|
|
218
|
-
* @
|
|
219
|
-
*
|
|
220
|
-
* `makeLocaleProfile` in `@sheetxl/sdk`.
|
|
247
|
+
* @internal
|
|
248
|
+
* @hidden
|
|
221
249
|
*/
|
|
222
250
|
export declare const DEFAULT_LOCALE_PROFILE: LocaleProfile;
|
|
223
251
|
/**
|
|
224
252
|
* The shared {@link IFormulaContext} for formula implementations. See {@link ScopedFormulaContext}.
|
|
253
|
+
*
|
|
254
|
+
* @internal
|
|
255
|
+
* @hidden
|
|
225
256
|
*/
|
|
226
257
|
export declare const FormulaContext: IFormulaContext;
|
|
227
258
|
//# sourceMappingURL=FormulaContext.d.ts.map
|
|
@@ -3,6 +3,7 @@ import { FormulaError } from './FormulaError';
|
|
|
3
3
|
import { IRange } from './IRange';
|
|
4
4
|
import { IReferenceRange } from './IReferenceRange';
|
|
5
5
|
import { IFunction } from './IFunction';
|
|
6
|
+
import { IFunctionArguments } from './IFunctionArguments';
|
|
6
7
|
import { IRuntime } from './IRuntime';
|
|
7
8
|
/**
|
|
8
9
|
* Everything a formula function is allowed to know about the world outside its arguments.
|
|
@@ -27,9 +28,10 @@ import { IRuntime } from './IRuntime';
|
|
|
27
28
|
*
|
|
28
29
|
* | Category | Key methods |
|
|
29
30
|
* |---|---|
|
|
30
|
-
* | Evaluation lifecycle | `markVolatile`, `getRow`, `getColumn`, `getEntireCoords` |
|
|
31
|
+
* | Evaluation lifecycle | `markVolatile`, `getRow`, `getColumn`, `getEntireCoords`, `getRandom` |
|
|
32
|
+
* | Argument reflection | `getArgs` |
|
|
31
33
|
* | Output hints | `formatResults` |
|
|
32
|
-
* | Range construction | `createRange`, `filterHidden` |
|
|
34
|
+
* | Range construction | `createRange`, `flattenAreas`, `filterHidden` |
|
|
33
35
|
* | Dynamic references | `getReference`, `getValueAt`, `getFormulaAt`, `getSpillAt` |
|
|
34
36
|
* | Function lookup | `getFunction` |
|
|
35
37
|
* | Dates | `getNow`, `toSerialDate`, `fromSerialDate`, `getDateParts`, `getSerialDate`, `parseAsDate`, `parseAsSerialDate`, `isValidDate` |
|
|
@@ -52,6 +54,25 @@ export interface IFormulaContext {
|
|
|
52
54
|
* invoked per cell. Default is `null` (an empty range).
|
|
53
55
|
*/
|
|
54
56
|
createRange<TS extends Scalar = Scalar>(rows?: number, columns?: number, values?: Scalar | Scalar[][] | ((value: TS, coords: IRange.CellCoords, range: IRange<TS>) => TS)): IRange;
|
|
57
|
+
/**
|
|
58
|
+
* One range over every cell of a `ReportType` slot's argument — the AREAS of a reference union
|
|
59
|
+
* folded into a single column, or the range returned unchanged.
|
|
60
|
+
*
|
|
61
|
+
* @param value The argument as it arrived: a range, or one range per area.
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* A union `(A1:A5,B1:B2)` reaches a {@link IFunction.ParameterTypeJSON.reportType} slot as one
|
|
65
|
+
* `IRange` per area. Functions that answer over it do so because they walk MEMBERS and a union
|
|
66
|
+
* simply has more of them — `LARGE((DA1:DA5,DK1:DK2),2)` is the second largest of all seven
|
|
67
|
+
* cells. This is that walk, and it is a helper rather than a marshalling step on purpose: Excel
|
|
68
|
+
* flattens in exactly the same place, a shared reducer its bodies opt into, which is why the
|
|
69
|
+
* same union is flattened by `LARGE`, refused by `SUMPRODUCT` and answered `#REF!` by `ROWS`.
|
|
70
|
+
*
|
|
71
|
+
* The result is a single column in area order, row-major within each area. SHAPE IS NOT
|
|
72
|
+
* PRESERVED — a union has none. A body that needs an extent must ask
|
|
73
|
+
* {@link IFunctionArguments.getAreaCountAt} and answer for itself.
|
|
74
|
+
*/
|
|
75
|
+
flattenAreas(value: IRange | IRange[]): IRange;
|
|
55
76
|
/**
|
|
56
77
|
* Returns coordinates as an address string.
|
|
57
78
|
*
|
|
@@ -92,6 +113,20 @@ export interface IFormulaContext {
|
|
|
92
113
|
* Returns the 0-based column of the cell being evaluated.
|
|
93
114
|
*/
|
|
94
115
|
getColumn(): number;
|
|
116
|
+
/**
|
|
117
|
+
* Whether the call being evaluated is in Excel's VALUE mode, where a multi-cell reference at a
|
|
118
|
+
* slot that reads ONE value is implicitly intersected with the formula's cell (the `@` rule);
|
|
119
|
+
* `false` is ARRAY mode, where such a slot reads the reference's first cell.
|
|
120
|
+
*
|
|
121
|
+
* @remarks
|
|
122
|
+
* Only a body that accepts a whole reference at a single-value slot and reads it itself asks
|
|
123
|
+
* (`LINEST`'s `const`). The engine decides the mode from the formula around the call — a
|
|
124
|
+
* scalar-valued root, an aggregator or a lookup above it are value mode; a spilling root, an
|
|
125
|
+
* operator or lifting slot over an array-valued operand, a `LAMBDA` body and an array-entered
|
|
126
|
+
* block are array mode — and the mode is inherited through every call that does not set it.
|
|
127
|
+
* Outside a calculation this is `false`.
|
|
128
|
+
*/
|
|
129
|
+
isImplicitIntersect(): boolean;
|
|
95
130
|
/**
|
|
96
131
|
* Resolves a range reference at runtime, returning an {@link IReferenceRange}.
|
|
97
132
|
*
|
|
@@ -275,6 +310,7 @@ export interface IFormulaContext {
|
|
|
275
310
|
*
|
|
276
311
|
* @param criteria The criteria, exactly as the user wrote it — a comparison (`">10"`, `"<>x"`),
|
|
277
312
|
* a wildcard pattern (`"a*"`), or a literal of any type.
|
|
313
|
+
* @param options How the criteria is matched. See {@link IFormulaContext.CriteriaOptions}.
|
|
278
314
|
* @returns A predicate to test cell values with. Call it once per cell.
|
|
279
315
|
*
|
|
280
316
|
* @remarks
|
|
@@ -296,7 +332,7 @@ export interface IFormulaContext {
|
|
|
296
332
|
* const count = range.reduce((total, value) => matches(value) ? total + 1 : total, 0);
|
|
297
333
|
* ```
|
|
298
334
|
*/
|
|
299
|
-
createCriteria(criteria: Scalar): IFormulaContext.CriteriaEvaluator;
|
|
335
|
+
createCriteria(criteria: Scalar, options?: IFormulaContext.CriteriaOptions): IFormulaContext.CriteriaEvaluator;
|
|
300
336
|
/**
|
|
301
337
|
* Reads a typed literal in the workbook's language — the parse side of {@link toText}.
|
|
302
338
|
*
|
|
@@ -384,6 +420,30 @@ export interface IFormulaContext {
|
|
|
384
420
|
* ```
|
|
385
421
|
*/
|
|
386
422
|
getNow(): number;
|
|
423
|
+
/**
|
|
424
|
+
* Returns a random number in `[0, 1)`, like `Math.random()`.
|
|
425
|
+
*
|
|
426
|
+
* @remarks
|
|
427
|
+
* Always draw through this, never `Math.random()`. The source is the runtime's, so a test or a
|
|
428
|
+
* replay can seed it, and the engine sees the draw: a draw is a PER-CELL read — two cells calling
|
|
429
|
+
* the same function in one pass differ — where `getNow` is one value for the whole pass, and the
|
|
430
|
+
* engine only shares an evaluation across the cells of a block when nothing per-cell was read.
|
|
431
|
+
* Pair it with `Volatile<T>` so the function draws again on the next pass.
|
|
432
|
+
*
|
|
433
|
+
* Under a seeded runtime ({@link IRuntime.getRandomSeed}) each draw is keyed by the cell, the
|
|
434
|
+
* pass and which draw it is within that cell, so a function that draws more than once gets
|
|
435
|
+
* distinct values and a cell gets the same ones however the pass was ordered. Take the draws
|
|
436
|
+
* where they are used rather than hoisting them, and the values follow the cells rather than
|
|
437
|
+
* the code path.
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* ```typescript
|
|
441
|
+
* export function RAND(): Volatile<number> {
|
|
442
|
+
* return FormulaContext.getRandom();
|
|
443
|
+
* }
|
|
444
|
+
* ```
|
|
445
|
+
*/
|
|
446
|
+
getRandom(): number;
|
|
387
447
|
/**
|
|
388
448
|
* Returns `true` if the value is a usable date — either a `Date` or a number in the
|
|
389
449
|
* workbook's serial date range.
|
|
@@ -445,14 +505,12 @@ export interface IFormulaContext {
|
|
|
445
505
|
* Fields may fall outside their normal range and carry, which is what makes `DATE` and
|
|
446
506
|
* `TIME` arithmetic work: month 13 is January of the next year, hour 50 is two days plus
|
|
447
507
|
* two hours, and `getSerialDate(1900, 1, 0)` is serial 0. The `day` carries in SERIAL
|
|
448
|
-
* space, so it runs through the phantom `1900-02-29
|
|
449
|
-
* `probe-date-1900-day-overflow.ps1`.
|
|
508
|
+
* space, so it runs through the phantom `1900-02-29`.
|
|
450
509
|
*
|
|
451
510
|
* **This validates nothing, and that is deliberate — a caller MUST choose its own
|
|
452
511
|
* policy.** No range check, no clamping, no bounds on any field, and no `DATE`-style
|
|
453
512
|
* `0..1899 -> +1900` year offset. Those belong to `DATE`'s ARGUMENTS, not to the
|
|
454
|
-
* calendar, and
|
|
455
|
-
* (`probe-date-arg-layer.ps1`, 2026-08-20):
|
|
513
|
+
* calendar, and three things prove it:
|
|
456
514
|
*
|
|
457
515
|
* * **The day policy is the caller's.** `DATE` and `DATEDIF`'s `md`/`yd` re-anchoring
|
|
458
516
|
* want the raw carry above — `DATEDIF("2020-01-31","2020-03-01","md")` is `-1`
|
|
@@ -482,6 +540,22 @@ export interface IFormulaContext {
|
|
|
482
540
|
* Mostly for diagnostics; the built-in `INFO` function is built on it.
|
|
483
541
|
*/
|
|
484
542
|
getRuntime(): IRuntime;
|
|
543
|
+
/**
|
|
544
|
+
* The current call's arguments — how many the caller supplied, in which positions, of what kind,
|
|
545
|
+
* and what each value was BEFORE coercion.
|
|
546
|
+
*
|
|
547
|
+
* @remarks
|
|
548
|
+
* Argument REFLECTION, for the one thing a declaration cannot say: what happened at *this* call.
|
|
549
|
+
* It exists to serve Excel's declared `any`, which means "no contract, the body decides" — every
|
|
550
|
+
* other Excel type maps onto a type we already have and the marshaller handles it.
|
|
551
|
+
*
|
|
552
|
+
* The returned view is valid ONLY while the body that asked for it is running. Views are pooled
|
|
553
|
+
* by dispatch depth, so retaining one across an `await`, a callback, or a nested evaluation hands
|
|
554
|
+
* you another call's arguments.
|
|
555
|
+
*
|
|
556
|
+
* @throws If called outside a function dispatch — there are no arguments to reflect on.
|
|
557
|
+
*/
|
|
558
|
+
getArgs(): IFunctionArguments;
|
|
485
559
|
}
|
|
486
560
|
/**
|
|
487
561
|
* {@inheritDoc IFormulaContext}
|
|
@@ -505,6 +579,26 @@ export declare namespace IFormulaContext {
|
|
|
505
579
|
* there.
|
|
506
580
|
*/
|
|
507
581
|
type CriteriaEvaluator = (value: Scalar) => boolean;
|
|
582
|
+
/**
|
|
583
|
+
* How a criteria is matched — see {@link IFormulaContext.createCriteria}.
|
|
584
|
+
*/
|
|
585
|
+
interface CriteriaOptions {
|
|
586
|
+
/**
|
|
587
|
+
* Where a TEXT criteria has to line up with the cell: `'whole'` (the default) for the whole
|
|
588
|
+
* cell, `'start'` for a prefix.
|
|
589
|
+
*
|
|
590
|
+
* @remarks
|
|
591
|
+
* The `D` functions' criteria table is the prefix form and the `*IF` family is not: the
|
|
592
|
+
* criterion `appl` takes the row whose value is `Apple` at `DSUM` and no row at all at
|
|
593
|
+
* `COUNTIF`, and the empty criterion — a prefix of everything — takes every TEXT cell at
|
|
594
|
+
* `DSUM` where `COUNTIF` takes only a cell that IS an empty string.
|
|
595
|
+
*
|
|
596
|
+
* It applies to a criteria that stays TEXT and to nothing else. An OPERATOR turns it off
|
|
597
|
+
* (`=appl` selects no row), and so does a criteria that reads as a number, a boolean or an
|
|
598
|
+
* error — `1` does not reach a cell holding `12`.
|
|
599
|
+
*/
|
|
600
|
+
anchor?: 'whole' | 'start';
|
|
601
|
+
}
|
|
508
602
|
/**
|
|
509
603
|
* A serial date split into fields — see {@link IFormulaContext.getDateParts}.
|
|
510
604
|
*
|