@sheetxl/sdk 0.7.28-beta.3 → 0.8.0-beta.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.
- package/browser/cjs/{BX6A6xGDOr_td9mw.cjs → BatsV2UUraVDCRXm.cjs} +1 -1
- package/browser/cjs/CUz53T65cRGQRgvv.cjs +33 -0
- package/browser/cjs/{CWCKcp58KidyndaL.cjs → DU0kYUtdFa3jK-im.cjs} +1 -1
- package/browser/cjs/{B4PKKgaDTG9aSO-f.cjs → Dv4yIPLV98M5zLHa.cjs} +1 -1
- package/browser/cjs/a0Z-SXs_N71CtqYb.cjs +1 -0
- package/browser/cjs/index.cjs +2 -2
- package/browser/esm/{Dv8FyXyeygJPXoHo.mjs → 6JKSOvc5czaQB2Bj.mjs} +3 -3
- package/browser/esm/{DZfds6s3ayTZrozO.mjs → B0HS42a7lga1k1U_.mjs} +1 -1
- package/browser/esm/{C78IaCXqwCcraBPe.mjs → BtuJ9AGzeURtAsGo.mjs} +6946 -5790
- package/browser/esm/{CX1NO_a1QPjXDvTU.mjs → DGU6sM25u0EWCKl1.mjs} +3 -3
- package/browser/esm/{B1gpnr-7kLU7jTy-.mjs → DlPMeIyxT9tG_WDk.mjs} +2 -2
- package/browser/esm/{CPgz9_iM7xyAcytg.mjs → f2G3QRgEbvFJcoa2.mjs} +2 -2
- package/browser/esm/index.mjs +17 -14
- package/browser/esm/{Rj8e7SashcMlcdZJ.mjs → uyWBMSIxMlt8n5Z3.mjs} +2 -2
- package/node/esm/{8VtzCFSmLPKxJjOa.mjs → -pxdn3M3tc6PLHs7.mjs} +20 -20
- package/node/esm/{BkY99r-c3BhlT_Kv.mjs → 0n5bslM9jhO1JnI2.mjs} +1 -1
- package/node/esm/{DE3eIaqkk5xzmV1c.mjs → Cku7XiUvw1xrRasi.mjs} +1 -1
- package/node/esm/index.mjs +9650 -8487
- package/package.json +6 -6
- package/types/scripting-enums.json +6 -0
- package/types/scripting.d.ts +586 -27
- package/types/src/anchored/IAnchored.d.ts +27 -0
- package/types/src/calculation/Calculation.d.ts +26 -12
- package/types/src/calculation/ICalculation.d.ts +178 -0
- package/types/src/calculation/executor/CalcExecutor.d.ts +314 -14
- package/types/src/calculation/executor/CalcExecutorUtils.d.ts +31 -0
- package/types/src/calculation/executor/CircularReference.d.ts +81 -0
- package/types/src/calculation/grid/CalcGrid.d.ts +3 -1
- package/types/src/calculation/grid/CalcGridUtils.d.ts +3 -2
- package/types/src/calculation/grid/ICalcGrid.d.ts +12 -1
- package/types/src/calculation/spatial/CircularEntry.d.ts +18 -0
- package/types/src/calculation/spatial/index.d.ts +1 -0
- package/types/src/calculation/state/CalcNode.d.ts +44 -17
- package/types/src/calculation/state/CalcState.d.ts +78 -15
- package/types/src/calculation/state/CalculationContext.d.ts +42 -1
- package/types/src/calculation/state/IContextContainer.d.ts +31 -0
- package/types/src/calculation/state/_ReadObservedGrid.d.ts +90 -0
- package/types/src/cell/ICell.d.ts +16 -0
- package/types/src/cellRange/ICellRange.d.ts +51 -21
- package/types/src/condition/AnchoredConditional.d.ts +26 -6
- package/types/src/conditionalFormat/ConditionalFormat.d.ts +8 -1
- package/types/src/conditionalFormat/IConditionalFormat.d.ts +4 -1
- package/types/src/conditionalFormat/IConditionalFormatCollection.d.ts +6 -2
- package/types/src/dataValidation/IDataValidationCollection.d.ts +6 -2
- package/types/src/hyperlink/IHyperlink.d.ts +3 -1
- package/types/src/hyperlink/_Hyperlink.d.ts +6 -0
- package/types/src/lib/utils/_Utils.d.ts +7 -0
- package/types/src/lib/utils/utils.browser.d.ts +5 -0
- package/types/src/license/LicenseDetails.d.ts +5 -0
- package/types/src/primitives/CalcSignal.d.ts +20 -0
- package/types/src/primitives/PrimitiveUtils.d.ts +4 -2
- package/types/src/primitives/Range.d.ts +3 -1
- package/types/src/protectedRange/IProtectedRangeCollection.d.ts +7 -2
- package/types/src/scripting/FunctionArguments.d.ts +22 -0
- package/types/src/scripting/TypedFunction.d.ts +60 -0
- package/types/src/scripting/_ScriptUtils.d.ts +13 -0
- package/types/src/sheet/Sheet.d.ts +41 -2
- package/types/src/sheet/SheetCell.d.ts +2 -0
- package/types/src/sheet/SheetRange.d.ts +3 -0
- package/types/src/sheet/_SheetAutoFitUtils.d.ts +28 -0
- package/types/src/sheet/_SheetStateTypes.d.ts +14 -1
- package/types/src/style/IStyle.d.ts +5 -0
- package/types/src/table/AnchoredTable.d.ts +17 -1
- package/types/src/text/TextUtils.d.ts +18 -0
- package/browser/cjs/1mH2uhx_Dmceu88H.cjs +0 -33
- package/browser/cjs/D6cjnwWR_iUSe1f6.cjs +0 -1
|
@@ -40,31 +40,58 @@ export interface CalcNode {
|
|
|
40
40
|
cachedValue: Scalar | IRange | undefined;
|
|
41
41
|
pendingPromise: Promise<any> | null;
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
43
|
+
* The demand evaluation's result — finalized for the cell, or a pending promise — which
|
|
44
|
+
* `doEvaluate` consumes in place of an `evaluateAt` of its own. Cleared once consumed.
|
|
45
|
+
* Meaningful only while `CalcState.Circular` is set.
|
|
44
46
|
*/
|
|
45
|
-
|
|
47
|
+
demandValue: any;
|
|
46
48
|
/**
|
|
47
|
-
*
|
|
49
|
+
* Identifies the cycle a `CycleRole.Member` belongs to (and the one a `CycleRole.Downstream`
|
|
50
|
+
* node read). `0` for none. Slices that share a node share an id. Reset every mark phase.
|
|
48
51
|
*/
|
|
49
|
-
|
|
52
|
+
cycleGroup: number;
|
|
50
53
|
/**
|
|
51
|
-
*
|
|
54
|
+
* For a `CycleRole.Member`: the member this one READ that continues the cycle — the next step
|
|
55
|
+
* of the walk `ICircularReference.getPath` answers. A cycle of one points at itself. Written
|
|
56
|
+
* from the `Circular` slice (whose stack order is the read order) and rewritten whenever the
|
|
57
|
+
* cycle is detected again; stale otherwise, so a walk checks each step is still a live member.
|
|
52
58
|
*/
|
|
53
|
-
|
|
59
|
+
cycleNext: CalcNode | null;
|
|
54
60
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*
|
|
61
|
+
* The cycle the sheet's circular index currently shows this cell in (`0` none) — what the last
|
|
62
|
+
* commit wrote, so the next can write the delta. Persists across passes, unlike
|
|
63
|
+
* {@link cycleGroup}; the role it shows is the `CalcState.ShownRoleMask` field of {@link state}.
|
|
64
|
+
*/
|
|
65
|
+
shownGroup: number;
|
|
66
|
+
/**
|
|
67
|
+
* Position of this node in the last FULLY-ORDERED plan that stamped it (CALC-PERFORMANCE-PLAN.md
|
|
68
|
+
* §1.2). Meaningful only when {@link planId} and {@link planEpoch} match the executor's current
|
|
69
|
+
* plan id and the container's static epoch; `-1` until first stamped.
|
|
70
|
+
*/
|
|
71
|
+
orderIndex: number;
|
|
72
|
+
/**
|
|
73
|
+
* Id of the Kahn pass that stamped {@link orderIndex}; `0` = never stamped. Stamps from
|
|
74
|
+
* different passes are NOT mutually comparable — the fast path requires every affected node to
|
|
75
|
+
* carry the executor's `_lastPlanId`.
|
|
76
|
+
*/
|
|
77
|
+
planId: number;
|
|
78
|
+
/** The container's `staticEpoch` when {@link orderIndex} was stamped; stale under a newer epoch. */
|
|
79
|
+
planEpoch: number;
|
|
80
|
+
/**
|
|
81
|
+
* The container's `precedentEpoch` when {@link dependents} was last computed
|
|
82
|
+
* (CALC-PERFORMANCE-PLAN.md §1.3). Discovery reuses the cached array while this matches;
|
|
83
|
+
* `0` = never computed.
|
|
62
84
|
*/
|
|
63
|
-
|
|
85
|
+
dependentsEpoch: number;
|
|
64
86
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
87
|
+
* Bit mask, laid out by `CalcState`: the pending flags, `Skip`, `Circular`, and the
|
|
88
|
+
* `DemandState`/`CycleRole` fields of the current pass.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* The node is reused across passes, so a per-pass bit is only meaningful when {@link cycleId}
|
|
92
|
+
* and {@link markId} say the node is in the current pass; the mark phase resets them
|
|
93
|
+
* (`CalcState.PassMask`) as it visits each affected node. `Skip` and the shown role outlive a
|
|
94
|
+
* pass on purpose.
|
|
68
95
|
*/
|
|
69
96
|
state: number;
|
|
70
97
|
}
|
|
@@ -1,28 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bit layout of `CalcNode.state`: single-bit flags in the low byte, then three 2-bit fields.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Every bit is independent, so a phase touches only its own: the mark phase clears
|
|
6
|
+
* {@link PassMask} (what the last pass decided), `doEvaluate` consumes {@link Skip}, and the
|
|
7
|
+
* promise path flips the pending bits — none of them assigns the whole word.
|
|
8
|
+
*
|
|
9
|
+
* The 2-bit fields hold a {@link DemandState} and two {@link CycleRole}s. Their values are
|
|
10
|
+
* pre-shifted into place, so a read is `(state & Mask) === Value` and a write is
|
|
11
|
+
* `state = (state & ~Mask) | Value`. The `ShownRole` field sits two bits above `CycleRole`, so
|
|
12
|
+
* copying the role the pass decided into what the sheet shows is `(state & CycleRoleMask) << 2`.
|
|
13
|
+
*/
|
|
1
14
|
export declare const CalcState: {
|
|
15
|
+
/** Nothing set. */
|
|
16
|
+
readonly Idle: 0;
|
|
2
17
|
/**
|
|
3
|
-
*
|
|
18
|
+
* Evaluate-once guard for a dynamic dependency (a dynamic precedent or a spill output) that
|
|
19
|
+
* caused a recalc: the next pass skips the node instead of re-evaluating it.
|
|
4
20
|
*/
|
|
5
|
-
readonly
|
|
21
|
+
readonly Skip: number;
|
|
22
|
+
/** Reserved. */
|
|
23
|
+
readonly Removed: number;
|
|
24
|
+
/** The node is in the pending spatial (the user has been given a pending status). */
|
|
25
|
+
readonly Pending: number;
|
|
26
|
+
/** A precedent evaluated to a pending value this pass, so the node keeps its cached value. */
|
|
27
|
+
readonly PendingPrecedents: number;
|
|
28
|
+
/** The node's promise resolved; the result waits in `cachedValue` for the next pass. */
|
|
29
|
+
readonly PendingResolved: number;
|
|
6
30
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
31
|
+
* The topological sort could not order the node this pass — it is in a reference cycle, or
|
|
32
|
+
* downstream of one — so it was (or will be) evaluated by demand and `doEvaluate` takes its
|
|
33
|
+
* `demandValue` in place of an `evaluateAt`.
|
|
9
34
|
*/
|
|
10
|
-
readonly
|
|
11
|
-
readonly Removed: 2;
|
|
35
|
+
readonly Circular: number;
|
|
12
36
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
37
|
+
* A `Waiting` node the evaluation in progress has read under iterative calculation — it is in
|
|
38
|
+
* the executor's hit list already, so a second read of it in the same evaluation adds nothing.
|
|
39
|
+
* Cleared when the list is consumed.
|
|
15
40
|
*/
|
|
16
|
-
readonly
|
|
41
|
+
readonly IterHit: number;
|
|
42
|
+
/** Field: the {@link DemandState}. */
|
|
43
|
+
readonly DemandMask: number;
|
|
44
|
+
/** Field: the {@link CycleRole} this pass decided. */
|
|
45
|
+
readonly CycleRoleMask: number;
|
|
46
|
+
/** Field: the {@link CycleRole} the sheet's circular index currently shows (persists). */
|
|
47
|
+
readonly ShownRoleMask: number;
|
|
17
48
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
49
|
+
* In the executor's circular roster for the pass in progress. Outside {@link PassMask} on
|
|
50
|
+
* purpose: the roster outlives the re-marks a pass makes while it re-dirties, so the executor
|
|
51
|
+
* clears this when it empties the roster.
|
|
20
52
|
*/
|
|
21
|
-
readonly
|
|
53
|
+
readonly Rostered: number;
|
|
54
|
+
/** What the mark phase resets: everything a single pass decides. `Skip` and the shown role survive. */
|
|
55
|
+
readonly PassMask: number;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Where a node the topological sort could not order stands in the demand evaluation
|
|
59
|
+
* (DESIGN-CIRCULAR-CALC.md §4.3). Meaningful only while `CalcState.Circular` is set for the
|
|
60
|
+
* current pass. Values sit in the `CalcState.DemandMask` field.
|
|
61
|
+
*/
|
|
62
|
+
export declare const DemandState: {
|
|
63
|
+
/** Not yet evaluated; a read of it suspends the reader so it can go first. */
|
|
64
|
+
readonly Unevaluated: 0;
|
|
65
|
+
/** On the in-progress stack; a read of it is a reference cycle. */
|
|
66
|
+
readonly Waiting: number;
|
|
67
|
+
/** Evaluated (or written `0` as a cycle member); reads see its value. */
|
|
68
|
+
readonly Done: number;
|
|
69
|
+
/**
|
|
70
|
+
* Evaluated on the ordered path but not yet committed — its value is in the pending batch, so a
|
|
71
|
+
* lazy read of the grid would still see the previous one. Reads treat it as {@link Unevaluated}
|
|
72
|
+
* until the batch is flushed, which makes it {@link Done}.
|
|
73
|
+
*/
|
|
74
|
+
readonly Evaluated: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* How a node relates to a reference cycle, decided by the demand evaluation's reads. Values sit
|
|
78
|
+
* in the `CalcState.CycleRoleMask` field.
|
|
79
|
+
*/
|
|
80
|
+
export declare const CycleRole: {
|
|
81
|
+
/** Not in a cycle and reads none — an unorderable node that simply computed. */
|
|
82
|
+
readonly None: 0;
|
|
83
|
+
/** Named by a `Circular` read: its evaluation needed its own value. Writes `0`. */
|
|
84
|
+
readonly Member: number;
|
|
22
85
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
86
|
+
* Read a member (transitively). Writes `0` too — Excel gives every cell downstream of a cycle
|
|
87
|
+
* `0`, not a value computed from the members' `0` (design §2.1: `=A1+100` is `0`).
|
|
25
88
|
*/
|
|
26
|
-
readonly
|
|
89
|
+
readonly Downstream: number;
|
|
27
90
|
};
|
|
28
91
|
//# sourceMappingURL=CalcState.d.ts.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { IRange, ScalarType, FormulaError, Scalar, IReferenceRange, IFunction, IFormulaContext, IRuntime } from '@sheetxl/primitives';
|
|
1
|
+
import { IRange, ScalarType, FormulaError, Scalar, IReferenceRange, IFunction, IFormulaContext, IFunctionArguments, IRuntime } from '@sheetxl/primitives';
|
|
2
2
|
import { FunctionProvider } from '@sheetxl/scripting';
|
|
3
3
|
import { ITransaction } from '../../transaction';
|
|
4
4
|
import { IFunctionCollection } from '../../scripting';
|
|
5
5
|
import { Tuple } from '../../collections';
|
|
6
6
|
import { IContextContainer } from './IContextContainer';
|
|
7
7
|
import { CalcScope } from './CalcScope';
|
|
8
|
+
import { ReadHook } from './_ReadObservedGrid';
|
|
8
9
|
export declare class CalculationContext implements IFormulaContext {
|
|
9
10
|
protected _instanceScope: any;
|
|
10
11
|
protected _runtime: IRuntime;
|
|
@@ -14,9 +15,39 @@ export declare class CalculationContext implements IFormulaContext {
|
|
|
14
15
|
protected _axis: IRange.Axis;
|
|
15
16
|
protected _coerceToNumber: (value: Scalar, fromType: ScalarType, options?: IFormulaContext.ParseNumberOptions) => Scalar;
|
|
16
17
|
protected _functionProviders?: readonly FunctionProvider[];
|
|
18
|
+
/**
|
|
19
|
+
* Receives every value read while armed; `null` on the ordinary path.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* Two paths read the grid on a formula's behalf and both report here: a reference built by
|
|
23
|
+
* {@link _toReference} (its grid is wrapped in a {@link ReadObservedGrid}) and the direct
|
|
24
|
+
* single-cell read {@link getValueAt} falls back to. Constructing a reference is not a read.
|
|
25
|
+
*/
|
|
26
|
+
protected _onRead: ReadHook | null;
|
|
27
|
+
/**
|
|
28
|
+
* Receives the reads of references built on the DYNAMIC branch of {@link getReference} — the
|
|
29
|
+
* result of `OFFSET`/`INDIRECT`/`INDEX` — when {@link _onRead} is not armed. The executor arms
|
|
30
|
+
* it for the length of an ordinary pass so that a dynamic read landing on the evaluating cell
|
|
31
|
+
* is seen (DESIGN-CIRCULAR-CALC.md §5); `null` outside a pass.
|
|
32
|
+
*/
|
|
33
|
+
protected _dynamicRead: ReadHook | null;
|
|
17
34
|
constructor(container: IContextContainer, axis?: IRange.Axis, functionProviders?: readonly FunctionProvider[]);
|
|
18
35
|
/** @hidden */
|
|
19
36
|
_setInstanceScope(instanceScope: any): void;
|
|
37
|
+
/**
|
|
38
|
+
* @hidden
|
|
39
|
+
* Arms (or, with `null`, disarms) the read hook. While armed, every reference this context
|
|
40
|
+
* builds observes its reads and every direct cell read is reported — the funnel a demand
|
|
41
|
+
* evaluation decides circularity through. The ordinary evaluation path leaves it `null` and
|
|
42
|
+
* builds references exactly as before.
|
|
43
|
+
*/
|
|
44
|
+
_setReadHook(hook: ReadHook | null): void;
|
|
45
|
+
/**
|
|
46
|
+
* @hidden
|
|
47
|
+
* Arms (or, with `null`, disarms) the hook dynamic-branch references report to while no read
|
|
48
|
+
* hook is armed. See {@link _dynamicRead}.
|
|
49
|
+
*/
|
|
50
|
+
_setDynamicReadHook(hook: ReadHook | null): void;
|
|
20
51
|
/**
|
|
21
52
|
* @hidden
|
|
22
53
|
*
|
|
@@ -100,6 +131,14 @@ export declare class CalculationContext implements IFormulaContext {
|
|
|
100
131
|
* A caller that reads a WINDOW rather than returning a reference - `SUMIF`'s `sum_range`,
|
|
101
132
|
* `LOOKUP`'s `result_vector`, both anchor-plus-length - goes through
|
|
102
133
|
* {@link getResizedReference} instead: Excel reads the part that fits rather than failing.
|
|
134
|
+
*
|
|
135
|
+
* This is the one place a reference is built on a formula's behalf, so it is where the read
|
|
136
|
+
* hook attaches: while {@link _onRead} is armed the reference is built over a
|
|
137
|
+
* {@link ReadObservedGrid} and every value it (or a view derived from it) opens is reported.
|
|
138
|
+
* Unarmed, a static reference's grid is used as is — the ordinary path pays nothing, not even a
|
|
139
|
+
* branch per read — while a `dynamic` one (the result of `OFFSET`/`INDIRECT`/`INDEX`, the rare
|
|
140
|
+
* path) reports to {@link _dynamicRead} when that is armed: a dynamic read that lands on the
|
|
141
|
+
* evaluating cell is a cycle on any path (design §5).
|
|
103
142
|
*/
|
|
104
143
|
private _toReference;
|
|
105
144
|
/** @inheritdoc IFormulaContext.getAddress */
|
|
@@ -119,6 +158,8 @@ export declare class CalculationContext implements IFormulaContext {
|
|
|
119
158
|
toText(value: Scalar | undefined): string;
|
|
120
159
|
/** @inheritdoc IFormulaContext.getRuntime */
|
|
121
160
|
getRuntime(): IRuntime;
|
|
161
|
+
/** @inheritdoc IFormulaContext.getArgs */
|
|
162
|
+
getArgs(): IFunctionArguments;
|
|
122
163
|
get [Symbol.toStringTag](): string;
|
|
123
164
|
toString(): string;
|
|
124
165
|
}
|
|
@@ -156,6 +156,37 @@ export interface IContextContainer {
|
|
|
156
156
|
* still carry, and the "already visited this cycle" guards would skip their re-evaluation.
|
|
157
157
|
*/
|
|
158
158
|
getCycleId(): number;
|
|
159
|
+
/**
|
|
160
|
+
* The graph-version counters the executor's plan caches key on (CALC-PERFORMANCE-PLAN.md §1.1).
|
|
161
|
+
*
|
|
162
|
+
* `staticEpoch` advances whenever the static edges may have changed — formula block
|
|
163
|
+
* register/unregister/edit, structural shift, sheet add/remove, undo/redo state swap — and
|
|
164
|
+
* governs order-stamp validity. `precedentEpoch` advances whenever `staticEpoch` does, plus on
|
|
165
|
+
* dynamic-precedent commits (spill/INDIRECT watchers), and governs `CalcNode.dependents`
|
|
166
|
+
* validity. The split is load-bearing: a dynamic commit changes who is affected, never the
|
|
167
|
+
* static topological constraints, so a sheet with a spill keeps a valid order cache.
|
|
168
|
+
*
|
|
169
|
+
* READING is what synchronizes: the implementation compares the identities of the spatial maps
|
|
170
|
+
* it last saw and advances the counters when a clone-then-swap happened (edits, shifts, undo/
|
|
171
|
+
* redo, pass-end dynamic commits all publish fresh maps). Sites that mutate the CURRENT maps in
|
|
172
|
+
* place — `CalcGrid.fromJSON` loads, an un-cloned `shift` — must call {@link bumpCalcEpochs}
|
|
173
|
+
* explicitly, because no identity changes there.
|
|
174
|
+
*
|
|
175
|
+
* Both counters are monotonic and deliberately NOT transactional, for the same reason as
|
|
176
|
+
* {@link getCycleId}: they are compared against stamps on plain mutable graph objects that
|
|
177
|
+
* undo/redo never rewinds, so rewinding a counter would re-validate stale stamps.
|
|
178
|
+
*/
|
|
179
|
+
getCalcEpochs(): {
|
|
180
|
+
staticEpoch: number;
|
|
181
|
+
precedentEpoch: number;
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* Advances the epoch counters for an IN-PLACE mutation of the current spatial maps — the paths
|
|
185
|
+
* identity comparison in {@link getCalcEpochs} cannot see. `includeStatic: true` advances both
|
|
186
|
+
* counters (a formula/structure change); `false` advances only `precedentEpoch` (a
|
|
187
|
+
* dynamic-precedent-only change).
|
|
188
|
+
*/
|
|
189
|
+
bumpCalcEpochs(includeStatic: boolean): void;
|
|
159
190
|
/**
|
|
160
191
|
* Returns the committed or in-progress scalar values for the given grid.
|
|
161
192
|
*
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Scalar } from '@sheetxl/primitives';
|
|
2
|
+
import { Direction, RangeAxis, CellCoords, RangeCoords } from '@sheetxl/utils';
|
|
3
|
+
import { IGrid, ISparseGrid, Tuple } from '../../collections';
|
|
4
|
+
/**
|
|
5
|
+
* Receives every value read a formula makes while a read hook is armed.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* A single-cell read reports a 1x1 rectangle; a block read (iteration, runs, bounded tuples)
|
|
9
|
+
* reports the rectangle it was asked for — the cells it *may* open — because a sparse iterator
|
|
10
|
+
* cannot tell an empty cell from a formula cell whose value is not there yet, and the second is
|
|
11
|
+
* exactly the read a cycle check must see. Coordinates are absolute and closed.
|
|
12
|
+
*
|
|
13
|
+
* The hook may throw; the throw propagates through the reading function up to the evaluation
|
|
14
|
+
* that armed it. Nothing is reported for constructing a reference, for its coords or size, or for
|
|
15
|
+
* a copy made to hold derived values.
|
|
16
|
+
*/
|
|
17
|
+
export type ReadHook = (gridId: string, rowStart: number, colStart: number, rowEnd: number, colEnd: number) => void;
|
|
18
|
+
/**
|
|
19
|
+
* An `ISparseGrid` that reports every value access on an inner grid to a {@link ReadHook}.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* Every `ReferenceRange` a formula receives reads its cells through the grid it was built over
|
|
23
|
+
* and never touches the sheet directly, so wrapping that grid observes every value read the
|
|
24
|
+
* reference makes — through any `Range` view derived from it, since views share the grid.
|
|
25
|
+
*
|
|
26
|
+
* `clone`/`cloneEmpty` hand back the inner grid's copy UNWRAPPED. A `Range` operation clones
|
|
27
|
+
* its grid only as scratch space for a derived result (`fill`, `map`, a scalar broadcast) and
|
|
28
|
+
* overwrites what it later reads back; the coordinates in such a copy no longer name sheet
|
|
29
|
+
* cells (a broadcast writes its scalar at (0,0)), so reporting them would invent reads of A1.
|
|
30
|
+
*
|
|
31
|
+
* Writes are delegated verbatim; nothing on a reference's path writes to its grid.
|
|
32
|
+
*/
|
|
33
|
+
export declare class ReadObservedGrid implements ISparseGrid<Scalar> {
|
|
34
|
+
/**
|
|
35
|
+
* Number of wrappers constructed since module load.
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* A pass that Kahn orders builds none; tests pin that the ordinary path stays unwrapped.
|
|
39
|
+
*/
|
|
40
|
+
static created: number;
|
|
41
|
+
protected readonly _inner: ISparseGrid<Scalar>;
|
|
42
|
+
protected readonly _gridId: string;
|
|
43
|
+
protected readonly _onRead: ReadHook;
|
|
44
|
+
constructor(inner: ISparseGrid<Scalar>, gridId: string, onRead: ReadHook);
|
|
45
|
+
/** The grid being observed. */
|
|
46
|
+
getInner(): ISparseGrid<Scalar>;
|
|
47
|
+
/**
|
|
48
|
+
* Reports a block read. Missing sides of a partial bound are taken from the grid's maximum
|
|
49
|
+
* extent, then from its data extent; a grid with neither has nothing to read.
|
|
50
|
+
*/
|
|
51
|
+
protected _reportBounds(bounds: Partial<RangeCoords> | null | undefined): void;
|
|
52
|
+
/** {@inheritDoc IGrid.getValueAt} */
|
|
53
|
+
getValueAt(row: number, column: number): Scalar;
|
|
54
|
+
/** {@inheritDoc ISparseGrid.getRuns} */
|
|
55
|
+
getRuns(options?: ISparseGrid.RunIteratorOptions): ISparseGrid.RunIterableIterator<Scalar>;
|
|
56
|
+
/** {@inheritDoc IGrid.entries} */
|
|
57
|
+
entries(options?: IGrid.IteratorOptions): IGrid.EntryIterator<Scalar>;
|
|
58
|
+
/** {@inheritDoc IGrid.values} */
|
|
59
|
+
values(options?: IGrid.IteratorOptions): IGrid.ValueIterator;
|
|
60
|
+
/** {@inheritDoc IGrid.keys} */
|
|
61
|
+
keys(options?: IGrid.IteratorOptions): IGrid.KeyIterator;
|
|
62
|
+
/** {@inheritDoc IGrid.getValues} */
|
|
63
|
+
getValues(coords?: RangeCoords): Tuple.BoundedTuples<Scalar> | null;
|
|
64
|
+
/** {@inheritDoc IGrid.copyTo} */
|
|
65
|
+
copyTo(destination: IGrid, topLeft: CellCoords, from: RangeCoords): void;
|
|
66
|
+
/** {@inheritDoc IGrid.getAxis} */
|
|
67
|
+
getAxis(): RangeAxis;
|
|
68
|
+
/** {@inheritDoc IGrid.getCount} */
|
|
69
|
+
getCount(): number;
|
|
70
|
+
/** {@inheritDoc IGrid.getCoords} */
|
|
71
|
+
getCoords(): RangeCoords | null;
|
|
72
|
+
/** {@inheritDoc IGrid.getMaxCoords} */
|
|
73
|
+
getMaxCoords(): RangeCoords | null;
|
|
74
|
+
/** {@inheritDoc IGrid.clone} */
|
|
75
|
+
clone(cloneKey?: any): this;
|
|
76
|
+
/** {@inheritDoc IGrid.cloneEmpty} */
|
|
77
|
+
cloneEmpty(cloneKey?: any): this;
|
|
78
|
+
/** {@inheritDoc IGrid.setValues} */
|
|
79
|
+
setValues(values: Tuple.GridTuple<Scalar>): this;
|
|
80
|
+
/** {@inheritDoc IGrid.setValueAt} */
|
|
81
|
+
setValueAt(row: number, column: number, value: Scalar): void;
|
|
82
|
+
/** {@inheritDoc IGrid.delete} */
|
|
83
|
+
delete(coords: RangeCoords | null): boolean;
|
|
84
|
+
/** {@inheritDoc IGrid.clear} */
|
|
85
|
+
clear(): void;
|
|
86
|
+
/** {@inheritDoc IGrid.shift} */
|
|
87
|
+
shift(coords: RangeCoords, direction: Direction): boolean;
|
|
88
|
+
get [Symbol.toStringTag](): string;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=_ReadObservedGrid.d.ts.map
|
|
@@ -124,12 +124,28 @@ export interface ICell {
|
|
|
124
124
|
*
|
|
125
125
|
* @remarks
|
|
126
126
|
* Warnings differ from errors in that they may alter the display of the cell's value or type.
|
|
127
|
+
* A cell in a reference cycle, or downstream of one, carries one here — the text form of
|
|
128
|
+
* {@link getCircularReference}: the walk from this cell around the cycle and back
|
|
129
|
+
* ("Circular reference: A1 → B1 → A1"), or "Reads a circular reference at A1".
|
|
127
130
|
*/
|
|
128
131
|
getWarnings(): readonly string[];
|
|
129
132
|
/**
|
|
130
133
|
* Retrieves any errors attached to the cell.
|
|
131
134
|
*/
|
|
132
135
|
getErrors(): readonly string[];
|
|
136
|
+
/**
|
|
137
|
+
* The reference cycle this cell is in, or downstream of — or `null` when it is neither.
|
|
138
|
+
*
|
|
139
|
+
* @remarks
|
|
140
|
+
* Evaluated state, beside the value: a cell in a cycle, and every cell that reads one, is `0`
|
|
141
|
+
* (Excel, iterative calculation off), and this is the only thing that says why. Ask the cycle
|
|
142
|
+
* whether this cell is a member or a reader ({@link ICalculation.ICircularReference.isMember})
|
|
143
|
+
* and, under iterative calculation, whether it converged.
|
|
144
|
+
*
|
|
145
|
+
* The range-level view is `ICellRange.Feature.Circular` — `getCounts` for how many cells,
|
|
146
|
+
* `getRegions` for which, each region carrying this same object as its payload.
|
|
147
|
+
*/
|
|
148
|
+
getCircularReference(): ICalculation.ICircularReference | null;
|
|
133
149
|
/**
|
|
134
150
|
* Returns the style information applied to the cell.
|
|
135
151
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FormulaError, IRange, Scalar, InteropScalar, IRangeStats } from '@sheetxl/primitives';
|
|
2
|
-
import { Bounds, ReferenceableClipboard } from '@sheetxl/utils';
|
|
2
|
+
import { Bounds, Size, ReferenceableClipboard } from '@sheetxl/utils';
|
|
3
3
|
import { ITypes } from '../type';
|
|
4
4
|
import { IListener } from '../listener';
|
|
5
5
|
import { ITransaction } from '../transaction';
|
|
@@ -1102,6 +1102,22 @@ export interface ICellRange {
|
|
|
1102
1102
|
* Returns the absolute bounds for the range.
|
|
1103
1103
|
*/
|
|
1104
1104
|
getBounds(): Bounds;
|
|
1105
|
+
/**
|
|
1106
|
+
* The size this range's content needs — what {@link getBounds} would report if the range had
|
|
1107
|
+
* been {@link autoFit}. A pure query: nothing is measured onto the model and nothing is committed.
|
|
1108
|
+
*
|
|
1109
|
+
* @param options Measurement options. Default `{ axes: IRange.AxisSelection.Both }`.
|
|
1110
|
+
*
|
|
1111
|
+
* @remarks
|
|
1112
|
+
* - The width is the sum of the per-column best fits and the height the sum of the per-row best
|
|
1113
|
+
* fits, so a single-column range answers "how wide must this list be" directly.
|
|
1114
|
+
* - An axis left out of {@link BestFitOptions.axes} reports its current size.
|
|
1115
|
+
* - Only the range's own content is measured, so the answer never depends on cells outside it.
|
|
1116
|
+
* (`autoFit` also scans outside the range, to prove a shrink is safe.)
|
|
1117
|
+
* - Sheet protection is not consulted: reading a size cannot violate it, and a protected sheet
|
|
1118
|
+
* answers the same as an unprotected one.
|
|
1119
|
+
*/
|
|
1120
|
+
getBestFit(options?: ICellRange.BestFitOptions): Size;
|
|
1105
1121
|
/**
|
|
1106
1122
|
* Indicates if the range is readonly only.
|
|
1107
1123
|
*
|
|
@@ -1613,9 +1629,9 @@ export declare namespace ICellRange {
|
|
|
1613
1629
|
includeMergeOverflow?: boolean;
|
|
1614
1630
|
}
|
|
1615
1631
|
/**
|
|
1616
|
-
* Options for {@link ICellRange.
|
|
1632
|
+
* Options for {@link ICellRange.getBestFit} — measurement only.
|
|
1617
1633
|
*/
|
|
1618
|
-
interface
|
|
1634
|
+
interface BestFitOptions {
|
|
1619
1635
|
/**
|
|
1620
1636
|
* Best fit using the minimum amount of space required.
|
|
1621
1637
|
*
|
|
@@ -1626,21 +1642,6 @@ export declare namespace ICellRange {
|
|
|
1626
1642
|
* For example allowing numbers to round or use scientific notation.
|
|
1627
1643
|
*/
|
|
1628
1644
|
minContent?: boolean;
|
|
1629
|
-
/**
|
|
1630
|
-
* Restricts autoFit to only grow, never shrink.
|
|
1631
|
-
*
|
|
1632
|
-
* @defaultValue false - adjust in both directions.
|
|
1633
|
-
*
|
|
1634
|
-
* @remarks
|
|
1635
|
-
* This is useful when adjusting fonts and wan the columns to resize but not the rows.
|
|
1636
|
-
*/
|
|
1637
|
-
expandOnly?: boolean | IRange.Axis;
|
|
1638
|
-
/**
|
|
1639
|
-
* If this is set to `true` then any headers that have custom sizes will be ignored.
|
|
1640
|
-
*
|
|
1641
|
-
* @defaultValue false
|
|
1642
|
-
*/
|
|
1643
|
-
skipCustomSize?: boolean;
|
|
1644
1645
|
/**
|
|
1645
1646
|
* The axes to autoFit.
|
|
1646
1647
|
*
|
|
@@ -1662,6 +1663,26 @@ export declare namespace ICellRange {
|
|
|
1662
1663
|
*/
|
|
1663
1664
|
formulaView?: boolean;
|
|
1664
1665
|
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Options for {@link ICellRange.autoFit}.
|
|
1668
|
+
*/
|
|
1669
|
+
interface AutoFitOptions extends BestFitOptions, ITransaction.OperationOptions {
|
|
1670
|
+
/**
|
|
1671
|
+
* Restricts autoFit to only grow, never shrink.
|
|
1672
|
+
*
|
|
1673
|
+
* @defaultValue false - adjust in both directions.
|
|
1674
|
+
*
|
|
1675
|
+
* @remarks
|
|
1676
|
+
* This is useful when adjusting fonts and wan the columns to resize but not the rows.
|
|
1677
|
+
*/
|
|
1678
|
+
expandOnly?: boolean | IRange.Axis;
|
|
1679
|
+
/**
|
|
1680
|
+
* If this is set to `true` then any headers that have custom sizes will be ignored.
|
|
1681
|
+
*
|
|
1682
|
+
* @defaultValue false
|
|
1683
|
+
*/
|
|
1684
|
+
skipCustomSize?: boolean;
|
|
1685
|
+
}
|
|
1665
1686
|
/**
|
|
1666
1687
|
* Options for {@link ICellRanges.getFlattened}.
|
|
1667
1688
|
*/
|
|
@@ -2191,11 +2212,20 @@ export declare namespace ICellRange {
|
|
|
2191
2212
|
/** Cells inside a dynamic-array spill zone. Writing into one is a real failure mode. */
|
|
2192
2213
|
readonly Spills: "spills";
|
|
2193
2214
|
/**
|
|
2194
|
-
* Evaluated state: cells whose calculation itself failed
|
|
2195
|
-
*
|
|
2196
|
-
*
|
|
2215
|
+
* Evaluated state: cells whose calculation itself failed. Distinct from
|
|
2216
|
+
* {@link Feature.Error}: `#DIV/0!` is a successfully calculated error VALUE (the `Error`
|
|
2217
|
+
* kind); `CalcError` is the engine failing to evaluate at all. A reference cycle is not a
|
|
2218
|
+
* failure — its cells evaluate, to `0` — and is {@link Feature.Circular}.
|
|
2197
2219
|
*/
|
|
2198
2220
|
readonly CalcError: "calcError";
|
|
2221
|
+
/**
|
|
2222
|
+
* Evaluated state: cells in a reference cycle, or downstream of one. Both evaluate to `0`
|
|
2223
|
+
* (Excel, iterative calculation off) with nothing else to show for it — this is the marker.
|
|
2224
|
+
* Regions group by cycle and by kind (`member` | `downstream`), so a block that reads one bad
|
|
2225
|
+
* cell is ONE region, and each region's payload is the cycle itself
|
|
2226
|
+
* (`ICalculation.ICircularReference` — members, counts, whether iteration settled it).
|
|
2227
|
+
*/
|
|
2228
|
+
readonly Circular: "circular";
|
|
2199
2229
|
/** Direct fill. */
|
|
2200
2230
|
readonly Fill: "fill";
|
|
2201
2231
|
/** Direct borders. */
|
|
@@ -163,21 +163,41 @@ export declare abstract class AnchoredConditional<STATE extends AnchoredConditio
|
|
|
163
163
|
protected _rebaseConditionFormulas(json: any, from: IRange.CellCoords, to: IRange.CellCoords): boolean | null;
|
|
164
164
|
/**
|
|
165
165
|
* The extend half of a paste: fold the pasted `ranges` into THIS live rule — coalescing
|
|
166
|
-
* into clean
|
|
166
|
+
* into one clean rectangle — rather than minting a duplicate.
|
|
167
167
|
*
|
|
168
168
|
* @param ranges The pasted images of the rule's marked areas (already tiled/clipped).
|
|
169
169
|
* @param jsonAtMark `JSON.stringify` of the rule's `toJSON()` at mark time.
|
|
170
|
-
* @returns `false` when this rule
|
|
171
|
-
*
|
|
170
|
+
* @returns `false` when this rule cannot absorb the paste — deleted, its definition changed
|
|
171
|
+
* since the mark, or the union would move the anchor — and the caller must clone instead.
|
|
172
172
|
*
|
|
173
173
|
* @remarks
|
|
174
174
|
* Merging is provenance-keyed: only THE rule the areas were copied from extends, which is
|
|
175
|
-
* what keeps manually authored duplicates separate.
|
|
176
|
-
*
|
|
177
|
-
*
|
|
175
|
+
* what keeps manually authored duplicates separate.
|
|
176
|
+
*
|
|
177
|
+
* On top of provenance, a paste merges only when the union is a single rectangle whose
|
|
178
|
+
* top-left is still the rule's anchor. That is Excel's rule (desktop and online alike): a
|
|
179
|
+
* paste flush below or to the right of the applies-to merges into it, while one above, to
|
|
180
|
+
* the left, or with a gap mints a separate rule at top priority. The shape of it is that
|
|
181
|
+
* PASTE NEVER MOVES THE ANCHOR — growing down or right leaves the stored formula's frame
|
|
182
|
+
* alone, whereas growing up or left forces a rebase, which Excel is only willing to do for
|
|
183
|
+
* autofill. Hence fill merges in all four directions and paste in two.
|
|
178
184
|
* @internal
|
|
179
185
|
*/
|
|
180
186
|
_extendPastedRanges(ranges: readonly IRange.Coords[], jsonAtMark: string): boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Re-anchors a freshly pasted CLONE, whose formulas still carry the SOURCE rule's frame, to
|
|
189
|
+
* its own anchor — the shift Excel applies when a copied rule lands as a new rule (copying
|
|
190
|
+
* `F5:F10`/`G5>5` to `F20` stores `G20>5`).
|
|
191
|
+
*
|
|
192
|
+
* The shift is source-anchor to clone-anchor; the hop through the copied cell cancels, since
|
|
193
|
+
* relative offsets are preserved by both halves of it.
|
|
194
|
+
*
|
|
195
|
+
* A rebase that cannot survive the move leaves the formulas as authored — the wrong frame,
|
|
196
|
+
* but live, which beats a rule of `#REF!`. Excel never hits this: it wraps modulo the sheet
|
|
197
|
+
* instead, the same divergence the io layer converts across.
|
|
198
|
+
* @internal
|
|
199
|
+
*/
|
|
200
|
+
_rebaseClonedAnchor(anchorFrom: IRange.Coords): void;
|
|
181
201
|
/**
|
|
182
202
|
* The geometry half of {@link _extendPastedRanges}, shared with autofill (which needs no
|
|
183
203
|
* liveness or definition guards — the rule was read live inside the fill's transaction):
|
|
@@ -134,7 +134,14 @@ export declare class ConditionalFormat extends AnchoredConditional<State, Commit
|
|
|
134
134
|
/** @internal */
|
|
135
135
|
protected _createSpatial(coords: IRange.Coords): ISpatialMap.IUpdatableValue;
|
|
136
136
|
/** {@inheritDoc IConditionalFormat.update} */
|
|
137
|
-
update(properties: IConditionalFormat.Modifiers, options?: ITransaction.OperationOptions): this;
|
|
137
|
+
update(properties: IConditionalFormat.Modifiers | IConditionalFormat, options?: ITransaction.OperationOptions): this;
|
|
138
|
+
/**
|
|
139
|
+
* The modifiers that make one rule's definition another's: every mutually-exclusive key is
|
|
140
|
+
* named, so the target's old shape (`scale` vs `condition`+`style`) is cleared rather than
|
|
141
|
+
* merged with.
|
|
142
|
+
* @internal
|
|
143
|
+
*/
|
|
144
|
+
static replaceModifiers(json: IConditionalFormat.JSON | null): IConditionalFormat.Modifiers;
|
|
138
145
|
/** {@inheritDoc IConditionalFormat.toJSON} */
|
|
139
146
|
toJSON(): IConditionalFormat.JSON | null;
|
|
140
147
|
/** @internal */
|
|
@@ -123,8 +123,11 @@ export interface IConditionalFormat extends IAnchored, ICondition.Stateful, IPro
|
|
|
123
123
|
* Only the keys named are touched. An explicit `null` **clears** a key — required when switching
|
|
124
124
|
* a rule between its two shapes, since `condition`+`style` and `scale` are mutually exclusive
|
|
125
125
|
* (setting one side also clears the other unless the caller named both).
|
|
126
|
+
*
|
|
127
|
+
* Passing another rule takes its whole definition — every key, cleared where the other rule
|
|
128
|
+
* has none — so the shape switches with it. The anchor is not part of it.
|
|
126
129
|
*/
|
|
127
|
-
update(properties: IConditionalFormat.Modifiers, options?: ITransaction.OperationOptions): this;
|
|
130
|
+
update(properties: IConditionalFormat.Modifiers | IConditionalFormat, options?: ITransaction.OperationOptions): this;
|
|
128
131
|
/**
|
|
129
132
|
* Returns a snapshot of the conditional that can be used for copying and archiving.
|
|
130
133
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ICellRange, ICellRanges } from '../cellRange';
|
|
2
2
|
import { ICollection } from '../type';
|
|
3
|
+
import { IAnchored } from '../anchored';
|
|
3
4
|
import { IConditionalFormat } from './IConditionalFormat';
|
|
4
|
-
import { ITransaction } from '../transaction';
|
|
5
5
|
/**
|
|
6
6
|
* Holds a collection of {@link IConditionalFormat}s.
|
|
7
7
|
*/
|
|
@@ -38,8 +38,12 @@ export interface IConditionalFormatCollection extends ICollection<IConditionalFo
|
|
|
38
38
|
export declare namespace IConditionalFormatCollection {
|
|
39
39
|
/**
|
|
40
40
|
* Options for adding a {@link IConditionalFormat}.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* `replaceExisting` redefines the rule at `index` only when it is a scale rule of the same
|
|
44
|
+
* kind on exactly the same ranges — see {@link IAnchored.AddOptions.replaceExisting}.
|
|
41
45
|
*/
|
|
42
|
-
interface AddOptions extends IConditionalFormat.Properties,
|
|
46
|
+
interface AddOptions extends IConditionalFormat.Properties, IAnchored.AddOptions {
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
45
49
|
* Options for searching for {@link IConditionalFormat}s.
|