@sheetxl/primitives 0.7.28-beta.4 → 0.8.0-beta.10

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.
@@ -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 */
@@ -59,7 +66,7 @@ export declare class StubbedFormulaContext implements IFormulaContext {
59
66
  /** @inheritdoc IFormulaContext.formatResults */
60
67
  formatResults(numFmt: string): void;
61
68
  /** @inheritdoc IFormulaContext.filterHidden */
62
- filterHidden(range: IRange, axes?: IRange.AxisSelection): IRange;
69
+ filterHidden(range: IRange, options?: IFormulaContext.FilterHiddenOptions): IRange;
63
70
  /** @inheritdoc IFormulaContext.filterTotals */
64
71
  filterTotals(range: IRange): IRange;
65
72
  /** @inheritdoc IFormulaContext.getFunction */
@@ -82,7 +89,14 @@ 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;
93
+ /**
94
+ * Unimplemented. See {@link IFormulaContext.createGrouping}.
95
+ *
96
+ * @remarks
97
+ * Grouping needs Excel's key equality, which this stub does not have.
98
+ */
99
+ createGrouping(keys: IRange, options?: IFormulaContext.GroupingOptions): IFormulaContext.Grouping;
86
100
  /**
87
101
  * Parses the canonical English boolean and error literals.
88
102
  * See {@link IFormulaContext.parseAsLiteral}.
@@ -127,6 +141,8 @@ export declare class StubbedFormulaContext implements IFormulaContext {
127
141
  compare(a: Scalar, b: Scalar, options?: Intl.CollatorOptions): number;
128
142
  /** @inheritdoc IFormulaContext.getRuntime */
129
143
  getRuntime(): IRuntime;
144
+ /** @inheritdoc IFormulaContext.getArgs */
145
+ getArgs(): IFunctionArguments;
130
146
  }
131
147
  /**
132
148
  * The single, shared {@link IFormulaContext} that formula implementations use (via
@@ -144,6 +160,18 @@ export declare class ScopedFormulaContext implements IFormulaContext {
144
160
  _setScope(scope: Partial<IFormulaContext> | null): void;
145
161
  /** @hidden */
146
162
  _getScope(): Partial<IFormulaContext>;
163
+ /**
164
+ * @hidden Installed ONCE by the runtime marshaller; answers {@link getArgs} for whichever call
165
+ * is currently dispatching, or `null` when none is.
166
+ *
167
+ * @remarks
168
+ * A provider rather than a stack because the marshaller already pools one view per dispatch
169
+ * DEPTH and knows the current depth. Reading a function pointer costs nothing for the ~99% of
170
+ * calls whose body never asks.
171
+ */
172
+ protected _argsFn: (() => IFunctionArguments | null) | null;
173
+ /** @hidden */
174
+ _setArgsProvider(provider: (() => IFunctionArguments | null) | null): void;
147
175
  /** @inheritdoc IFormulaContext.getNumberFormat */
148
176
  getNumberFormat(formatText: string, value: Scalar): string | null;
149
177
  /** @inheritdoc IFormulaContext.getEntireCoords */
@@ -156,7 +184,9 @@ export declare class ScopedFormulaContext implements IFormulaContext {
156
184
  parseAsNumber(textOrNumber: Scalar, options?: IFormulaContext.ParseNumberOptions): number;
157
185
  parseAsNumber(textOrNumber: Scalar | undefined, options?: IFormulaContext.ParseNumberOptions): number | undefined;
158
186
  /** @inheritdoc IFormulaContext.createCriteria */
159
- createCriteria(criteria: Scalar): IFormulaContext.CriteriaEvaluator;
187
+ createCriteria(criteria: Scalar, options?: IFormulaContext.CriteriaOptions): IFormulaContext.CriteriaEvaluator;
188
+ /** @inheritdoc IFormulaContext.createGrouping */
189
+ createGrouping(keys: IRange, options?: IFormulaContext.GroupingOptions): IFormulaContext.Grouping;
160
190
  /** @inheritdoc IFormulaContext.parseAsLiteral */
161
191
  parseAsLiteral(text: string): boolean | FormulaError.Known | undefined;
162
192
  /** @inheritdoc IFormulaContext.toText */
@@ -173,12 +203,18 @@ export declare class ScopedFormulaContext implements IFormulaContext {
173
203
  getSerialDate(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millis?: number): number;
174
204
  /** @inheritdoc IFormulaContext.getNow */
175
205
  getNow(): number;
206
+ /** @inheritdoc IFormulaContext.getRandom */
207
+ getRandom(): number;
176
208
  /** @inheritdoc IFormulaContext.createRange */
177
209
  createRange<TS extends Scalar = Scalar>(rows?: number, columns?: number, values?: Scalar | Scalar[][] | ((value: TS, coords: IRange.CellCoords, range: IRange<TS>) => TS)): IRange;
210
+ /** @inheritdoc IFormulaContext.flattenAreas */
211
+ flattenAreas(value: IRange | IRange[]): IRange;
178
212
  /** @inheritdoc IFormulaContext.getRow */
179
213
  getRow(): number;
180
214
  /** @inheritdoc IFormulaContext.getColumn */
181
215
  getColumn(): number;
216
+ /** @inheritdoc IFormulaContext.isImplicitIntersect */
217
+ isImplicitIntersect(): boolean;
182
218
  /** @inheritdoc IFormulaContext.getReference */
183
219
  getReference(coords?: Readonly<IRange.Coords>, r1c1?: boolean): IReferenceRange;
184
220
  /** @inheritdoc IFormulaContext.getResizedReference */
@@ -198,7 +234,7 @@ export declare class ScopedFormulaContext implements IFormulaContext {
198
234
  /** @inheritdoc IFormulaContext.formatResults */
199
235
  formatResults(numFmt: string): void;
200
236
  /** @inheritdoc IFormulaContext.filterHidden */
201
- filterHidden(range: IRange, axes?: IRange.AxisSelection): IRange;
237
+ filterHidden(range: IRange, options?: IFormulaContext.FilterHiddenOptions): IRange;
202
238
  /** @inheritdoc IFormulaContext.filterTotals */
203
239
  filterTotals(range: IRange): IRange;
204
240
  /** @inheritdoc IFormulaContext.getFunction */
@@ -209,19 +245,23 @@ export declare class ScopedFormulaContext implements IFormulaContext {
209
245
  compare(a: Scalar, b: Scalar, options?: Intl.CollatorOptions): number;
210
246
  /** @inheritdoc IFormulaContext.getRuntime */
211
247
  getRuntime(): IRuntime;
248
+ /** @inheritdoc IFormulaContext.getArgs */
249
+ getArgs(): IFunctionArguments;
212
250
  get [Symbol.toStringTag](): string;
213
251
  toString(): string;
214
252
  }
215
253
  /**
216
254
  * A plain en-US profile, for stubs and for environments without `Intl`.
217
255
  *
218
- * @remarks
219
- * Deliberately static data -- no probing. Real profiles come from
220
- * `makeLocaleProfile` in `@sheetxl/sdk`.
256
+ * @internal
257
+ * @hidden
221
258
  */
222
259
  export declare const DEFAULT_LOCALE_PROFILE: LocaleProfile;
223
260
  /**
224
261
  * The shared {@link IFormulaContext} for formula implementations. See {@link ScopedFormulaContext}.
262
+ *
263
+ * @internal
264
+ * @hidden
225
265
  */
226
266
  export declare const FormulaContext: IFormulaContext;
227
267
  //# 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,14 +28,16 @@ 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` |
36
38
  * | Coercion | `parseAsNumber`, `parseAsLiteral`, `toText`, `compare` |
37
39
  * | Criteria | `createCriteria` |
40
+ * | Grouping | `createGrouping` |
38
41
  * | Sheet introspection | `getSheetCount`, `getSheetIndex`, `getAddress`, `getNumberFormat` |
39
42
  *
40
43
  * ### Implementors
@@ -52,6 +55,25 @@ export interface IFormulaContext {
52
55
  * invoked per cell. Default is `null` (an empty range).
53
56
  */
54
57
  createRange<TS extends Scalar = Scalar>(rows?: number, columns?: number, values?: Scalar | Scalar[][] | ((value: TS, coords: IRange.CellCoords, range: IRange<TS>) => TS)): IRange;
58
+ /**
59
+ * One range over every cell of a `ReportType` slot's argument — the AREAS of a reference union
60
+ * folded into a single column, or the range returned unchanged.
61
+ *
62
+ * @param value The argument as it arrived: a range, or one range per area.
63
+ *
64
+ * @remarks
65
+ * A union `(A1:A5,B1:B2)` reaches a {@link IFunction.ParameterTypeJSON.reportType} slot as one
66
+ * `IRange` per area. Functions that answer over it do so because they walk MEMBERS and a union
67
+ * simply has more of them — `LARGE((DA1:DA5,DK1:DK2),2)` is the second largest of all seven
68
+ * cells. This is that walk, and it is a helper rather than a marshalling step on purpose: Excel
69
+ * flattens in exactly the same place, a shared reducer its bodies opt into, which is why the
70
+ * same union is flattened by `LARGE`, refused by `SUMPRODUCT` and answered `#REF!` by `ROWS`.
71
+ *
72
+ * The result is a single column in area order, row-major within each area. SHAPE IS NOT
73
+ * PRESERVED — a union has none. A body that needs an extent must ask
74
+ * {@link IFunctionArguments.getAreaCountAt} and answer for itself.
75
+ */
76
+ flattenAreas(value: IRange | IRange[]): IRange;
55
77
  /**
56
78
  * Returns coordinates as an address string.
57
79
  *
@@ -92,6 +114,20 @@ export interface IFormulaContext {
92
114
  * Returns the 0-based column of the cell being evaluated.
93
115
  */
94
116
  getColumn(): number;
117
+ /**
118
+ * Whether the call being evaluated is in Excel's VALUE mode, where a multi-cell reference at a
119
+ * slot that reads ONE value is implicitly intersected with the formula's cell (the `@` rule);
120
+ * `false` is ARRAY mode, where such a slot reads the reference's first cell.
121
+ *
122
+ * @remarks
123
+ * Only a body that accepts a whole reference at a single-value slot and reads it itself asks
124
+ * (`LINEST`'s `const`). The engine decides the mode from the formula around the call — a
125
+ * scalar-valued root, an aggregator or a lookup above it are value mode; a spilling root, an
126
+ * operator or lifting slot over an array-valued operand, a `LAMBDA` body and an array-entered
127
+ * block are array mode — and the mode is inherited through every call that does not set it.
128
+ * Outside a calculation this is `false`.
129
+ */
130
+ isImplicitIntersect(): boolean;
95
131
  /**
96
132
  * Resolves a range reference at runtime, returning an {@link IReferenceRange}.
97
133
  *
@@ -184,16 +220,30 @@ export interface IFormulaContext {
184
220
  */
185
221
  getSheetIndex(sheet?: string | IReferenceRange): number;
186
222
  /**
187
- * Returns a copy of a range with hidden rows or columns removed.
223
+ * Returns a range as it reads without its hidden rows or columns.
188
224
  *
189
225
  * @param range The range to filter.
190
- * @param axes Which axis to filter on. Default is `IRange.AxisSelection.Row`.
191
- * @returns A new range without the hidden rows or columns.
226
+ * @param options See {@link IFormulaContext.FilterHiddenOptions}.
227
+ * @returns `range` itself when nothing in it is hidden; otherwise the same range reading with
228
+ * the hidden rows or columns skipped ({@link IRange.IteratorOptions.processRowSkip}).
192
229
  *
193
230
  * @remarks
194
231
  * Use this for functions that ignore hidden data, such as `SUBTOTAL`.
232
+ *
233
+ * Nothing is copied. The shape of `range` is kept, and a reference stays a reference: a hidden
234
+ * cell is not visited and reads as empty, so every position still means the cell it meant, and
235
+ * an aggregate that ignores blanks ignores it. A computed array has no rows or columns to hide
236
+ * and is returned as it is.
237
+ *
238
+ * A hidden row is a hidden row, whoever hid it: a filter and the user leave the same mark, and
239
+ * nothing here tells them apart. What a filter adds is a state of the range's SHEET, which
240
+ * {@link IFormulaContext.FilterHiddenOptions.onlyWhileFiltered} reads.
241
+ *
242
+ * A formula that calls `SUBTOTAL` or `AGGREGATE` is recalculated when a row or column is hidden
243
+ * or shown, and when a filter is set or cleared. One that reaches this only through a custom
244
+ * function is not: it reads the state when it is next calculated.
195
245
  */
196
- filterHidden(range: IRange, axes?: IRange.AxisSelection): IRange;
246
+ filterHidden(range: IRange, options?: IFormulaContext.FilterHiddenOptions): IRange;
197
247
  /**
198
248
  * Returns a copy of a range with any cell whose formula is a nested total removed.
199
249
  *
@@ -275,6 +325,7 @@ export interface IFormulaContext {
275
325
  *
276
326
  * @param criteria The criteria, exactly as the user wrote it — a comparison (`">10"`, `"<>x"`),
277
327
  * a wildcard pattern (`"a*"`), or a literal of any type.
328
+ * @param options How the criteria is matched. See {@link IFormulaContext.CriteriaOptions}.
278
329
  * @returns A predicate to test cell values with. Call it once per cell.
279
330
  *
280
331
  * @remarks
@@ -296,7 +347,34 @@ export interface IFormulaContext {
296
347
  * const count = range.reduce((total, value) => matches(value) ? total + 1 : total, 0);
297
348
  * ```
298
349
  */
299
- createCriteria(criteria: Scalar): IFormulaContext.CriteriaEvaluator;
350
+ createCriteria(criteria: Scalar, options?: IFormulaContext.CriteriaOptions): IFormulaContext.CriteriaEvaluator;
351
+ /**
352
+ * Groups the records of a range — its rows — by their values.
353
+ *
354
+ * @param keys The key columns. Each row is one record, and records with equal values in every
355
+ * column form one group.
356
+ * @param options Which records take part. See {@link IFormulaContext.GroupingOptions}.
357
+ * @returns The groups, numbered in the order they first appear.
358
+ *
359
+ * @remarks
360
+ * Two keys are equal by the rule `UNIQUE` uses: text ignores case, and types never mix, so `1`,
361
+ * `"1"` and `TRUE` are three groups. A blank key is a key of its own, distinct from `""`, and an
362
+ * error is a key like any other value. Every row is a record, blank rows included.
363
+ *
364
+ * Group ONCE and ask the grouping for each group's members. The grouping does the work a
365
+ * per-group scan would repeat, so it stays proportional to the data rather than to the data
366
+ * times the number of groups.
367
+ *
368
+ * @example
369
+ * ```typescript
370
+ * const grouping = FormulaContext.createGrouping(regions);
371
+ * for (let g = 0; g < grouping.getGroupCount(); g++) {
372
+ * const [region] = grouping.getKeys(g);
373
+ * const sales = grouping.getMembers(amounts, [g]);
374
+ * }
375
+ * ```
376
+ */
377
+ createGrouping(keys: IRange, options?: IFormulaContext.GroupingOptions): IFormulaContext.Grouping;
300
378
  /**
301
379
  * Reads a typed literal in the workbook's language — the parse side of {@link toText}.
302
380
  *
@@ -384,6 +462,30 @@ export interface IFormulaContext {
384
462
  * ```
385
463
  */
386
464
  getNow(): number;
465
+ /**
466
+ * Returns a random number in `[0, 1)`, like `Math.random()`.
467
+ *
468
+ * @remarks
469
+ * Always draw through this, never `Math.random()`. The source is the runtime's, so a test or a
470
+ * replay can seed it, and the engine sees the draw: a draw is a PER-CELL read — two cells calling
471
+ * the same function in one pass differ — where `getNow` is one value for the whole pass, and the
472
+ * engine only shares an evaluation across the cells of a block when nothing per-cell was read.
473
+ * Pair it with `Volatile<T>` so the function draws again on the next pass.
474
+ *
475
+ * Under a seeded runtime ({@link IRuntime.getRandomSeed}) each draw is keyed by the cell, the
476
+ * pass and which draw it is within that cell, so a function that draws more than once gets
477
+ * distinct values and a cell gets the same ones however the pass was ordered. Take the draws
478
+ * where they are used rather than hoisting them, and the values follow the cells rather than
479
+ * the code path.
480
+ *
481
+ * @example
482
+ * ```typescript
483
+ * export function RAND(): Volatile<number> {
484
+ * return FormulaContext.getRandom();
485
+ * }
486
+ * ```
487
+ */
488
+ getRandom(): number;
387
489
  /**
388
490
  * Returns `true` if the value is a usable date — either a `Date` or a number in the
389
491
  * workbook's serial date range.
@@ -445,14 +547,12 @@ export interface IFormulaContext {
445
547
  * Fields may fall outside their normal range and carry, which is what makes `DATE` and
446
548
  * `TIME` arithmetic work: month 13 is January of the next year, hour 50 is two days plus
447
549
  * 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` — measured 25/25 by
449
- * `probe-date-1900-day-overflow.ps1`.
550
+ * space, so it runs through the phantom `1900-02-29`.
450
551
  *
451
552
  * **This validates nothing, and that is deliberate — a caller MUST choose its own
452
553
  * policy.** No range check, no clamping, no bounds on any field, and no `DATE`-style
453
554
  * `0..1899 -> +1900` year offset. Those belong to `DATE`'s ARGUMENTS, not to the
454
- * calendar, and the three things that prove it were measured together
455
- * (`probe-date-arg-layer.ps1`, 2026-08-20):
555
+ * calendar, and three things prove it:
456
556
  *
457
557
  * * **The day policy is the caller's.** `DATE` and `DATEDIF`'s `md`/`yd` re-anchoring
458
558
  * want the raw carry above — `DATEDIF("2020-01-31","2020-03-01","md")` is `-1`
@@ -482,6 +582,22 @@ export interface IFormulaContext {
482
582
  * Mostly for diagnostics; the built-in `INFO` function is built on it.
483
583
  */
484
584
  getRuntime(): IRuntime;
585
+ /**
586
+ * The current call's arguments — how many the caller supplied, in which positions, of what kind,
587
+ * and what each value was BEFORE coercion.
588
+ *
589
+ * @remarks
590
+ * Argument REFLECTION, for the one thing a declaration cannot say: what happened at *this* call.
591
+ * It exists to serve Excel's declared `any`, which means "no contract, the body decides" — every
592
+ * other Excel type maps onto a type we already have and the marshaller handles it.
593
+ *
594
+ * The returned view is valid ONLY while the body that asked for it is running. Views are pooled
595
+ * by dispatch depth, so retaining one across an `await`, a callback, or a nested evaluation hands
596
+ * you another call's arguments.
597
+ *
598
+ * @throws If called outside a function dispatch — there are no arguments to reflect on.
599
+ */
600
+ getArgs(): IFunctionArguments;
485
601
  }
486
602
  /**
487
603
  * {@inheritDoc IFormulaContext}
@@ -492,6 +608,28 @@ export interface IFormulaContext {
492
608
  * {@link IFormulaContext}
493
609
  */
494
610
  export declare namespace IFormulaContext {
611
+ /**
612
+ * Options for {@link IFormulaContext.filterHidden}.
613
+ */
614
+ interface FilterHiddenOptions {
615
+ /**
616
+ * Which axis to filter on.
617
+ * @defaultValue `IRange.AxisSelection.Row`
618
+ */
619
+ axes?: IRange.AxisSelection;
620
+ /**
621
+ * Skip the hidden rows or columns only while the range's sheet is filtered: while some
622
+ * AutoFilter or table on that sheet holds a condition, whether or not it hides a row. Until
623
+ * then `range` is returned as it is, hidden rows included.
624
+ *
625
+ * @remarks
626
+ * This is `SUBTOTAL` 1-11 (Excel: they "include manually hidden rows", which is what an
627
+ * unfiltered sheet reads as). `SUBTOTAL` 101-111 and `AGGREGATE` leave it off and skip
628
+ * always.
629
+ * @defaultValue false
630
+ */
631
+ onlyWhileFiltered?: boolean;
632
+ }
495
633
  /**
496
634
  * Options for {@link IFormulaContext.parseAsNumber}.
497
635
  */
@@ -505,6 +643,80 @@ export declare namespace IFormulaContext {
505
643
  * there.
506
644
  */
507
645
  type CriteriaEvaluator = (value: Scalar) => boolean;
646
+ /**
647
+ * How a criteria is matched — see {@link IFormulaContext.createCriteria}.
648
+ */
649
+ interface CriteriaOptions {
650
+ /**
651
+ * Where a TEXT criteria has to line up with the cell: `'whole'` (the default) for the whole
652
+ * cell, `'start'` for a prefix.
653
+ *
654
+ * @remarks
655
+ * The `D` functions' criteria table is the prefix form and the `*IF` family is not: the
656
+ * criterion `appl` takes the row whose value is `Apple` at `DSUM` and no row at all at
657
+ * `COUNTIF`, and the empty criterion — a prefix of everything — takes every TEXT cell at
658
+ * `DSUM` where `COUNTIF` takes only a cell that IS an empty string.
659
+ *
660
+ * It applies to a criteria that stays TEXT and to nothing else. An OPERATOR turns it off
661
+ * (`=appl` selects no row), and so does a criteria that reads as a number, a boolean or an
662
+ * error — `1` does not reach a cell holding `12`.
663
+ */
664
+ anchor?: 'whole' | 'start';
665
+ }
666
+ /**
667
+ * Options for {@link IFormulaContext.createGrouping}.
668
+ */
669
+ interface GroupingOptions {
670
+ /**
671
+ * One column, as tall as the keys, selecting the records that take part. A record is kept
672
+ * when its member is `TRUE` or a nonzero number, and left out otherwise.
673
+ */
674
+ filter?: IRange;
675
+ }
676
+ /**
677
+ * The records of a range divided into groups — see {@link IFormulaContext.createGrouping}.
678
+ */
679
+ interface Grouping {
680
+ /**
681
+ * The number of records kept by the filter.
682
+ */
683
+ getRecordCount(): number;
684
+ /**
685
+ * The number of groups.
686
+ */
687
+ getGroupCount(): number;
688
+ /**
689
+ * The number of records in a group.
690
+ */
691
+ getSize(group: number): number;
692
+ /**
693
+ * A group's key, one value per key column, as spelled by the group's first record. A blank
694
+ * key is `null`.
695
+ */
696
+ getKeys(group: number): readonly Scalar[];
697
+ /**
698
+ * The group a record belongs to, or `-1` when the filter left it out.
699
+ *
700
+ * @param record The record's row within the keys.
701
+ */
702
+ getGroup(record: number): number;
703
+ /**
704
+ * The row of a group's first record within the keys.
705
+ *
706
+ * @remarks
707
+ * With {@link getGroup} on another grouping of the same records, this maps a group of one
708
+ * grouping onto the group of another — a finer grouping's group onto its parent's.
709
+ */
710
+ getFirstRecord(group: number): number;
711
+ /**
712
+ * The members of `values` that belong to some groups, as one column in record order.
713
+ *
714
+ * @param values One column, as tall as the keys.
715
+ * @param groups The groups to take members from. Omit it for every kept record.
716
+ * @returns An array, never a reference. A blank member stays blank.
717
+ */
718
+ getMembers(values: IRange, groups?: readonly number[]): IRange;
719
+ }
508
720
  /**
509
721
  * A serial date split into fields — see {@link IFormulaContext.getDateParts}.
510
722
  *