diff --git a/packages/engine-formula/src/commands/mutations/set-formula-calculation.mutation.ts b/packages/engine-formula/src/commands/mutations/set-formula-calculation.mutation.ts index 804ce5a5ef..cda13bebea 100644 --- a/packages/engine-formula/src/commands/mutations/set-formula-calculation.mutation.ts +++ b/packages/engine-formula/src/commands/mutations/set-formula-calculation.mutation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { IExecutionOptions, IMutation, Nullable } from '@univerjs/core'; +import type { IExecutionOptions, IMutation, IUnitRange, Nullable } from '@univerjs/core'; import type { IFormulaExecuteResultMap, IFormulaStringMap, @@ -58,6 +58,15 @@ export interface ISetCellFormulaDependencyCalculationResultMutation { result: IFormulaDependencyTreeFullJson | undefined; } +export interface ISetQueryFormulaDependencyMutation { + unitRanges: IUnitRange[]; + isInRange?: boolean; +} + +export interface ISetQueryFormulaDependencyResultMutation { + result: IFormulaDependencyTreeJson[]; +} + /** * TODO: @DR-Univer * Trigger the calculation of the formula and stop the formula @@ -134,3 +143,15 @@ export const SetCellFormulaDependencyCalculationResultMutation: IMutation true, }; + +export const SetQueryFormulaDependencyMutation: IMutation = { + id: 'formula.mutation.set-query-formula-dependency', + type: CommandType.MUTATION, + handler: () => true, +}; + +export const SetQueryFormulaDependencyResultMutation: IMutation = { + id: 'formula.mutation.set-query-formula-dependency-result', + type: CommandType.MUTATION, + handler: () => true, +}; diff --git a/packages/engine-formula/src/controller/calculate.controller.ts b/packages/engine-formula/src/controller/calculate.controller.ts index e4ee7d5e14..acb698169f 100644 --- a/packages/engine-formula/src/controller/calculate.controller.ts +++ b/packages/engine-formula/src/controller/calculate.controller.ts @@ -16,7 +16,8 @@ import type { ICommandInfo } from '@univerjs/core'; import type { ISetArrayFormulaDataMutationParams } from '../commands/mutations/set-array-formula-data.mutation'; -import type { ISetFormulaCalculationStartMutation, ISetFormulaDependencyCalculationMutation, ISetFormulaStringBatchCalculationMutation } from '../commands/mutations/set-formula-calculation.mutation'; +import type { ISetFormulaCalculationStartMutation, ISetFormulaDependencyCalculationMutation, ISetFormulaStringBatchCalculationMutation, ISetQueryFormulaDependencyMutation } from '../commands/mutations/set-formula-calculation.mutation'; +import type { IFormulaDependencyTreeJson } from '../engine/dependency/dependency-tree'; import type { IFormulaDirtyData } from '../services/current-data.service'; import type { IAllRuntimeData } from '../services/runtime.service'; import { Disposable, ICommandService, Inject } from '@univerjs/core'; @@ -33,6 +34,8 @@ import { SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation, + SetQueryFormulaDependencyMutation, + SetQueryFormulaDependencyResultMutation, } from '../commands/mutations/set-formula-calculation.mutation'; import { SetImageFormulaDataMutation } from '../commands/mutations/set-image-formula-data.mutation'; import { FormulaDataModel } from '../models/formula-data.model'; @@ -79,6 +82,9 @@ export class CalculateController extends Disposable { this._generateAllDependencyTreeJson(); } else if (command.id === SetCellFormulaDependencyCalculationMutation.id) { this._generateCellDependencyTreeJson(command.params as ISetFormulaDependencyCalculationMutation); + } else if (command.id === SetQueryFormulaDependencyMutation.id) { + const params = command.params as ISetQueryFormulaDependencyMutation; + this._queryFormulaDependencyJson(params); } }) ); @@ -110,6 +116,26 @@ export class CalculateController extends Disposable { }); } + private async _queryFormulaDependencyJson(param: ISetQueryFormulaDependencyMutation) { + const { unitRanges, isInRange } = param; + let result: IFormulaDependencyTreeJson[] = []; + if (isInRange) { + result = await this._calculateFormulaService.getInRangeFormulas(unitRanges); + } else { + result = await this._calculateFormulaService.getRangeDependents(unitRanges); + } + + this._commandService.executeCommand( + SetQueryFormulaDependencyResultMutation.id, + { + result, + }, + { + onlyLocal: true, + } + ); + } + private async _generateAllDependencyTreeJson() { const result = await this._calculateFormulaService.getAllDependencyJson(); @@ -139,20 +165,10 @@ export class CalculateController extends Disposable { ); } - private async _calculateFormulaString(params: ISetFormulaStringBatchCalculationMutation) { - const formulaData = this._formulaDataModel.getFormulaData(); - const arrayFormulaCellData = this._formulaDataModel.getArrayFormulaCellData(); - // array formula range is used to check whether the newly added array formula conflicts with the existing array formula - const arrayFormulaRange = this._formulaDataModel.getArrayFormulaRange(); - - const rowData = this._formulaDataModel.getHiddenRowsFiltered(); - + private async _calculateFormulaString(param: ISetFormulaStringBatchCalculationMutation) { + const { formulas } = param; const result = await this._calculateFormulaService.executeFormulas( - params.formulas, - formulaData, - arrayFormulaCellData, - arrayFormulaRange, - rowData + formulas ); this._commandService.executeCommand( diff --git a/packages/engine-formula/src/controller/formula.controller.ts b/packages/engine-formula/src/controller/formula.controller.ts index 31fdf567b0..972177987b 100644 --- a/packages/engine-formula/src/controller/formula.controller.ts +++ b/packages/engine-formula/src/controller/formula.controller.ts @@ -35,6 +35,8 @@ import { SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation, + SetQueryFormulaDependencyMutation, + SetQueryFormulaDependencyResultMutation, } from '../commands/mutations/set-formula-calculation.mutation'; import { SetFormulaDataMutation } from '../commands/mutations/set-formula-data.mutation'; import { SetImageFormulaDataMutation } from '../commands/mutations/set-image-formula-data.mutation'; @@ -84,6 +86,8 @@ export class FormulaController extends Disposable { SetFormulaCalculationStartMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation, + SetQueryFormulaDependencyMutation, + SetQueryFormulaDependencyResultMutation, SetFormulaCalculationStopMutation, SetFormulaCalculationNotificationMutation, SetFormulaCalculationResultMutation, diff --git a/packages/engine-formula/src/engine/dependency/formula-dependency.ts b/packages/engine-formula/src/engine/dependency/formula-dependency.ts index b5c1cdf122..683e2993ce 100644 --- a/packages/engine-formula/src/engine/dependency/formula-dependency.ts +++ b/packages/engine-formula/src/engine/dependency/formula-dependency.ts @@ -59,6 +59,8 @@ export interface IFormulaDependencyGenerator { generate(): Promise; getAllDependencyJson(): Promise; getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number): Promise; + getRangeDependents(unitRanges: IUnitRange[]): Promise; + getInRangeFormulas(unitRanges: IUnitRange[]): Promise; } export const IFormulaDependencyGenerator = createIdentifier('engine-formula.dependency-generator'); @@ -1411,26 +1413,28 @@ export class FormulaDependencyGenerator extends Disposable { this._startFormulaDependencyTreeModel(); const treeModel = this._getFormulaDependencyTreeModel(tree); - const formula = this._lexerTreeBuilder.moveFormulaRefOffset( - tree.formula, - tree.refOffsetX, - tree.refOffsetY - ); - treeModel.formula = formula; - - const childIds = this._getDependencyTreeChildrenIds(tree); - for (const childId of childIds) { - const childTreeModel = this._getTreeModel(childId); - const tree = this._getTreeById(treeId); - if (!tree) { - continue; - } + if (tree.isVirtual) { const formula = this._lexerTreeBuilder.moveFormulaRefOffset( tree.formula, tree.refOffsetX, tree.refOffsetY ); - childTreeModel.formula = formula; + treeModel.formula = formula; + } + + const childIds = this._getDependencyTreeChildrenIds(tree); + for (const childId of childIds) { + const childTreeModel = this._getTreeModel(childId); + const tree = this._getTreeById(childId); + if (tree && tree.isVirtual) { + const formula = this._lexerTreeBuilder.moveFormulaRefOffset( + tree.formula, + tree.refOffsetX, + tree.refOffsetY + ); + childTreeModel.formula = formula; + } + treeModel.addChild(childTreeModel); } @@ -1438,4 +1442,88 @@ export class FormulaDependencyGenerator extends Disposable { return treeModel.toFullJson(); } + + async getRangeDependents(unitRanges: IUnitRange[]): Promise { + await this._initializeGenerateTreeList(); + + this._startFormulaDependencyTreeModel(); + + const treeIds = this._dependencyManagerService.searchDependency(unitRanges); + const treeList: FormulaDependencyTreeModel[] = []; + for (const treeId of treeIds) { + const tree = this._getTreeById(treeId); + if (!tree) { + continue; + } + const treeModel = this._getFormulaDependencyTreeModel(tree); + if (tree.isVirtual) { + const formula = this._lexerTreeBuilder.moveFormulaRefOffset( + tree.formula, + tree.refOffsetX, + tree.refOffsetY + ); + treeModel.formula = formula; + } + treeList.push(treeModel); + } + + const resultsJson: IFormulaDependencyTreeJson[] = []; + for (const result of treeList) { + if (result) { + resultsJson.push(result.toJson()); + } + } + + this._endFormulaDependencyTreeModel(); + + return resultsJson; + } + + async getInRangeFormulas(unitRanges: IUnitRange[]): Promise { + const treeList = await this._getAllTreeList(); + const matchTreeList: IFormulaDependencyTree[] = []; + for (const dependencyTree of treeList) { + for (const unitRange of unitRanges) { + const unitId = unitRange.unitId; + const sheetId = unitRange.sheetId; + if (dependencyTree.unitId !== unitId || dependencyTree.subUnitId !== sheetId) { + continue; + } + + const range = unitRange.range; + + if (dependencyTree.inRangeData(unitRange.range)) { + matchTreeList.push(dependencyTree); + break; + } + } + } + + this._startFormulaDependencyTreeModel(); + + const results: FormulaDependencyTreeModel[] = []; + for (const tree of matchTreeList) { + const treeModel = this._getFormulaDependencyTreeModel(tree); + if (tree.isVirtual) { + const formula = this._lexerTreeBuilder.moveFormulaRefOffset( + tree.formula, + tree.refOffsetX, + tree.refOffsetY + ); + treeModel.formula = formula; + } + results[tree.treeId] = treeModel; + } + + const resultsJson: IFormulaDependencyTreeJson[] = []; + for (const result of results) { + if (result) { + resultsJson.push(result.toJson()); + } + } + + this._endFormulaDependencyTreeModel(); + + return resultsJson; + } } diff --git a/packages/engine-formula/src/facade/f-formula.ts b/packages/engine-formula/src/facade/f-formula.ts index 84a9ea268f..4d52652b41 100644 --- a/packages/engine-formula/src/facade/f-formula.ts +++ b/packages/engine-formula/src/facade/f-formula.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import type { ICommandInfo, IDisposable } from '@univerjs/core'; -import type { FormulaExecutedStateType, IExecutionInProgressParams, IFormulaDependencyTreeFullJson, IFormulaDependencyTreeJson, IFormulaExecuteResultMap, IFormulaStringMap, ISequenceNode, ISetCellFormulaDependencyCalculationResultMutation, ISetFormulaCalculationNotificationMutation, ISetFormulaCalculationStartMutation, ISetFormulaDependencyCalculationResultMutation, ISetFormulaStringBatchCalculationResultMutation } from '@univerjs/engine-formula'; +import type { ICommandInfo, IDisposable, IUnitRange } from '@univerjs/core'; +import type { FormulaExecutedStateType, IExecutionInProgressParams, IFormulaDependencyTreeFullJson, IFormulaDependencyTreeJson, IFormulaExecuteResultMap, IFormulaStringMap, ISequenceNode, ISetCellFormulaDependencyCalculationResultMutation, ISetFormulaCalculationNotificationMutation, ISetFormulaCalculationResultMutation, ISetFormulaCalculationStartMutation, ISetFormulaDependencyCalculationResultMutation, ISetFormulaStringBatchCalculationResultMutation } from '@univerjs/engine-formula'; import { ICommandService, IConfigService, Inject, Injector } from '@univerjs/core'; import { FBase } from '@univerjs/core/facade'; -import { ENGINE_FORMULA_CYCLE_REFERENCE_COUNT, GlobalComputingStatusService, LexerTreeBuilder, SetCellFormulaDependencyCalculationMutation, SetCellFormulaDependencyCalculationResultMutation, SetFormulaCalculationNotificationMutation, SetFormulaCalculationStartMutation, SetFormulaCalculationStopMutation, SetFormulaDependencyCalculationMutation, SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation } from '@univerjs/engine-formula'; +import { ENGINE_FORMULA_CYCLE_REFERENCE_COUNT, GlobalComputingStatusService, LexerTreeBuilder, SetCellFormulaDependencyCalculationMutation, SetCellFormulaDependencyCalculationResultMutation, SetFormulaCalculationNotificationMutation, SetFormulaCalculationResultMutation, SetFormulaCalculationStartMutation, SetFormulaCalculationStopMutation, SetFormulaDependencyCalculationMutation, SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation, SetQueryFormulaDependencyMutation, SetQueryFormulaDependencyResultMutation } from '@univerjs/engine-formula'; import { filter, firstValueFrom, map, race, timer } from 'rxjs'; /** @@ -249,6 +249,120 @@ export class FFormula extends FBase { this._configService.setConfig(ENGINE_FORMULA_CYCLE_REFERENCE_COUNT, maxIteration); } + /** + * Listens for the moment when formula-calculation results are applied. + * + * This event fires after the engine completes a calculation cycle and + * dispatches a `SetFormulaCalculationResultMutation`. + * The callback is invoked during an idle frame to avoid blocking UI updates. + * + * @param {Function} callback - A function called with the calculation result payload + * once the result-application mutation is emitted. + * @returns {IDisposable} A disposable used to unsubscribe from the event. + * + * @example + * ```ts + * const formulaEngine = univerAPI.getFormula(); + * + * const dispose = formulaEngine.calculationResultApplied((result) => { + * console.log('Calculation results applied:', result); + * }); + * + * // Later… + * dispose.dispose(); + * ``` + */ + calculationResultApplied(callback: (result: ISetFormulaCalculationResultMutation) => void): IDisposable { + return this._commandService.onCommandExecuted((command: ICommandInfo) => { + if (command.id !== SetFormulaCalculationResultMutation.id) { + return; + } + + const params = command.params as ISetFormulaCalculationResultMutation; + + if (params !== undefined) { + requestIdleCallback(() => { + callback(params); + }); + } + }); + } + + /** + * Waits for formula-calculation results to be applied. + * + * This method resolves under three conditions: + * 1. A real calculation runs and the engine emits a "calculation started" signal, + * followed by a "calculation result applied" signal. + * 2. No calculation actually starts within 500 ms — the method assumes there is + * nothing to wait for and resolves automatically. + * 3. A global 30 s timeout triggers, in which case the promise rejects. + * + * The API internally listens to both “calculation in progress” events and + * “calculation result applied” events, ensuring it behaves correctly whether + * formulas are recalculated or skipped due to cache/state. + * + * @returns {Promise} A promise that resolves when calculation results are applied + * or when no calculation occurs within the start-detection window. + * + * @example + * ```ts + * const formulaEngine = univerAPI.getFormula(); + * + * // Wait for formula updates to apply before reading values. + * await formulaEngine.onCalculationResultApplied(); + * + * const value = sheet.getRange("C24").getValue(); + * console.log("Updated value:", value); + * ``` + */ + onCalculationResultApplied(): Promise { + return new Promise((resolve, reject) => { + let started = false; + let finished = false; + + // Global timeout: reject if the whole calculation hangs + const mainTimer = setTimeout(() => { + cleanup(); + reject(new Error('Calculation end timeout')); + }, 30_000); + + // Watchdog: if no "calculation started" signal is received within 500ms, + // assume there is no real calculation running and resolve immediately. + const startWatchdog = setTimeout(() => { + if (!started) { + cleanup(); + resolve(); + } + }, 500); + + // Listen for "calculation in progress" signal (stageInfo) + const processingDisposable = this.calculationProcessing(() => { + if (started) return; + started = true; + + // A start signal is received → no need for the watchdog anymore + clearTimeout(startWatchdog); + }); + + // Listen for the "calculation completed" signal + const endDisposable = this.calculationResultApplied(() => { + if (finished) return; + finished = true; + + cleanup(); + resolve(); + }); + + function cleanup(): void { + clearTimeout(mainTimer); + clearTimeout(startWatchdog); + processingDisposable.dispose(); + endDisposable.dispose(); + } + }); + } + /** * Execute a batch of formulas asynchronously and receive computed results. * @@ -417,4 +531,99 @@ export class FFormula extends FBase { disposable.dispose(); }); } + + /** + * Retrieve the full dependency trees for all formulas that *depend on* the + * specified ranges. This triggers a local dependency-calculation command and + * invokes the callback once the calculation completes. + * + * @param unitRanges An array of workbook/sheet ranges to query. Each range + * includes: + * - `unitId` The workbook ID. + * - `sheetId` The sheet ID. + * - `range` The row/column boundaries. + * + * @param callback A function invoked with an array of `IFormulaDependencyTreeJson` + * results. Each entry represents a formula node and its parent/child + * relationships within the dependency graph. + * + * @example + * ```ts + * const formulaEngine = univerAPI.getFormula(); + * + * // Query all formulas that depend on A1:B10 in Sheet1. + * formulaEngine.getRangeDependents( + * [{ unitId: 'workbook1', sheetId: 'sheet1', range: { startRow: 0, endRow: 9, startColumn: 0, endColumn: 1 } }], + * (result) => { + * console.log('Dependent formulas:', result); + * } + * ); + * ``` + */ + getRangeDependents(unitRanges: IUnitRange[], callback: (result: IFormulaDependencyTreeJson[]) => void): void { + this._commandService.executeCommand(SetQueryFormulaDependencyMutation.id, { unitRanges }, { onlyLocal: true }); + + const disposable = this._commandService.onCommandExecuted((command: ICommandInfo) => { + if (command.id !== SetQueryFormulaDependencyResultMutation.id) { + return; + } + + const params = command.params as ISetFormulaDependencyCalculationResultMutation; + + if (params.result != null) { + callback(params.result); + } + + disposable.dispose(); + }); + } + + /** + * Retrieve the dependency trees of all formulas *inside* the specified ranges. + * Unlike `getRangeDependents`, this API only returns formulas whose definitions + * physically reside within the queried ranges. + * + * Internally this triggers the same dependency-calculation command but with + * `isInRange = true`, and the callback is invoked when the results are ready. + * + * @param unitRanges An array of workbook/sheet ranges defining the lookup + * boundaries: + * - `unitId` The workbook ID. + * - `sheetId` The sheet ID. + * - `range` The zero-based grid range. + * + * @param callback Receives an array of `IFormulaDependencyTreeJson` describing + * every formula found in the provided ranges along with their parent/child + * relationships. + * + * @example + * ```ts + * const formulaEngine = univerAPI.getFormula(); + * + * // Query all formulas that lie within A1:D20 in Sheet1. + * formulaEngine.getInRangeFormulas( + * [{ unitId: 'workbook1', sheetId: 'sheet1', range: { startRow: 0, endRow: 19, startColumn: 0, endColumn: 3 } }], + * (result) => { + * console.log('Formulas inside range:', result); + * } + * ); + * ``` + */ + getInRangeFormulas(unitRanges: IUnitRange[], callback: (result: IFormulaDependencyTreeJson[]) => void): void { + this._commandService.executeCommand(SetQueryFormulaDependencyMutation.id, { unitRanges, isInRange: true }, { onlyLocal: true }); + + const disposable = this._commandService.onCommandExecuted((command: ICommandInfo) => { + if (command.id !== SetQueryFormulaDependencyResultMutation.id) { + return; + } + + const params = command.params as ISetFormulaDependencyCalculationResultMutation; + + if (params.result != null) { + callback(params.result); + } + + disposable.dispose(); + }); + } } diff --git a/packages/engine-formula/src/index.ts b/packages/engine-formula/src/index.ts index e044dfffa1..59ed8f6c0d 100644 --- a/packages/engine-formula/src/index.ts +++ b/packages/engine-formula/src/index.ts @@ -62,6 +62,7 @@ export { type ISetFormulaDependencyCalculationMutation, type ISetFormulaDependencyCalculationResultMutation, type ISetFormulaStringBatchCalculationResultMutation, + type ISetQueryFormulaDependencyResultMutation, SetCellFormulaDependencyCalculationMutation, SetCellFormulaDependencyCalculationResultMutation, SetFormulaCalculationNotificationMutation, @@ -72,6 +73,8 @@ export { SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation, + SetQueryFormulaDependencyMutation, + SetQueryFormulaDependencyResultMutation, } from './commands/mutations/set-formula-calculation.mutation'; export { type ISetFormulaDataMutationParams, SetFormulaDataMutation } from './commands/mutations/set-formula-data.mutation'; export { type ISetImageFormulaDataMutationParams, SetImageFormulaDataMutation } from './commands/mutations/set-image-formula-data.mutation'; diff --git a/packages/engine-formula/src/services/calculate-formula.service.ts b/packages/engine-formula/src/services/calculate-formula.service.ts index 7c47800059..3e489bd58f 100644 --- a/packages/engine-formula/src/services/calculate-formula.service.ts +++ b/packages/engine-formula/src/services/calculate-formula.service.ts @@ -18,9 +18,7 @@ import type { IUnitRange } from '@univerjs/core'; import type { Observable } from 'rxjs'; import type { IArrayFormulaRangeType, - IArrayFormulaUnitCellType, IFeatureDirtyRangeType, - IFormulaData, IFormulaDatasetConfig, IFormulaExecuteResultItem, IFormulaExecuteResultMap, @@ -74,9 +72,11 @@ export interface ICalculateFormulaService { execute(formulaDatasetConfig: IFormulaDatasetConfig): Promise; stopFormulaExecution(): void; calculate(formulaString: string, transformSuffix?: boolean): void; - executeFormulas(formulas: IFormulaStringMap, formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData: IUnitRowData): Promise; - getAllDependencyJson(): Promise; - getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number): Promise; + executeFormulas(formulas: IFormulaStringMap, rowData?: IUnitRowData): Promise; + getAllDependencyJson(rowData?: IUnitRowData): Promise; + getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number, rowData?: IUnitRowData): Promise; + getRangeDependents(unitRanges: IUnitRange[]): Promise; + getInRangeFormulas(unitRanges: IUnitRange[]): Promise; } export const ICalculateFormulaService = createIdentifier('engine-formula.calculate-formula.service'); @@ -378,11 +378,8 @@ export class CalculateFormulaService extends Disposable implements ICalculateFor return this._runtimeService.getAllRuntimeData(); } - async executeFormulas(formulas: IFormulaStringMap, formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData?: IUnitRowData) { + async executeFormulas(formulas: IFormulaStringMap, rowData?: IUnitRowData) { this._currentConfigService.loadDataLite( - formulaData, - arrayFormulaCellData, - arrayFormulaRange, rowData ); @@ -515,10 +512,22 @@ export class CalculateFormulaService extends Disposable implements ICalculateFor } async getAllDependencyJson(): Promise { + this._currentConfigService.loadDataLite(); return this._formulaDependencyGenerator.getAllDependencyJson(); } async getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number): Promise { + this._currentConfigService.loadDataLite(); return this._formulaDependencyGenerator.getCellDependencyJson(unitId, sheetId, row, column); } + + async getRangeDependents(unitRanges: IUnitRange[]): Promise { + this._currentConfigService.loadDataLite(); + return this._formulaDependencyGenerator.getRangeDependents(unitRanges); + } + + async getInRangeFormulas(unitRanges: IUnitRange[]): Promise { + this._currentConfigService.loadDataLite(); + return this._formulaDependencyGenerator.getInRangeFormulas(unitRanges); + } } diff --git a/packages/engine-formula/src/services/current-data.service.ts b/packages/engine-formula/src/services/current-data.service.ts index 1b3b82242d..bb7e70d93b 100644 --- a/packages/engine-formula/src/services/current-data.service.ts +++ b/packages/engine-formula/src/services/current-data.service.ts @@ -17,7 +17,6 @@ import type { IUnitRange, LocaleType, Nullable, Workbook } from '@univerjs/core'; import type { IArrayFormulaRangeType, - IArrayFormulaUnitCellType, IDirtyUnitFeatureMap, IDirtyUnitOtherFormulaMap, IDirtyUnitSheetDefinedNameMap, @@ -115,7 +114,7 @@ export interface IFormulaCurrentConfigService { setSheetNameMap(sheetIdToNameMap: IUnitSheetIdToNameMap): void; - loadDataLite(formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData?: IUnitRowData): void; + loadDataLite(rowData?: IUnitRowData): void; } export class FormulaCurrentConfigService extends Disposable implements IFormulaCurrentConfigService { @@ -348,7 +347,7 @@ export class FormulaCurrentConfigService extends Disposable implements IFormulaC this._mergeNameMap(this._sheetNameMap, this._dirtyNameMap); } - loadDataLite(formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData?: IUnitRowData) { + loadDataLite(rowData?: IUnitRowData) { const { allUnitData, unitSheetNameMap, unitStylesData } = this._loadSheetData(); this._unitData = allUnitData; @@ -357,11 +356,9 @@ export class FormulaCurrentConfigService extends Disposable implements IFormulaC this._sheetNameMap = unitSheetNameMap; - this._formulaData = formulaData; - - this._arrayFormulaCellData = convertUnitDataToRuntime(arrayFormulaCellData); - - this._arrayFormulaRange = arrayFormulaRange; + this._formulaData = this._formulaDataModel.getFormulaData(); + this._arrayFormulaCellData = convertUnitDataToRuntime(this._formulaDataModel.getArrayFormulaCellData()); + this._arrayFormulaRange = this._formulaDataModel.getArrayFormulaRange(); // apply row data, including rows hidden by filters rowData && this._applyUnitRowData(rowData);