@univerjs-pro/engine-formula 1.0.0-alpha.7 → 1.0.0-beta.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.
Files changed (38) hide show
  1. package/lib/cjs/facade.js +1 -1
  2. package/lib/cjs/index.js +1 -1
  3. package/lib/es/facade.js +1 -1
  4. package/lib/es/index.js +1 -1
  5. package/lib/facade.js +1 -1
  6. package/lib/index.js +1 -1
  7. package/lib/types/commands/commands/host-external-reference.command.d.ts +43 -0
  8. package/lib/types/commands/commands/persist-formula-last-values.command.d.ts +6 -0
  9. package/lib/types/commands/mutations/set-host-external-reference.mutation.d.ts +7 -0
  10. package/lib/types/controllers/formula-last-value-persistence.controller.d.ts +9 -0
  11. package/lib/types/controllers/host-external-reference-active-dirty.controller.d.ts +5 -0
  12. package/lib/types/controllers/host-external-reference-calculation.controller.d.ts +9 -0
  13. package/lib/types/controllers/host-external-reference.controller.d.ts +5 -0
  14. package/lib/types/engine/dependency-engine/dependency-engine.d.ts +6 -5
  15. package/lib/types/engine/dependency-engine/formula-cell-index.d.ts +3 -2
  16. package/lib/types/engine/dependency-engine/helpers.d.ts +7 -6
  17. package/lib/types/engine/dependency-engine/point-subscription-index.d.ts +3 -2
  18. package/lib/types/engine/dependency-engine/range-index.d.ts +5 -4
  19. package/lib/types/engine/dependency-engine/types.d.ts +3 -20
  20. package/lib/types/engine/formula-dependency.d.ts +2 -2
  21. package/lib/types/facade/f-enum.d.ts +12 -2
  22. package/lib/types/facade/f-formula.d.ts +110 -60
  23. package/lib/types/index.d.ts +16 -1
  24. package/lib/types/models/formula-last-value.d.ts +14 -0
  25. package/lib/types/models/host-external-reference.model.d.ts +61 -0
  26. package/lib/types/services/calculate-formula.service.d.ts +8 -14
  27. package/lib/types/services/dependency-manager.service.d.ts +4 -4
  28. package/lib/types/services/formula-cache-eligibility.service.d.ts +18 -0
  29. package/lib/types/services/formula-last-value-persistence.service.d.ts +18 -0
  30. package/lib/types/services/formula-reference-data.service.d.ts +11 -1
  31. package/lib/types/services/formula-reference-unit.service.d.ts +70 -10
  32. package/lib/types/services/formula-result-presentation.d.ts +22 -0
  33. package/lib/types/services/host-external-reference-data-loader.service.d.ts +31 -0
  34. package/lib/types/services/host-formula-binding.service.d.ts +15 -0
  35. package/lib/types/services/main-formula-reference-data.service.d.ts +1 -0
  36. package/lib/umd/facade.js +1 -1
  37. package/lib/umd/index.js +1 -1
  38. package/package.json +6 -6
@@ -0,0 +1,43 @@
1
+ import type { ICommand, IMutationInfo } from '@univerjs/core';
2
+ import type { FormulaUnitType } from '@univerjs/engine-formula';
3
+ import type { IHostExternalReference } from '../../models/host-external-reference.model';
4
+ import type { ISetHostExternalReferenceMutationParams } from '../mutations/set-host-external-reference.mutation';
5
+ export interface IUpsertHostExternalReferenceCommandParams {
6
+ /** Stable ID of the Host Unit that owns the formula and persisted mapping. */
7
+ unitId: string;
8
+ /**
9
+ * Public Source name used in formula text, without brackets or quotes.
10
+ * Positive integers are invalid because Excel reserves them as external-link slots.
11
+ */
12
+ qualifier: string;
13
+ /** Stable Source Unit ID used for Formula Reference Data requests. */
14
+ sourceUnitId: string;
15
+ /** Source business type; product External References support Sheet and Base. */
16
+ sourceUnitType: FormulaUnitType;
17
+ /** Existing Host-local reference ID when the caller needs to update that exact entry. */
18
+ referenceId?: string;
19
+ }
20
+ export interface IRemoveHostExternalReferenceCommandParams {
21
+ /** Stable ID of the Host Unit that owns the mapping. */
22
+ unitId: string;
23
+ /** Host-local reference ID to remove. Supply this or `qualifier`. */
24
+ referenceId?: string;
25
+ /** Public Source qualifier to remove. Supply this or `referenceId`. */
26
+ qualifier?: string;
27
+ }
28
+ export interface IUpsertHostExternalReferencesCommandParams {
29
+ /** Stable ID of the Host Unit that owns the formula and persisted mappings. */
30
+ unitId: string;
31
+ /** Complete set of Source bindings required by one authoring operation. */
32
+ references: readonly IHostExternalReference[];
33
+ }
34
+ export interface IHostExternalReferenceMutationPair {
35
+ redoMutation?: IMutationInfo<ISetHostExternalReferenceMutationParams>;
36
+ undoMutation?: IMutationInfo<ISetHostExternalReferenceMutationParams>;
37
+ }
38
+ export declare const UpsertHostExternalReferenceCommand: ICommand<IUpsertHostExternalReferenceCommandParams>;
39
+ export declare const UpsertHostExternalReferencesCommand: ICommand<IUpsertHostExternalReferencesCommandParams>;
40
+ export declare const RemoveHostExternalReferenceCommand: ICommand<IRemoveHostExternalReferenceCommandParams>;
41
+ export declare function buildUpsertHostExternalReferenceMutations(accessor: Parameters<ICommand['handler']>[0], unitId: string | undefined, references: ReadonlyArray<IHostExternalReference & {
42
+ referenceId?: string;
43
+ }>): IHostExternalReferenceMutationPair | null;
@@ -0,0 +1,6 @@
1
+ import type { ICommand } from '@univerjs/core';
2
+ export interface IPersistFormulaLastValuesCommandParams {
3
+ sessionId: number;
4
+ }
5
+ /** Internal derived-state command. It intentionally does not create an undo entry. */
6
+ export declare const PersistFormulaLastValuesCommand: ICommand<IPersistFormulaLastValuesCommandParams>;
@@ -0,0 +1,7 @@
1
+ import type { IMutation } from '@univerjs/core';
2
+ import type { IHostExternalReferenceResource } from '../../models/host-external-reference.model';
3
+ export interface ISetHostExternalReferenceMutationParams {
4
+ unitId: string;
5
+ resource: IHostExternalReferenceResource;
6
+ }
7
+ export declare const SetHostExternalReferenceMutation: IMutation<ISetHostExternalReferenceMutationParams>;
@@ -0,0 +1,9 @@
1
+ import { Disposable, ICommandService } from '@univerjs/core';
2
+ import { FormulaCalculationSessionService } from '@univerjs/engine-formula';
3
+ import { FormulaLastValuePersistenceService } from '../services/formula-last-value-persistence.service';
4
+ export declare class FormulaLastValuePersistenceController extends Disposable {
5
+ private readonly _commandService;
6
+ private readonly _sessionService;
7
+ private _lastPersistedSessionId;
8
+ constructor(_commandService: ICommandService, _sessionService: FormulaCalculationSessionService, _persistenceService: FormulaLastValuePersistenceService);
9
+ }
@@ -0,0 +1,5 @@
1
+ import { Disposable, IUniverInstanceService } from '@univerjs/core';
2
+ import { IActiveDirtyManagerService, RegisterOtherFormulaService } from '@univerjs/engine-formula';
3
+ export declare class HostExternalReferenceActiveDirtyController extends Disposable {
4
+ constructor(activeDirtyManagerService: IActiveDirtyManagerService, univerInstanceService: IUniverInstanceService, registerOtherFormulaService: RegisterOtherFormulaService);
5
+ }
@@ -0,0 +1,9 @@
1
+ import { Disposable, ICommandService } from '@univerjs/core';
2
+ import { HostExternalReferenceModel } from '../models/host-external-reference.model';
3
+ /**
4
+ * External Reference resources travel with each calculation payload, just like dirty data.
5
+ * They are not synchronized to the Worker through resource mutations.
6
+ */
7
+ export declare class HostExternalReferenceCalculationController extends Disposable {
8
+ constructor(commandService: ICommandService, model: HostExternalReferenceModel);
9
+ }
@@ -0,0 +1,5 @@
1
+ import { Disposable, ICommandService, IResourceManagerService } from '@univerjs/core';
2
+ import { HostExternalReferenceModel } from '../models/host-external-reference.model';
3
+ export declare class HostExternalReferenceController extends Disposable {
4
+ constructor(commandService: ICommandService, resourceManagerService: IResourceManagerService, model: HostExternalReferenceModel);
5
+ }
@@ -1,4 +1,5 @@
1
- import type { CalcNodeIndex, CellId, DepList, ExternalNodeId, ICalcNodeDeps, ICalcNodeRef, ICalculationOrderResult, ICompressedSharedFormulaGroup, IDecodedCell, IDecodedFeatureCalculationId, IDecodedOtherFormulaId, IDependencyEngineOptions, IDynamicResolver, IRefRange, ISetNodeResult } from './types';
1
+ import type { IUnitRange } from '@univerjs/core';
2
+ import type { CalcNodeIndex, CellId, DepList, ExternalNodeId, ICalcNodeDeps, ICalcNodeRef, ICalculationOrderResult, ICompressedSharedFormulaGroup, IDecodedCell, IDecodedFeatureCalculationId, IDecodedOtherFormulaId, IDependencyEngineOptions, IDynamicResolver, ISetNodeResult } from './types';
2
3
  import { CellCodec } from './cell-codec';
3
4
  import { RangeIndex } from './range-index';
4
5
  /**
@@ -98,7 +99,7 @@ export declare class DependencyEngine {
98
99
  }): ISetNodeResult;
99
100
  setNewCellFormulaDeps(cell: CellId, deps: ICalcNodeDeps): ISetNodeResult;
100
101
  setNewCellFormulaNodeOnly(cell: CellId): ISetNodeResult;
101
- setNewCellFormulaNodeOnlyRange(unitId: string, sheetId: string, range: IRefRange['range'], skip?: {
102
+ setNewCellFormulaNodeOnlyRange(unitId: string, sheetId: string, range: IUnitRange['range'], skip?: {
102
103
  row: number;
103
104
  col: number;
104
105
  }): CalcNodeIndex[];
@@ -210,14 +211,14 @@ export declare class DependencyEngine {
210
211
  /**
211
212
  * Marks dependents of a changed range dirty without expanding all cells.
212
213
  */
213
- markRangeChanged(rangeInput: IRefRange, options?: {
214
+ markRangeChanged(rangeInput: IUnitRange, options?: {
214
215
  includeFormulaCells?: boolean;
215
216
  coalesce?: boolean;
216
217
  }): void;
217
218
  /**
218
219
  * Batch range-change entry point for paste, fill, clear, and import.
219
220
  */
220
- markRangesChanged(rangeInputs: IRefRange[], options?: {
221
+ markRangesChanged(rangeInputs: IUnitRange[], options?: {
221
222
  includeFormulaCells?: boolean;
222
223
  coalesce?: boolean;
223
224
  }): void;
@@ -244,7 +245,7 @@ export declare class DependencyEngine {
244
245
  getDirtyNodeIndices(): CalcNodeIndex[];
245
246
  getDirtyNodes(): ICalcNodeRef[];
246
247
  forEachDependentByCell(cell: CellId, cb: (node: ICalcNodeRef, nodeIndex: CalcNodeIndex) => void): void;
247
- forEachDependentByRange(range: IRefRange, cb: (node: ICalcNodeRef, nodeIndex: CalcNodeIndex) => void): void;
248
+ forEachDependentByRange(range: IUnitRange, cb: (node: ICalcNodeRef, nodeIndex: CalcNodeIndex) => void): void;
248
249
  forEachDependentByNode(node: ICalcNodeRef, cb: (dependentNode: ICalcNodeRef, dependentIndex: CalcNodeIndex) => void): void;
249
250
  forEachDependentByIndex(nodeIndex: CalcNodeIndex, cb: (dependentNode: ICalcNodeRef, dependentIndex: CalcNodeIndex) => void): void;
250
251
  /**
@@ -1,5 +1,6 @@
1
+ import type { IUnitRange } from '@univerjs/core';
1
2
  import type { CellCodec } from './cell-codec';
2
- import type { CalcNodeIndex, ExternalNodeId, IRefRange } from './types';
3
+ import type { CalcNodeIndex, ExternalNodeId } from './types';
3
4
  /**
4
5
  * Spatial index for active `CellFormula` nodes.
5
6
  *
@@ -16,7 +17,7 @@ export declare class FormulaCellIndex {
16
17
  addFormulaCell(formulaCell: number, nodeIndex: CalcNodeIndex): void;
17
18
  addFormulaCellByPosition(sheetKey: number, row: number, col: number, nodeIndex: CalcNodeIndex): void;
18
19
  removeFormulaCell(formulaCell: number, nodeIndex: CalcNodeIndex): void;
19
- forEachFormulaInRange(rangeInput: IRefRange, cb: (nodeIndex: CalcNodeIndex) => boolean | void): boolean;
20
+ forEachFormulaInRange(rangeInput: IUnitRange, cb: (nodeIndex: CalcNodeIndex) => boolean | void): boolean;
20
21
  private _scanRows;
21
22
  private _scanCols;
22
23
  private _scanRowBucket;
@@ -1,4 +1,5 @@
1
- import type { CalcNodeIndex, DepList, ExternalNodeId, ICalcNodeRef, IDecodedCell, IRefRange } from './types';
1
+ import type { IUnitRange } from '@univerjs/core';
2
+ import type { CalcNodeIndex, DepList, ExternalNodeId, ICalcNodeRef, IDecodedCell } from './types';
2
3
  /**
3
4
  * Shared low-level helpers for dependency storage.
4
5
  *
@@ -7,10 +8,10 @@ import type { CalcNodeIndex, DepList, ExternalNodeId, ICalcNodeRef, IDecodedCell
7
8
  * propagation.
8
9
  */
9
10
  export declare function assertCellNodeId(id: ExternalNodeId): asserts id is number;
10
- export declare function normalizeRange(r: IRefRange): IRefRange;
11
- export declare function rangeRowCount(r: IRefRange): number;
12
- export declare function rangeColCount(r: IRefRange): number;
13
- export declare function rangeContainsCell(r: IRefRange, d: IDecodedCell): boolean;
11
+ export declare function normalizeRange(r: IUnitRange): IUnitRange;
12
+ export declare function rangeRowCount(r: IUnitRange): number;
13
+ export declare function rangeColCount(r: IUnitRange): number;
14
+ export declare function rangeContainsCell(r: IUnitRange, d: IDecodedCell): boolean;
14
15
  export declare function uniqueSortedNumbers(values: readonly number[] | undefined): number[];
15
16
  export declare function pushToArrayMap<K>(map: Map<K, number[]>, key: K, value: number): void;
16
17
  export declare function removeFromArraySwap(arr: number[], value: number): boolean;
@@ -29,4 +30,4 @@ export declare function uniqueNodeRefs(values: readonly ICalcNodeRef[] | undefin
29
30
  * We do not merge L-shaped areas into a larger rectangle because that would
30
31
  * create too many false-positive dependents.
31
32
  */
32
- export declare function coalesceAlignedRanges(rangeInputs: IRefRange[]): IRefRange[];
33
+ export declare function coalesceAlignedRanges(rangeInputs: IUnitRange[]): IUnitRange[];
@@ -1,5 +1,6 @@
1
+ import type { IUnitRange } from '@univerjs/core';
1
2
  import type { CellCodec } from './cell-codec';
2
- import type { CellId, IRefRange } from './types';
3
+ import type { CellId } from './types';
3
4
  /**
4
5
  * Index of direct precedent cells subscribed by formula dependencies.
5
6
  *
@@ -15,7 +16,7 @@ export declare class PointSubscriptionIndex {
15
16
  constructor(_codec: CellCodec, _pointScanCellLimit: number);
16
17
  add(cell: CellId): void;
17
18
  remove(cell: CellId): void;
18
- forEachCellInRange(rangeInput: IRefRange, cb: (cell: CellId) => void): void;
19
+ forEachCellInRange(rangeInput: IUnitRange, cb: (cell: CellId) => void): void;
19
20
  private _isSmallArea;
20
21
  private _scanRows;
21
22
  private _scanCols;
@@ -1,5 +1,6 @@
1
+ import type { IUnitRange } from '@univerjs/core';
1
2
  import type { CellCodec } from './cell-codec';
2
- import type { CalcNodeIndex, IRefRange } from './types';
3
+ import type { CalcNodeIndex } from './types';
3
4
  /**
4
5
  * Reverse index from precedent ranges to dependent calculation nodes.
5
6
  *
@@ -37,19 +38,19 @@ export declare class RangeIndex {
37
38
  private readonly _nodeToWholeRowKeys;
38
39
  constructor(_codec: CellCodec, initialCapacity: number, _maxIndexedSpan: number);
39
40
  reserveCapacity(minCapacity: number): void;
40
- addRange(nodeIndex: CalcNodeIndex, rangeInput: IRefRange): void;
41
+ addRange(nodeIndex: CalcNodeIndex, rangeInput: IUnitRange): void;
41
42
  removeNode(nodeIndex: CalcNodeIndex): void;
42
43
  /**
43
44
  * Finds range-dependent nodes when one cell changes.
44
45
  */
45
46
  forEachPoint(unitId: string, sheetId: string, row: number, col: number, cb: (nodeIndex: CalcNodeIndex) => void): void;
46
- forEachRangeIntersecting(changedInput: IRefRange, cb: (nodeIndex: CalcNodeIndex) => void): void;
47
+ forEachRangeIntersecting(changedInput: IUnitRange, cb: (nodeIndex: CalcNodeIndex) => void): void;
47
48
  /**
48
49
  * Finds range-dependent nodes intersecting a batch of changed ranges.
49
50
  *
50
51
  * A single range epoch deduplicates normal range IDs across the batch.
51
52
  */
52
- forEachRangesIntersecting(changedInputs: IRefRange[], cb: (nodeIndex: CalcNodeIndex) => void): void;
53
+ forEachRangesIntersecting(changedInputs: IUnitRange[], cb: (nodeIndex: CalcNodeIndex) => void): void;
53
54
  private _allocRangeId;
54
55
  private _ensureRangeCapacity;
55
56
  private _setRangeMeta;
@@ -56,7 +56,6 @@ export interface IDecodedOtherFormulaId {
56
56
  /**
57
57
  * Unit-aware rectangular range.
58
58
  */
59
- export type IRefRange = IUnitRange;
60
59
  /**
61
60
  * Dependency declaration for a calculation node.
62
61
  */
@@ -73,7 +72,7 @@ export interface ICalcNodeDeps {
73
72
  *
74
73
  * Formula cells inside these ranges naturally become precedent nodes.
75
74
  */
76
- ranges?: IRefRange[];
75
+ ranges?: IUnitRange[];
77
76
  /**
78
77
  * Explicit precedent calculation nodes.
79
78
  *
@@ -107,7 +106,7 @@ export type ICompressedSharedFormulaPattern = {
107
106
  };
108
107
  export interface ICompressedSharedFormulaGroup {
109
108
  groupId: string;
110
- fillRange: IRefRange;
109
+ fillRange: IUnitRange;
111
110
  patterns: ICompressedSharedFormulaPattern[];
112
111
  memberNodeIndices?: CalcNodeIndex[];
113
112
  }
@@ -118,7 +117,7 @@ export interface IDynamicDependency {
118
117
  export interface IDynamicResolveResult {
119
118
  signature: string;
120
119
  cells?: CellId[];
121
- ranges?: IRefRange[];
120
+ ranges?: IUnitRange[];
122
121
  nodes?: ICalcNodeRef[];
123
122
  traceCells?: CellId[];
124
123
  status?: DynamicResolveStatus;
@@ -203,19 +202,3 @@ export declare enum RangeKind {
203
202
  /**
204
203
  * Backward-compatible type aliases for older imports.
205
204
  */
206
- export type CalcNodeRef = ICalcNodeRef;
207
- export type DecodedCell = IDecodedCell;
208
- export type DecodedFeatureCalculationId = IDecodedFeatureCalculationId;
209
- export type DecodedOtherFormulaId = IDecodedOtherFormulaId;
210
- export type DynamicDependency = IDynamicDependency;
211
- export type DynamicResolver = IDynamicResolver;
212
- export type DynamicResolveResult = IDynamicResolveResult;
213
- export type CompressedSharedFormulaGroup = ICompressedSharedFormulaGroup;
214
- export type CompressedSharedFormulaPattern = ICompressedSharedFormulaPattern;
215
- export type RefRange = IRefRange;
216
- export type CalcNodeDeps = ICalcNodeDeps;
217
- export type DependencyEngineOptions = IDependencyEngineOptions;
218
- export type SetNodeResult = ISetNodeResult;
219
- export type CalculationOrderResult = ICalculationOrderResult;
220
- export type CalculationPlanItem = ICalculationPlanItem;
221
- export type CalculationOrderTree = ICalculationOrderTree;
@@ -1,6 +1,6 @@
1
1
  import type { IUnitRange, Nullable } from '@univerjs/core';
2
2
  import type { BaseAstNode, IFormulaDataItem, IFormulaDependencyTree, IFormulaDependencyTreeJson, IUnitData } from '@univerjs/engine-formula';
3
- import type { DynamicResolver } from './dependency-engine/types';
3
+ import type { IDynamicResolver } from './dependency-engine/types';
4
4
  import type { ISharedFormulaCompressionMetrics } from './shared-formula-group-analyzer';
5
5
  import { FormulaDependencyGenerator, FormulaDependencyTree, FormulaDependencyTreeType } from '@univerjs/engine-formula';
6
6
  export interface IFormulaCalculationTree {
@@ -40,7 +40,7 @@ export declare class FormulaDependencyProGenerator extends FormulaDependencyGene
40
40
  getCalculationOrder(): import("./dependency-engine/types").ICalculationOrderResult;
41
41
  getSharedFormulaCompressionMetrics(): ISharedFormulaCompressionMetrics;
42
42
  hasDynamicDepsByIndex(nodeIndex: number): boolean;
43
- refreshDynamicDepsByIndex(nodeIndex: number, resolver: DynamicResolver): boolean;
43
+ refreshDynamicDepsByIndex(nodeIndex: number, resolver: IDynamicResolver): boolean;
44
44
  hasUncalculatedDirtyPrecedentByIndex(nodeIndex: number, calculatedNodeIndices: ReadonlySet<number>): boolean;
45
45
  getAllDependencyJson(): Promise<IFormulaDependencyTreeJson[]>;
46
46
  generatePro(isCalculateTreeModel?: boolean): Promise<{
@@ -24,7 +24,10 @@ export interface IFFormulaReferenceEnumMixin {
24
24
  * range: { startRow: 0, endRow: 9, startColumn: 0, endColumn: 1 },
25
25
  * },
26
26
  * });
27
- * shape.setFormula(`=SUM(${reference})`);
27
+ * shape.setFormula({
28
+ * formula: `=SUM(${reference})`,
29
+ * externalReferences: [], // Required; empty only because Source and Host are the same Unit.
30
+ * });
28
31
  * ```
29
32
  *
30
33
  * @example Select a Base table-column target
@@ -45,7 +48,14 @@ export interface IFFormulaReferenceEnumMixin {
45
48
  * columnName: 'Amount',
46
49
  * },
47
50
  * });
48
- * shape.setFormula(`=SUM(${reference})`);
51
+ * shape.setFormula({
52
+ * formula: `=SUM(${reference})`,
53
+ * externalReferences: [{
54
+ * qualifier: baseUnit.formulaQualifier,
55
+ * sourceUnitId: baseUnit.unitId,
56
+ * sourceUnitType: univerAPI.Enum.UniverInstanceType.UNIVER_BASE,
57
+ * }],
58
+ * });
49
59
  * }
50
60
  *
51
61
  * setSalesBaseFormula({
@@ -1,87 +1,137 @@
1
- import type { IBuildFormulaReferenceOptions } from '@univerjs-pro/engine-formula';
1
+ import type { IBuildFormulaReferenceOptions, IRemoveHostExternalReferenceCommandParams, IUpsertHostExternalReferenceCommandParams } from '@univerjs-pro/engine-formula';
2
2
  import { FFormula } from '@univerjs/engine-formula/facade';
3
3
  /** Formula-reference APIs contributed by Univer Pro. */
4
4
  export interface IFFormulaReferenceMixin {
5
5
  /**
6
- * Builds a Sheet-range or structured-table reference fragment.
6
+ * Builds one Sheet-range or Base-table reference fragment for Facade authoring.
7
7
  *
8
- * This is a pure text helper. It does not add a leading `=`, mutate a Shape,
9
- * discover or bind external resources, load a Unit, or start formula calculation.
8
+ * Use this method when the caller knows both the Host Unit ID and the stable
9
+ * Source Unit ID. For a cross-Unit Source, it synchronously persists the
10
+ * Host-owned External Reference before returning. For a Host-local Source, it
11
+ * only returns local reference syntax. An unchanged binding is an idempotent
12
+ * no-op.
13
+ *
14
+ * The returned value is a reference fragment, not a complete formula: it has no
15
+ * leading `=` and does not start calculation. The method does not load the Source
16
+ * Unit. Formula calculation later reads the Source through its stable `unitId`.
17
+ *
18
+ * Authoring rule:
19
+ * - Cell formula: build the reference, then pass the returned fragment to
20
+ * `range.setFormula(...)`; the binding has already been persisted.
21
+ * - Formula Shape: build the reference, then pass the same Source identity again
22
+ * in `shape.setFormula({ formula, externalReferences })`. The duplicate binding
23
+ * write is a no-op and the Shape setter remains the final consistency boundary.
24
+ * - Hand-written or imported formula text: call `upsertExternalReference()` before
25
+ * writing the formula because the engine never guesses `unitId` from a name.
10
26
  *
11
27
  * @param {IBuildFormulaReferenceOptions} options Host, caller-provided source Unit, and reference target.
12
28
  * @returns {string} A formula reference fragment.
13
29
  *
14
- * @example Build a cross-unit Sheet range from an externally supplied Unit
30
+ * @example Write a cross-Unit Sheet reference to a cell
15
31
  * ```ts
16
- * import type { IFormulaReferenceUnit } from '@univerjs-pro/engine-formula';
17
- *
18
- * function setSalesFormula(salesUnit: IFormulaReferenceUnit) {
19
- * const board = univerAPI.getActiveBoard();
20
- * if (!board) {
21
- * throw new Error('No active board.');
22
- * }
23
- *
24
- * const shape = board.getShape('formula-shape-1');
25
- * if (!shape?.isFormulaShape()) {
26
- * throw new Error('Formula Shape not found.');
27
- * }
28
- *
29
- * const reference = univerAPI.getFormula().buildReference({
30
- * hostUnitId: board.getId(),
31
- * unit: salesUnit,
32
- * target: {
33
- * kind: univerAPI.Enum.FormulaReferenceType.SHEET_RANGE,
34
- * sheetName: 'Sales',
35
- * range: { startRow: 1, endRow: 9, startColumn: 1, endColumn: 1 },
36
- * },
37
- * });
38
- * shape.setFormula(`=SUM(${reference})`);
39
- * }
40
- *
41
- * setSalesFormula({
32
+ * const workbook = univerAPI.getActiveWorkbook();
33
+ * if (!workbook) throw new Error('No active workbook.');
34
+ *
35
+ * const salesWorkbook = {
42
36
  * unitId: 'sales-workbook',
43
37
  * formulaQualifier: 'Sales Workbook',
38
+ * };
39
+ * const reference = univerAPI.getFormula().buildReference({
40
+ * hostUnitId: workbook.getId(),
41
+ * unit: salesWorkbook,
42
+ * target: {
43
+ * kind: univerAPI.Enum.FormulaReferenceType.SHEET_RANGE,
44
+ * sheetName: 'Sales',
45
+ * range: { startRow: 1, endRow: 9, startColumn: 1, endColumn: 1 },
46
+ * },
44
47
  * });
48
+ * workbook.getActiveSheet().getRange('C1').setFormula(`=SUM(${reference})`);
45
49
  * ```
46
50
  *
47
- * @example Build a cross-unit Base column from an externally supplied Unit
51
+ * @example Build a Host-local Sheet reference without creating a binding
48
52
  * ```ts
49
- * import type { IFormulaReferenceUnit } from '@univerjs-pro/engine-formula';
50
- *
51
- * function setSalesFormula(salesUnit: IFormulaReferenceUnit) {
52
- * const document = univerAPI.getActiveDocument();
53
- * if (!document) {
54
- * throw new Error('No active document.');
55
- * }
56
- *
57
- * const shape = document.getShape('formula-shape-1');
58
- * if (!shape?.isFormulaShape()) {
59
- * throw new Error('Formula Shape not found.');
60
- * }
61
- *
62
- * const reference = univerAPI.getFormula().buildReference({
63
- * hostUnitId: document.getId(),
64
- * unit: salesUnit,
65
- * target: {
66
- * kind: univerAPI.Enum.FormulaReferenceType.TABLE_COLUMN,
67
- * tableName: 'SalesTable',
68
- * columnName: 'Amount',
69
- * },
70
- * });
71
- * shape.setFormula(`=SUM(${reference})`);
72
- * }
73
- *
74
- * setSalesFormula({
75
- * unitId: 'sales-base',
76
- * formulaQualifier: 'Sales Base',
53
+ * const workbook = univerAPI.getActiveWorkbook();
54
+ * if (!workbook) throw new Error('No active workbook.');
55
+ *
56
+ * const reference = univerAPI.getFormula().buildReference({
57
+ * hostUnitId: workbook.getId(),
58
+ * unit: {
59
+ * unitId: workbook.getId(),
60
+ * formulaQualifier: workbook.getName(),
61
+ * },
62
+ * target: {
63
+ * kind: univerAPI.Enum.FormulaReferenceType.SHEET_RANGE,
64
+ * sheetName: 'Sales',
65
+ * range: { startRow: 1, endRow: 9, startColumn: 1, endColumn: 1 },
66
+ * },
77
67
  * });
68
+ * // reference contains local syntax such as Sales!B2:B10.
78
69
  * ```
79
70
  */
80
71
  buildReference(options: IBuildFormulaReferenceOptions): string;
72
+ /**
73
+ * Creates or rebinds one Host-owned External Reference.
74
+ *
75
+ * Use this explicit API when formula text is hand-written, imported, or generated
76
+ * in a batch without `buildReference()`. Call it before writing the formula.
77
+ * `qualifier` is the public name used inside the formula, without brackets or
78
+ * quotes; `sourceUnitId` is the stable identity used for data requests.
79
+ *
80
+ * Repeating the same mapping succeeds without mutation, dirty data, or undo.
81
+ *
82
+ * @param {IUpsertHostExternalReferenceCommandParams} options Host and stable Source binding.
83
+ * @returns {boolean} `true` when the binding already matches or was persisted.
84
+ *
85
+ * @example Bind a hand-written cross-workbook formula before writing it
86
+ * ```ts
87
+ * const workbook = univerAPI.getActiveWorkbook();
88
+ * if (!workbook) throw new Error('No active workbook.');
89
+ *
90
+ * const formula = univerAPI.getFormula();
91
+ * const bound = formula.upsertExternalReference({
92
+ * unitId: workbook.getId(),
93
+ * qualifier: 'Sales Workbook',
94
+ * sourceUnitId: 'sales-workbook',
95
+ * sourceUnitType: univerAPI.Enum.UniverInstanceType.UNIVER_SHEET,
96
+ * });
97
+ * if (!bound) throw new Error('Could not bind the Sales Workbook source.');
98
+ *
99
+ * workbook
100
+ * .getActiveSheet()
101
+ * .getRange('C1')
102
+ * .setFormula("=SUM('[Sales Workbook]Sales'!B2:B10)");
103
+ * ```
104
+ */
105
+ upsertExternalReference(options: IUpsertHostExternalReferenceCommandParams): boolean;
106
+ /**
107
+ * Removes one Host-owned External Reference by `referenceId` or `qualifier`.
108
+ *
109
+ * Removing a binding does not rewrite or delete formulas. It marks only the Host
110
+ * dirty; the next Host calculation resolves the remaining formula under the
111
+ * normal External Reference rules.
112
+ *
113
+ * @param {IRemoveHostExternalReferenceCommandParams} options Host plus reference ID or qualifier.
114
+ * @returns {boolean} `true` when an existing binding was removed.
115
+ *
116
+ * @example Remove a Host binding by qualifier
117
+ * ```ts
118
+ * const workbook = univerAPI.getActiveWorkbook();
119
+ * if (!workbook) throw new Error('No active workbook.');
120
+ *
121
+ * const removed = univerAPI.getFormula().removeExternalReference({
122
+ * unitId: workbook.getId(),
123
+ * qualifier: 'Sales Workbook',
124
+ * });
125
+ * if (!removed) throw new Error('External Reference was not found.');
126
+ * ```
127
+ */
128
+ removeExternalReference(options: IRemoveHostExternalReferenceCommandParams): boolean;
81
129
  }
82
130
  /** @ignore */
83
131
  export declare class FFormulaReferenceMixin extends FFormula implements IFFormulaReferenceMixin {
84
132
  buildReference(options: IBuildFormulaReferenceOptions): string;
133
+ upsertExternalReference(options: IUpsertHostExternalReferenceCommandParams): boolean;
134
+ removeExternalReference(options: IRemoveHostExternalReferenceCommandParams): boolean;
85
135
  }
86
136
  declare module '@univerjs/engine-formula/facade' {
87
137
  interface FFormula extends IFFormulaReferenceMixin {
@@ -1,3 +1,7 @@
1
+ export { buildUpsertHostExternalReferenceMutations, RemoveHostExternalReferenceCommand, UpsertHostExternalReferenceCommand, UpsertHostExternalReferencesCommand, } from './commands/commands/host-external-reference.command';
2
+ export type { IHostExternalReferenceMutationPair, IRemoveHostExternalReferenceCommandParams, IUpsertHostExternalReferenceCommandParams, IUpsertHostExternalReferencesCommandParams, } from './commands/commands/host-external-reference.command';
3
+ export { PersistFormulaLastValuesCommand } from './commands/commands/persist-formula-last-values.command';
4
+ export type { IPersistFormulaLastValuesCommandParams } from './commands/commands/persist-formula-last-values.command';
1
5
  export { ExternalReferenceDataProvidersController } from './controllers/external-reference-data-providers.controller';
2
6
  export { ExternalReferenceRenameController } from './controllers/external-reference-rename.controller';
3
7
  export { ExternalReferenceResourceController } from './controllers/external-reference-resource.controller';
@@ -6,16 +10,27 @@ export { ExternalReferenceOverlayModel } from './models/external-reference-overl
6
10
  export type { IExternalOverlayCellState } from './models/external-reference-overlay.model';
7
11
  export { createEmptyExternalReferenceResource, createExternalSyntheticUnitId, EXTERNAL_REFERENCE_SCHEMA_VERSION, ExternalReferenceModel, SHEET_EXTERNAL_DATA_PLUGIN, } from './models/external-reference.model';
8
12
  export type { ExternalReferenceBindingResult, IExternalReferenceCachedCell, IExternalReferenceCachedSheet, IExternalReferenceCoverage, IExternalReferenceLink, IExternalReferenceResource, IExternalReferenceTable, IExternalReferenceTableColumn, } from './models/external-reference.model';
13
+ export type { IFormulaLastValue } from './models/formula-last-value';
14
+ export { HOST_EXTERNAL_REFERENCE_SCHEMA_VERSION, HostExternalReferenceModel, normalizeHostExternalReferenceQualifier, UNIVER_EXTERNAL_REFERENCE_PLUGIN, } from './models/host-external-reference.model';
15
+ export type { HostExternalReferenceBindingResult, IHostExternalReference, IHostExternalReferenceResource, } from './models/host-external-reference.model';
9
16
  export { UniverProFormulaEnginePlugin } from './plugin';
10
17
  export { ExternalCacheReferenceDataProvider } from './services/external-cache-reference-data.provider';
11
18
  export { ExternalReferencePrefetchPlanner } from './services/external-reference-prefetch-planner';
12
19
  export { ExternalReferencePrefetchService } from './services/external-reference-prefetch.service';
13
20
  export type { IExternalReferencePrefetchLimits, IExternalReferencePrefetchResult, } from './services/external-reference-prefetch.service';
14
21
  export { ExternalFormulaUnitReferenceResolver } from './services/external-unit-reference-resolver.service';
22
+ export { FormulaCacheEligibilityService } from './services/formula-cache-eligibility.service';
23
+ export type { FormulaCacheIneligibleReason, IFormulaCacheEligibility, } from './services/formula-cache-eligibility.service';
24
+ export { FormulaLastValuePersistenceService } from './services/formula-last-value-persistence.service';
25
+ export type { IFormulaLastValuePersistenceProvider } from './services/formula-last-value-persistence.service';
15
26
  export { createUnavailableReferenceDataResponse, FormulaReferenceDataProviderRegistry, IFormulaReferenceDataProviderRegistry, IFormulaReferenceDataService, } from './services/formula-reference-data.service';
16
- export type { FormulaReferenceDataFreshness, FormulaReferenceDataSource, IFormulaReferenceDataCell, IFormulaReferenceDataProvider, IFormulaReferenceDataRangeRequest, IFormulaReferenceDataRequest, IFormulaReferenceDataResponse, IFormulaReferenceDataSheet, } from './services/formula-reference-data.service';
27
+ export type { FormulaReferenceDataFreshness, FormulaReferenceDataSource, IFormulaReferenceDataCell, IFormulaReferenceDataProvider, IFormulaReferenceDataRangeRequest, IFormulaReferenceDataRequest, IFormulaReferenceDataResponse, IFormulaReferenceDataSheet, IFormulaReferenceDataTable, } from './services/formula-reference-data.service';
17
28
  export { buildFormulaReference, FormulaReferenceType, } from './services/formula-reference-unit.service';
18
29
  export type { FormulaReferenceTarget, IBuildFormulaReferenceOptions, IFormulaReferenceUnit, IFormulaSheetRangeReferenceTarget, IFormulaTableColumnReferenceTarget, } from './services/formula-reference-unit.service';
30
+ export { getFormulaResultCell, getScalarFormulaResultCell, resolveFormulaResultPresentation, toFormulaLastValue, } from './services/formula-result-presentation';
31
+ export type { IFormulaResultPresentation, IResolveFormulaResultPresentationOptions, } from './services/formula-result-presentation';
32
+ export { collectFormulaExternalReferenceQualifiers, resolveHostFormulaExternalReferences, } from './services/host-formula-binding.service';
33
+ export type { HostFormulaExternalReferenceResolution, } from './services/host-formula-binding.service';
19
34
  export { MainFormulaReferenceDataService } from './services/main-formula-reference-data.service';
20
35
  export { RemoveSuperTableMutation, SetFormulaCalculationResultMutation, SetFormulaCalculationStartMutation, SetSuperTableMutation, SetTriggerFormulaCalculationStartMutation, } from '@univerjs/engine-formula';
21
36
  export type { ISetFormulaCalculationResultMutation, ISetFormulaCalculationStartMutation, ISuperTable, } from '@univerjs/engine-formula';
@@ -0,0 +1,14 @@
1
+ import type { CellValueType } from '@univerjs/core';
2
+ /**
3
+ * Minimal snapshot projection of the last successful scalar Formula result.
4
+ *
5
+ * This value is Host content. It intentionally excludes formula text, source bindings,
6
+ * display text, color, timestamps, calculation hashes, and all Source ACL metadata.
7
+ * It inherits only the Host object's persistence and read-permission boundary.
8
+ */
9
+ export interface IFormulaLastValue {
10
+ v: string | number | boolean | null;
11
+ t?: CellValueType;
12
+ /** Number format inherited from the successful result cell. */
13
+ pattern?: string;
14
+ }