mirror of
https://github.com/dream-num/univer.git
synced 2026-08-29 07:13:59 +08:00
feat(formula): dependency tree and calculation api (#6258)
This commit is contained in:
@@ -146,6 +146,19 @@ export interface IFormulaIdMap {
|
||||
c: number;
|
||||
}
|
||||
|
||||
export interface IFormulaStringMap {
|
||||
[unitId: string]: Nullable<{ [sheetId: string]: IObjectMatrixPrimitiveType<string[]> }>;
|
||||
}
|
||||
|
||||
export interface IFormulaExecuteResultItem {
|
||||
value: Nullable<number | string | boolean | Array<Array<number | string | boolean | null>>>;
|
||||
formula: string;
|
||||
}
|
||||
|
||||
export interface IFormulaExecuteResultMap {
|
||||
[unitId: string]: Nullable<{ [sheetId: string]: IObjectMatrixPrimitiveType<IFormulaExecuteResultItem[]> }>;
|
||||
}
|
||||
|
||||
export interface IFormulaIdMapData {
|
||||
[unitId: string]: Nullable<{ [subUnitId: string]: Nullable<{ [formulaId: string]: IFormulaIdMap }> }>;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
import type { IExecutionOptions, IMutation, Nullable } from '@univerjs/core';
|
||||
import type {
|
||||
IFormulaExecuteResultMap,
|
||||
IFormulaStringMap,
|
||||
IRuntimeOtherUnitDataType,
|
||||
IRuntimeUnitDataPrimitiveType,
|
||||
} from '../../basics/common';
|
||||
|
||||
import type { IFormulaDependencyTreeFullJson, IFormulaDependencyTreeJson } from '../../engine/dependency/dependency-tree';
|
||||
import type { IFormulaDirtyData } from '../../services/current-data.service';
|
||||
import type { FormulaExecutedStateType, IExecutionInProgressParams } from '../../services/runtime.service';
|
||||
import { CommandType } from '@univerjs/core';
|
||||
@@ -27,6 +30,34 @@ import { CommandType } from '@univerjs/core';
|
||||
export interface ISetFormulaCalculationStartMutation extends IFormulaDirtyData {
|
||||
options: Nullable<IExecutionOptions>;
|
||||
}
|
||||
|
||||
export interface ISetFormulaStringBatchCalculationMutation {
|
||||
formulas: IFormulaStringMap;
|
||||
}
|
||||
|
||||
export interface ISetFormulaStringBatchCalculationResultMutation {
|
||||
result: IFormulaExecuteResultMap;
|
||||
}
|
||||
|
||||
export interface ISetFormulaStringBatchCalculationResultMutation {
|
||||
result: IFormulaExecuteResultMap;
|
||||
}
|
||||
|
||||
export interface ISetFormulaDependencyCalculationMutation {
|
||||
unitId: string;
|
||||
sheetId: string;
|
||||
row: number;
|
||||
column: number;
|
||||
}
|
||||
|
||||
export interface ISetFormulaDependencyCalculationResultMutation {
|
||||
result: IFormulaDependencyTreeJson[];
|
||||
}
|
||||
|
||||
export interface ISetCellFormulaDependencyCalculationResultMutation {
|
||||
result: IFormulaDependencyTreeFullJson | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: @DR-Univer
|
||||
* Trigger the calculation of the formula and stop the formula
|
||||
@@ -37,7 +68,19 @@ export const SetFormulaCalculationStartMutation: IMutation<ISetFormulaCalculatio
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
export interface ISetFormulaCalculationStopMutation {}
|
||||
export const SetFormulaStringBatchCalculationMutation: IMutation<ISetFormulaStringBatchCalculationMutation> = {
|
||||
id: 'formula.mutation.set-formula-string-batch-calculation',
|
||||
type: CommandType.MUTATION,
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
export const SetFormulaStringBatchCalculationResultMutation: IMutation<ISetFormulaStringBatchCalculationResultMutation> = {
|
||||
id: 'formula.mutation.set-formula-string-batch-calculation-result',
|
||||
type: CommandType.MUTATION,
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
export interface ISetFormulaCalculationStopMutation { }
|
||||
|
||||
export const SetFormulaCalculationStopMutation: IMutation<ISetFormulaCalculationStopMutation> = {
|
||||
id: 'formula.mutation.set-formula-calculation-stop',
|
||||
@@ -67,3 +110,27 @@ export const SetFormulaCalculationResultMutation: IMutation<ISetFormulaCalculati
|
||||
type: CommandType.MUTATION,
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
export const SetFormulaDependencyCalculationMutation: IMutation<{}> = {
|
||||
id: 'formula.mutation.set-formula-dependency-calculation',
|
||||
type: CommandType.MUTATION,
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
export const SetFormulaDependencyCalculationResultMutation: IMutation<ISetFormulaDependencyCalculationResultMutation> = {
|
||||
id: 'formula.mutation.set-formula-dependency-calculation-result',
|
||||
type: CommandType.MUTATION,
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
export const SetCellFormulaDependencyCalculationMutation: IMutation<ISetFormulaDependencyCalculationMutation> = {
|
||||
id: 'formula.mutation.set-cell-formula-dependency-calculation',
|
||||
type: CommandType.MUTATION,
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
export const SetCellFormulaDependencyCalculationResultMutation: IMutation<ISetCellFormulaDependencyCalculationResultMutation> = {
|
||||
id: 'formula.mutation.set-cell-formula-dependency-calculation-result',
|
||||
type: CommandType.MUTATION,
|
||||
handler: () => true,
|
||||
};
|
||||
|
||||
@@ -16,17 +16,23 @@
|
||||
|
||||
import type { ICommandInfo } from '@univerjs/core';
|
||||
import type { ISetArrayFormulaDataMutationParams } from '../commands/mutations/set-array-formula-data.mutation';
|
||||
import type { ISetFormulaCalculationStartMutation } from '../commands/mutations/set-formula-calculation.mutation';
|
||||
import type { ISetFormulaCalculationStartMutation, ISetFormulaDependencyCalculationMutation, ISetFormulaStringBatchCalculationMutation } from '../commands/mutations/set-formula-calculation.mutation';
|
||||
import type { IFormulaDirtyData } from '../services/current-data.service';
|
||||
import type { IAllRuntimeData } from '../services/runtime.service';
|
||||
import { Disposable, ICommandService, Inject } from '@univerjs/core';
|
||||
import { convertRuntimeToUnitData } from '../basics/runtime';
|
||||
import { SetArrayFormulaDataMutation } from '../commands/mutations/set-array-formula-data.mutation';
|
||||
import {
|
||||
SetCellFormulaDependencyCalculationMutation,
|
||||
SetCellFormulaDependencyCalculationResultMutation,
|
||||
SetFormulaCalculationNotificationMutation,
|
||||
SetFormulaCalculationResultMutation,
|
||||
SetFormulaCalculationStartMutation,
|
||||
SetFormulaCalculationStopMutation,
|
||||
SetFormulaDependencyCalculationMutation,
|
||||
SetFormulaDependencyCalculationResultMutation,
|
||||
SetFormulaStringBatchCalculationMutation,
|
||||
SetFormulaStringBatchCalculationResultMutation,
|
||||
} from '../commands/mutations/set-formula-calculation.mutation';
|
||||
import { SetImageFormulaDataMutation } from '../commands/mutations/set-image-formula-data.mutation';
|
||||
import { FormulaDataModel } from '../models/formula-data.model';
|
||||
@@ -67,6 +73,12 @@ export class CalculateController extends Disposable {
|
||||
// TODO@Dushusir: Merge the array formula data into the formulaDataModel
|
||||
this._formulaDataModel.setArrayFormulaRange(arrayFormulaRange);
|
||||
this._formulaDataModel.setArrayFormulaCellData(arrayFormulaCellData);
|
||||
} else if (command.id === SetFormulaStringBatchCalculationMutation.id) {
|
||||
this._calculateFormulaString(command.params as ISetFormulaStringBatchCalculationMutation);
|
||||
} else if (command.id === SetFormulaDependencyCalculationMutation.id) {
|
||||
this._generateAllDependencyTreeJson();
|
||||
} else if (command.id === SetCellFormulaDependencyCalculationMutation.id) {
|
||||
this._generateCellDependencyTreeJson(command.params as ISetFormulaDependencyCalculationMutation);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -98,6 +110,62 @@ export class CalculateController extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private async _generateAllDependencyTreeJson() {
|
||||
const result = await this._calculateFormulaService.getAllDependencyJson();
|
||||
|
||||
this._commandService.executeCommand(
|
||||
SetFormulaDependencyCalculationResultMutation.id,
|
||||
{
|
||||
result,
|
||||
},
|
||||
{
|
||||
onlyLocal: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async _generateCellDependencyTreeJson(param: ISetFormulaDependencyCalculationMutation) {
|
||||
const { unitId, sheetId, row, column } = param;
|
||||
const result = await this._calculateFormulaService.getCellDependencyJson(unitId, sheetId, row, column);
|
||||
|
||||
this._commandService.executeCommand(
|
||||
SetCellFormulaDependencyCalculationResultMutation.id,
|
||||
{
|
||||
result,
|
||||
},
|
||||
{
|
||||
onlyLocal: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
const result = await this._calculateFormulaService.executeFormulas(
|
||||
params.formulas,
|
||||
formulaData,
|
||||
arrayFormulaCellData,
|
||||
arrayFormulaRange,
|
||||
rowData
|
||||
);
|
||||
|
||||
this._commandService.executeCommand(
|
||||
SetFormulaStringBatchCalculationResultMutation.id,
|
||||
{
|
||||
result,
|
||||
},
|
||||
{
|
||||
onlyLocal: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Notification
|
||||
private _initialExecuteFormulaListener() {
|
||||
/**
|
||||
|
||||
@@ -25,10 +25,16 @@ import { SetArrayFormulaDataMutation } from '../commands/mutations/set-array-for
|
||||
import { RemoveDefinedNameMutation, SetDefinedNameMutation } from '../commands/mutations/set-defined-name.mutation';
|
||||
import { RemoveFeatureCalculationMutation, SetFeatureCalculationMutation } from '../commands/mutations/set-feature-calculation.mutation';
|
||||
import {
|
||||
SetCellFormulaDependencyCalculationMutation,
|
||||
SetCellFormulaDependencyCalculationResultMutation,
|
||||
SetFormulaCalculationNotificationMutation,
|
||||
SetFormulaCalculationResultMutation,
|
||||
SetFormulaCalculationStartMutation,
|
||||
SetFormulaCalculationStopMutation,
|
||||
SetFormulaDependencyCalculationMutation,
|
||||
SetFormulaDependencyCalculationResultMutation,
|
||||
SetFormulaStringBatchCalculationMutation,
|
||||
SetFormulaStringBatchCalculationResultMutation,
|
||||
} 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';
|
||||
@@ -76,10 +82,17 @@ export class FormulaController extends Disposable {
|
||||
SetArrayFormulaDataMutation,
|
||||
SetImageFormulaDataMutation,
|
||||
SetFormulaCalculationStartMutation,
|
||||
SetFormulaStringBatchCalculationMutation,
|
||||
SetFormulaStringBatchCalculationResultMutation,
|
||||
SetFormulaCalculationStopMutation,
|
||||
SetFormulaCalculationNotificationMutation,
|
||||
SetFormulaCalculationResultMutation,
|
||||
|
||||
SetFormulaDependencyCalculationMutation,
|
||||
SetFormulaDependencyCalculationResultMutation,
|
||||
SetCellFormulaDependencyCalculationMutation,
|
||||
SetCellFormulaDependencyCalculationResultMutation,
|
||||
|
||||
SetDefinedNameMutation,
|
||||
RemoveDefinedNameMutation,
|
||||
SetFeatureCalculationMutation,
|
||||
|
||||
@@ -511,3 +511,111 @@ export class FormulaDependencyTree extends FormulaDependencyTreeCalculator {
|
||||
// this.parents.add(tree.treeId);
|
||||
// }
|
||||
}
|
||||
|
||||
interface IFormulaDependencyTreeJsonBase {
|
||||
treeId: number;
|
||||
formula: string;
|
||||
row: number;
|
||||
column: number;
|
||||
unitId: string;
|
||||
subUnitId: string;
|
||||
refOffsetX: number;
|
||||
refOffsetY: number;
|
||||
rangeList: IUnitRange[];
|
||||
refTreeId: number | undefined;
|
||||
}
|
||||
|
||||
export interface IFormulaDependencyTreeJson extends IFormulaDependencyTreeJsonBase {
|
||||
children: number[];
|
||||
parents: number[];
|
||||
}
|
||||
|
||||
export interface IFormulaDependencyTreeFullJson extends IFormulaDependencyTreeJsonBase {
|
||||
children: IFormulaDependencyTreeJson[];
|
||||
parents: IFormulaDependencyTreeJson[];
|
||||
}
|
||||
|
||||
export class FormulaDependencyTreeModel {
|
||||
children: Set<FormulaDependencyTreeModel> = new Set();
|
||||
|
||||
parents: Set<FormulaDependencyTreeModel> = new Set();
|
||||
|
||||
treeId: number = -1;
|
||||
|
||||
formula: string = '';
|
||||
|
||||
refOffsetX: number = 0;
|
||||
|
||||
refOffsetY: number = 0;
|
||||
|
||||
row: number = -1;
|
||||
|
||||
column: number = -1;
|
||||
|
||||
unitId: string = '';
|
||||
|
||||
subUnitId: string = '';
|
||||
|
||||
rangeList: IUnitRange[] = [];
|
||||
|
||||
refTreeId: number | undefined;
|
||||
|
||||
constructor(tree: IFormulaDependencyTree) {
|
||||
this.treeId = tree.treeId;
|
||||
this.row = tree.row;
|
||||
this.column = tree.column;
|
||||
this.unitId = tree.unitId;
|
||||
this.subUnitId = tree.subUnitId;
|
||||
this.refOffsetX = tree.refOffsetX;
|
||||
this.refOffsetY = tree.refOffsetY;
|
||||
this.rangeList = tree.rangeList;
|
||||
|
||||
if (tree.isVirtual) {
|
||||
this.refTreeId = (tree as FormulaDependencyTreeVirtual).refTree?.treeId ?? -1;
|
||||
} else {
|
||||
this.formula = tree.formula;
|
||||
}
|
||||
}
|
||||
|
||||
toJson(): IFormulaDependencyTreeJson {
|
||||
return {
|
||||
children: Array.from(this.children).map((child) => child.treeId),
|
||||
parents: Array.from(this.parents).map((parent) => parent.treeId),
|
||||
treeId: this.treeId,
|
||||
formula: this.formula,
|
||||
row: this.row,
|
||||
column: this.column,
|
||||
unitId: this.unitId,
|
||||
subUnitId: this.subUnitId,
|
||||
refOffsetX: this.refOffsetX,
|
||||
refOffsetY: this.refOffsetY,
|
||||
rangeList: this.rangeList,
|
||||
refTreeId: this.refTreeId,
|
||||
};
|
||||
}
|
||||
|
||||
toFullJson(): IFormulaDependencyTreeFullJson {
|
||||
return {
|
||||
children: Array.from(this.children).map((child) => child.toJson()),
|
||||
parents: Array.from(this.parents).map((parent) => parent.toJson()),
|
||||
treeId: this.treeId,
|
||||
formula: this.formula,
|
||||
row: this.row,
|
||||
column: this.column,
|
||||
unitId: this.unitId,
|
||||
subUnitId: this.subUnitId,
|
||||
refOffsetX: this.refOffsetX,
|
||||
refOffsetY: this.refOffsetY,
|
||||
rangeList: this.rangeList,
|
||||
refTreeId: this.refTreeId,
|
||||
};
|
||||
}
|
||||
|
||||
addParent(parent: FormulaDependencyTreeModel) {
|
||||
this.parents.add(parent);
|
||||
}
|
||||
|
||||
addChild(child: FormulaDependencyTreeModel) {
|
||||
this.children.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,21 +25,22 @@ import type { BaseAstNode } from '../ast-node/base-ast-node';
|
||||
import type { BaseReferenceObject, FunctionVariantType } from '../reference-object/base-reference-object';
|
||||
import type { IExecuteAstNodeData } from '../utils/ast-node-tool';
|
||||
import type { PreCalculateNodeType } from '../utils/node-type';
|
||||
import type { IFormulaDependencyTree } from './dependency-tree';
|
||||
import type { IFormulaDependencyTree, IFormulaDependencyTreeFullJson, IFormulaDependencyTreeJson } from './dependency-tree';
|
||||
import { createIdentifier, Disposable, Inject, ObjectMatrix, RTree } from '@univerjs/core';
|
||||
|
||||
import { prefixToken, suffixToken } from '../../basics/token';
|
||||
|
||||
import { IFormulaCurrentConfigService } from '../../services/current-data.service';
|
||||
import { IDependencyManagerService } from '../../services/dependency-manager.service';
|
||||
import { IFeatureCalculationManagerService } from '../../services/feature-calculation-manager.service';
|
||||
import { IOtherFormulaManagerService } from '../../services/other-formula-manager.service';
|
||||
import { IFormulaRuntimeService } from '../../services/runtime.service';
|
||||
import { Lexer } from '../analysis/lexer';
|
||||
import { LexerTreeBuilder } from '../analysis/lexer-tree-builder';
|
||||
import { AstTreeBuilder } from '../analysis/parser';
|
||||
import { NodeType } from '../ast-node/node-type';
|
||||
import { Interpreter } from '../interpreter/interpreter';
|
||||
import { FORMULA_AST_CACHE, generateAstNode, includeDefinedName } from '../utils/generate-ast-node';
|
||||
import { FormulaDependencyTree, FormulaDependencyTreeType, FormulaDependencyTreeVirtual } from './dependency-tree';
|
||||
import { FormulaDependencyTree, FormulaDependencyTreeModel, FormulaDependencyTreeType, FormulaDependencyTreeVirtual } from './dependency-tree';
|
||||
|
||||
const FORMULA_CACHE_LRU_COUNT = 5000;
|
||||
|
||||
@@ -56,6 +57,8 @@ export function generateRandomDependencyTreeId(dependencyManagerService: IDepend
|
||||
|
||||
export interface IFormulaDependencyGenerator {
|
||||
generate(): Promise<IFormulaDependencyTree[]>;
|
||||
getAllDependencyJson(): Promise<IFormulaDependencyTreeJson[]>;
|
||||
getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number): Promise<IFormulaDependencyTreeFullJson | undefined>;
|
||||
}
|
||||
|
||||
export const IFormulaDependencyGenerator = createIdentifier<IFormulaDependencyGenerator>('engine-formula.dependency-generator');
|
||||
@@ -74,7 +77,8 @@ export class FormulaDependencyGenerator extends Disposable {
|
||||
@Inject(Interpreter) private readonly _interpreter: Interpreter,
|
||||
@Inject(AstTreeBuilder) protected readonly _astTreeBuilder: AstTreeBuilder,
|
||||
@Inject(Lexer) protected readonly _lexer: Lexer,
|
||||
@IDependencyManagerService protected readonly _dependencyManagerService: IDependencyManagerService
|
||||
@IDependencyManagerService protected readonly _dependencyManagerService: IDependencyManagerService,
|
||||
@Inject(LexerTreeBuilder) protected readonly _lexerTreeBuilder: LexerTreeBuilder
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -1298,4 +1302,140 @@ export class FormulaDependencyGenerator extends Disposable {
|
||||
|
||||
return formulaRunList;
|
||||
}
|
||||
|
||||
protected async _initializeGenerateTreeList() {
|
||||
const formulaData = this._currentConfigService.getFormulaData();
|
||||
|
||||
const otherFormulaData = this._otherFormulaManagerService.getOtherFormulaData();
|
||||
|
||||
const unitData = this._currentConfigService.getUnitData();
|
||||
|
||||
const treeList = await this._generateTreeList(formulaData, otherFormulaData, unitData);
|
||||
|
||||
return treeList;
|
||||
}
|
||||
|
||||
protected async _getAllTreeList() {
|
||||
const treeList: IFormulaDependencyTree[] = await this._initializeGenerateTreeList();
|
||||
|
||||
const allTree: IFormulaDependencyTree[] = this._dependencyManagerService.buildDependencyTree(treeList);
|
||||
|
||||
return allTree;
|
||||
}
|
||||
|
||||
protected _formulaDependencyTreeModel = new Map<number, FormulaDependencyTreeModel>();
|
||||
|
||||
protected _getTreeModel(treeId: number): FormulaDependencyTreeModel {
|
||||
let treeModel = this._formulaDependencyTreeModel.get(treeId);
|
||||
if (!treeModel) {
|
||||
const tree = this._getTreeById(treeId);
|
||||
if (!tree) {
|
||||
throw new Error('FormulaDependencyTree is null');
|
||||
}
|
||||
|
||||
treeModel = new FormulaDependencyTreeModel(tree);
|
||||
// if (tree.isVirtual) {
|
||||
// const formula = this._lexerTreeBuilder.moveFormulaRefOffset(
|
||||
// tree.formula,
|
||||
// tree.refOffsetX,
|
||||
// tree.refOffsetY
|
||||
// );
|
||||
// treeModel.formula = formula;
|
||||
// }
|
||||
this._formulaDependencyTreeModel.set(treeId, treeModel);
|
||||
}
|
||||
return treeModel;
|
||||
}
|
||||
|
||||
protected _getDependencyTreeParenIds(tree: IFormulaDependencyTree): Set<number> {
|
||||
return tree.parents;
|
||||
}
|
||||
|
||||
protected _getDependencyTreeChildrenIds(tree: IFormulaDependencyTree): Set<number> {
|
||||
return tree.children;
|
||||
}
|
||||
|
||||
protected _getFormulaDependencyTreeModel(tree: IFormulaDependencyTree): FormulaDependencyTreeModel {
|
||||
const treeModel = this._getTreeModel(tree.treeId);
|
||||
const parentIds = this._getDependencyTreeParenIds(tree);
|
||||
for (const parentId of parentIds) {
|
||||
const parentTreeModel = this._getTreeModel(parentId);
|
||||
treeModel.addParent(parentTreeModel);
|
||||
parentTreeModel.addChild(treeModel);
|
||||
}
|
||||
return treeModel;
|
||||
}
|
||||
|
||||
protected _endFormulaDependencyTreeModel() {
|
||||
this._formulaDependencyTreeModel.clear();
|
||||
}
|
||||
|
||||
protected _startFormulaDependencyTreeModel() {
|
||||
|
||||
}
|
||||
|
||||
async getAllDependencyJson(): Promise<IFormulaDependencyTreeJson[]> {
|
||||
const treeList = await this._getAllTreeList();
|
||||
|
||||
this._startFormulaDependencyTreeModel();
|
||||
|
||||
const results: FormulaDependencyTreeModel[] = [];
|
||||
for (const tree of treeList) {
|
||||
const treeModel = this._getFormulaDependencyTreeModel(tree);
|
||||
results[tree.treeId] = treeModel;
|
||||
}
|
||||
|
||||
const resultsJson: IFormulaDependencyTreeJson[] = [];
|
||||
for (const result of results) {
|
||||
if (result) {
|
||||
resultsJson.push(result.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
this._endFormulaDependencyTreeModel();
|
||||
|
||||
return resultsJson;
|
||||
}
|
||||
|
||||
async getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number): Promise<IFormulaDependencyTreeFullJson | undefined> {
|
||||
await this._initializeGenerateTreeList();
|
||||
const treeId = this._dependencyManagerService.getFormulaDependency(unitId, sheetId, row, column);
|
||||
if (treeId == null) {
|
||||
return;
|
||||
}
|
||||
const tree = this._getTreeById(treeId);
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
const formula = this._lexerTreeBuilder.moveFormulaRefOffset(
|
||||
tree.formula,
|
||||
tree.refOffsetX,
|
||||
tree.refOffsetY
|
||||
);
|
||||
childTreeModel.formula = formula;
|
||||
treeModel.addChild(childTreeModel);
|
||||
}
|
||||
|
||||
this._endFormulaDependencyTreeModel();
|
||||
|
||||
return treeModel.toFullJson();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
|
||||
import type { ICommandInfo, IDisposable } from '@univerjs/core';
|
||||
import type { FormulaExecutedStateType, IExecutionInProgressParams, ISequenceNode, ISetFormulaCalculationNotificationMutation, ISetFormulaCalculationStartMutation } from '@univerjs/engine-formula';
|
||||
import type { FormulaExecutedStateType, IExecutionInProgressParams, IFormulaDependencyTreeFullJson, IFormulaDependencyTreeJson, IFormulaExecuteResultMap, IFormulaStringMap, ISequenceNode, ISetCellFormulaDependencyCalculationResultMutation, ISetFormulaCalculationNotificationMutation, 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, SetFormulaCalculationNotificationMutation, SetFormulaCalculationStartMutation, SetFormulaCalculationStopMutation } from '@univerjs/engine-formula';
|
||||
import { ENGINE_FORMULA_CYCLE_REFERENCE_COUNT, GlobalComputingStatusService, LexerTreeBuilder, SetCellFormulaDependencyCalculationMutation, SetCellFormulaDependencyCalculationResultMutation, SetFormulaCalculationNotificationMutation, SetFormulaCalculationStartMutation, SetFormulaCalculationStopMutation, SetFormulaDependencyCalculationMutation, SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation } from '@univerjs/engine-formula';
|
||||
import { filter, firstValueFrom, map, race, timer } from 'rxjs';
|
||||
|
||||
/**
|
||||
@@ -248,4 +248,173 @@ export class FFormula extends FBase {
|
||||
setMaxIteration(maxIteration: number): void {
|
||||
this._configService.setConfig(ENGINE_FORMULA_CYCLE_REFERENCE_COUNT, maxIteration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a batch of formulas asynchronously and receive computed results.
|
||||
*
|
||||
* Each formula cell is represented as a string array:
|
||||
* [fullFormula, ...subFormulas]
|
||||
*
|
||||
* Where:
|
||||
* - fullFormula (index 0) is the complete formula expression written in the cell.
|
||||
* Example: "=SUM(A1:A10) + SQRT(D7)".
|
||||
*
|
||||
* - subFormulas (index 1+) are **optional decomposed expressions** extracted from
|
||||
* the full formula. Each of them can be independently computed by the formula engine.
|
||||
*
|
||||
* These sub-expressions can include:
|
||||
* - Single-cell references: "A2", "B2", "C5"
|
||||
* - Range references: "A1:A10"
|
||||
* - Function calls: "SQRT(D7)", "ABS(A2-B2)"
|
||||
* - Any sub-formula that was parsed out of the original formula and can be
|
||||
* evaluated on its own.
|
||||
*
|
||||
* The batch execution engine may use these sub-formulas for dependency resolution,
|
||||
* incremental computation, or performance optimizations.
|
||||
*
|
||||
* @param {IFormulaStringMap} formulas
|
||||
* Nested structure (unit → sheet → row → column) describing formulas and
|
||||
* their decomposed sub-expressions.
|
||||
*
|
||||
* @param {(result: IFormulaExecuteResultMap) => void} callback
|
||||
* Receives the computed value map mirroring the input structure.
|
||||
*
|
||||
* @returns {IDisposable}
|
||||
* A disposer to stop listening for batch results.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const formulaEngine = univerAPI.getFormula();
|
||||
* const formulas = {
|
||||
* Book1: {
|
||||
* Sheet1: {
|
||||
* 2: {
|
||||
* 3: [
|
||||
* // Full formula:
|
||||
* "=SUM(A1:A10) + SQRT(D7)",
|
||||
*
|
||||
* // Decomposed sub-formulas (each one can be evaluated independently):
|
||||
* "SUM(A1:A10)", // sub-formula 1
|
||||
* "SQRT(D7)", // sub-formula 2
|
||||
* "A1:A10", // range reference
|
||||
* "D7", // single-cell reference
|
||||
* ],
|
||||
* },
|
||||
* 4: {
|
||||
* 5: [
|
||||
* "=A2 + B2 + SQRT(C5)",
|
||||
* "A2",
|
||||
* "B2",
|
||||
* "SQRT(C5)",
|
||||
* ],
|
||||
* }
|
||||
* },
|
||||
* },
|
||||
* };
|
||||
*
|
||||
* const disposer = formulaEngine.executeFormulas(formulas, (result) => {
|
||||
* console.log(result);
|
||||
* });
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
executeFormulas(formulas: IFormulaStringMap, callback: (result: IFormulaExecuteResultMap) => void): void {
|
||||
this._commandService.executeCommand(SetFormulaStringBatchCalculationMutation.id, { formulas }, { onlyLocal: true });
|
||||
const disposable = this._commandService.onCommandExecuted((command: ICommandInfo) => {
|
||||
if (command.id !== SetFormulaStringBatchCalculationResultMutation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = command.params as ISetFormulaStringBatchCalculationResultMutation;
|
||||
|
||||
if (params.result != null) {
|
||||
callback(params.result);
|
||||
}
|
||||
disposable.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all formula dependency trees that were produced during the latest
|
||||
* dependency-analysis run. This triggers a local dependency-calculation command
|
||||
* and returns the complete set of dependency trees once the calculation finishes.
|
||||
*
|
||||
* @param callback A function invoked with the resulting array of dependency trees.
|
||||
*
|
||||
* @returns {IDisposable} An object that disposes the internal event listener.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const formulaEngine = univerAPI.getFormula();
|
||||
*
|
||||
* // Fetch all dependency trees generated for the current workbook.
|
||||
* const disposable = formulaEngine.getAllDependencyTrees((trees) => {
|
||||
* console.log('All dependency trees:', trees);
|
||||
* });
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
getAllDependencyTrees(callback: (result: IFormulaDependencyTreeJson[]) => void): void {
|
||||
this._commandService.executeCommand(SetFormulaDependencyCalculationMutation.id, undefined, { onlyLocal: true });
|
||||
const disposable = this._commandService.onCommandExecuted((command: ICommandInfo) => {
|
||||
if (command.id !== SetFormulaDependencyCalculationResultMutation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = command.params as ISetFormulaDependencyCalculationResultMutation;
|
||||
|
||||
if (params.result != null) {
|
||||
callback(params.result);
|
||||
}
|
||||
|
||||
disposable.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the dependency tree of a specific cell. This triggers a local
|
||||
* dependency-calculation command for the given unit, sheet, and cell location,
|
||||
* and returns the computed dependency tree when the calculation is completed.
|
||||
*
|
||||
* @param param The target cell location:
|
||||
* - `unitId` The workbook ID.
|
||||
* - `sheetId` The sheet ID.
|
||||
* - `row` The zero-based row index.
|
||||
* - `column` The zero-based column index.
|
||||
*
|
||||
* @param callback A function invoked with the resulting dependency tree or
|
||||
* `undefined` if no dependency tree exists for that cell.
|
||||
*
|
||||
* @returns {IDisposable} An object that disposes the internal event listener.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const formulaEngine = univerAPI.getFormula();
|
||||
*
|
||||
* // Query the dependency tree for cell B2 in a specific sheet.
|
||||
* const disposable = formulaEngine.getCellDependencyTree(
|
||||
* { unitId: 'workbook1', sheetId: 'sheet1', row: 1, column: 1 },
|
||||
* (tree) => {
|
||||
* console.log('Cell dependency tree:', tree);
|
||||
* }
|
||||
* );
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
getCellDependencyTree(param: { unitId: string; sheetId: string; row: number; column: number }, callback: (result: IFormulaDependencyTreeFullJson | undefined) => void): void {
|
||||
this._commandService.executeCommand(SetCellFormulaDependencyCalculationMutation.id, param, { onlyLocal: true });
|
||||
const disposable = this._commandService.onCommandExecuted((command: ICommandInfo) => {
|
||||
if (command.id !== SetCellFormulaDependencyCalculationResultMutation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = command.params as ISetCellFormulaDependencyCalculationResultMutation;
|
||||
|
||||
if (params.result !== undefined) {
|
||||
callback(params.result);
|
||||
}
|
||||
|
||||
disposable.dispose();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ export type {
|
||||
IFormulaData,
|
||||
IFormulaDataItem,
|
||||
IFormulaDatasetConfig,
|
||||
IFormulaExecuteResultMap,
|
||||
IFormulaStringMap,
|
||||
IRuntimeImageFormulaDataType,
|
||||
IRuntimeUnitDataType,
|
||||
ISheetData,
|
||||
@@ -53,13 +55,23 @@ export { type ISetDefinedNameMutationParam, type ISetDefinedNameMutationSearchPa
|
||||
export { SetDefinedNameMutationFactory } from './commands/mutations/set-defined-name.mutation';
|
||||
export { RemoveFeatureCalculationMutation, SetFeatureCalculationMutation } from './commands/mutations/set-feature-calculation.mutation';
|
||||
export {
|
||||
type ISetCellFormulaDependencyCalculationResultMutation,
|
||||
type ISetFormulaCalculationNotificationMutation,
|
||||
type ISetFormulaCalculationResultMutation,
|
||||
type ISetFormulaCalculationStartMutation,
|
||||
type ISetFormulaDependencyCalculationMutation,
|
||||
type ISetFormulaDependencyCalculationResultMutation,
|
||||
type ISetFormulaStringBatchCalculationResultMutation,
|
||||
SetCellFormulaDependencyCalculationMutation,
|
||||
SetCellFormulaDependencyCalculationResultMutation,
|
||||
SetFormulaCalculationNotificationMutation,
|
||||
SetFormulaCalculationResultMutation,
|
||||
SetFormulaCalculationStartMutation,
|
||||
SetFormulaCalculationStopMutation,
|
||||
SetFormulaDependencyCalculationMutation,
|
||||
SetFormulaDependencyCalculationResultMutation,
|
||||
SetFormulaStringBatchCalculationMutation,
|
||||
SetFormulaStringBatchCalculationResultMutation,
|
||||
} 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';
|
||||
@@ -83,7 +95,7 @@ export { ReferenceNodeFactory } from './engine/ast-node/reference-node';
|
||||
export { SuffixNodeFactory } from './engine/ast-node/suffix-node';
|
||||
export { UnionNodeFactory } from './engine/ast-node/union-node';
|
||||
export { ValueNodeFactory } from './engine/ast-node/value-node';
|
||||
export { FormulaDependencyTree, type IFormulaDependencyTree } from './engine/dependency/dependency-tree';
|
||||
export { FormulaDependencyTree, FormulaDependencyTreeModel, type IFormulaDependencyTree, type IFormulaDependencyTreeFullJson, type IFormulaDependencyTreeJson } from './engine/dependency/dependency-tree';
|
||||
export { FormulaDependencyTreeType } from './engine/dependency/dependency-tree';
|
||||
export { FormulaDependencyTreeVirtual } from './engine/dependency/dependency-tree';
|
||||
export { FormulaDependencyGenerator, IFormulaDependencyGenerator } from './engine/dependency/formula-dependency';
|
||||
|
||||
@@ -18,15 +18,24 @@ import type { IUnitRange } from '@univerjs/core';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type {
|
||||
IArrayFormulaRangeType,
|
||||
IArrayFormulaUnitCellType,
|
||||
IFeatureDirtyRangeType,
|
||||
IFormulaData,
|
||||
IFormulaDatasetConfig,
|
||||
IFormulaExecuteResultItem,
|
||||
IFormulaExecuteResultMap,
|
||||
IFormulaStringMap,
|
||||
IRuntimeUnitDataType,
|
||||
IUnitExcludedCell,
|
||||
IUnitRowData,
|
||||
} from '../basics/common';
|
||||
|
||||
import type { IUniverEngineFormulaConfig } from '../controller/config.schema';
|
||||
import type { LexerNode } from '../engine/analysis/lexer-node';
|
||||
import type { FunctionVariantType } from '../engine/reference-object/base-reference-object';
|
||||
import type { IFormulaDependencyTreeFullJson, IFormulaDependencyTreeJson } from '../engine/dependency/dependency-tree';
|
||||
import type { BaseReferenceObject, FunctionVariantType } from '../engine/reference-object/base-reference-object';
|
||||
import type { ArrayValueObject } from '../engine/value-object/array-value-object';
|
||||
import type { BaseValueObject } from '../engine/value-object/base-value-object';
|
||||
import type { IAllRuntimeData, IExecutionInProgressParams } from './runtime.service';
|
||||
import {
|
||||
AsyncLock,
|
||||
@@ -43,7 +52,6 @@ import { CELL_INVERTED_INDEX_CACHE } from '../basics/inverted-index-cache';
|
||||
import { DEFAULT_CYCLE_REFERENCE_COUNT, ENGINE_FORMULA_PLUGIN_CONFIG_KEY } from '../controller/config.schema';
|
||||
import { Lexer } from '../engine/analysis/lexer';
|
||||
import { AstTreeBuilder } from '../engine/analysis/parser';
|
||||
import { ErrorNode } from '../engine/ast-node/base-ast-node';
|
||||
import { IFormulaDependencyGenerator } from '../engine/dependency/formula-dependency';
|
||||
import { Interpreter } from '../engine/interpreter/interpreter';
|
||||
import { FORMULA_REF_TO_ARRAY_CACHE } from '../engine/reference-object/base-reference-object';
|
||||
@@ -66,6 +74,9 @@ export interface ICalculateFormulaService {
|
||||
execute(formulaDatasetConfig: IFormulaDatasetConfig): Promise<void>;
|
||||
stopFormulaExecution(): void;
|
||||
calculate(formulaString: string, transformSuffix?: boolean): void;
|
||||
executeFormulas(formulas: IFormulaStringMap, formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData: IUnitRowData): Promise<IFormulaExecuteResultMap>;
|
||||
getAllDependencyJson(): Promise<IFormulaDependencyTreeJson[]>;
|
||||
getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number): Promise<IFormulaDependencyTreeFullJson | undefined>;
|
||||
}
|
||||
|
||||
export const ICalculateFormulaService = createIdentifier<ICalculateFormulaService>('engine-formula.calculate-formula.service');
|
||||
@@ -367,42 +378,147 @@ export class CalculateFormulaService extends Disposable implements ICalculateFor
|
||||
return this._runtimeService.getAllRuntimeData();
|
||||
}
|
||||
|
||||
calculate(formulaString: string, transformSuffix: boolean = true) {
|
||||
// TODO how to observe @alex
|
||||
// this.getObserver('onBeforeFormulaCalculateObservable')?.notifyObservers(formulaString);
|
||||
const lexerNode = this._lexer.treeBuilder(formulaString, transformSuffix);
|
||||
async executeFormulas(formulas: IFormulaStringMap, formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData?: IUnitRowData) {
|
||||
this._currentConfigService.loadDataLite(
|
||||
formulaData,
|
||||
arrayFormulaCellData,
|
||||
arrayFormulaRange,
|
||||
rowData
|
||||
);
|
||||
|
||||
if (Object.values(ErrorType).includes(lexerNode as ErrorType)) {
|
||||
return ErrorNode.create(lexerNode as ErrorType);
|
||||
const unitData = this._currentConfigService.getUnitData();
|
||||
|
||||
this._runtimeService.reset();
|
||||
|
||||
const result: IFormulaExecuteResultMap = {};
|
||||
|
||||
for (const unitId of Object.keys(formulas)) {
|
||||
const sheetFormulas = formulas[unitId];
|
||||
if (sheetFormulas == null) continue;
|
||||
|
||||
result[unitId] = {};
|
||||
|
||||
for (const sheetId of Object.keys(sheetFormulas)) {
|
||||
const rowFormulas = sheetFormulas[sheetId];
|
||||
if (rowFormulas == null) continue;
|
||||
|
||||
const sheetItem = unitData[unitId]?.[sheetId];
|
||||
|
||||
if (sheetItem == null) continue;
|
||||
|
||||
result[unitId]![sheetId] = {};
|
||||
|
||||
for (const rowString of Object.keys(rowFormulas)) {
|
||||
const row = Number.parseInt(rowString);
|
||||
result[unitId]![sheetId]![row] = {};
|
||||
|
||||
const cellData = rowFormulas[row];
|
||||
if (!cellData) continue;
|
||||
|
||||
for (const columnString of Object.keys(cellData)) {
|
||||
const column = Number.parseInt(columnString);
|
||||
const formulaStrings = cellData[column];
|
||||
if (!formulaStrings) continue;
|
||||
|
||||
const rowCount = sheetItem.rowCount || 0;
|
||||
const columnCount = sheetItem.columnCount || 0;
|
||||
|
||||
this._runtimeService.setCurrent(
|
||||
row,
|
||||
column,
|
||||
rowCount,
|
||||
columnCount,
|
||||
sheetId,
|
||||
unitId
|
||||
);
|
||||
|
||||
const item: IFormulaExecuteResultItem[] = [];
|
||||
|
||||
for (const formulaString of formulaStrings) {
|
||||
let resultCell = await this.calculate(formulaString);
|
||||
if (!resultCell) {
|
||||
item.push({
|
||||
value: null,
|
||||
formula: formulaString,
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resultCell.isReferenceObject()) {
|
||||
resultCell = (resultCell as BaseReferenceObject).toArrayValueObject();
|
||||
}
|
||||
|
||||
const resultRefObject = resultCell as BaseValueObject;
|
||||
|
||||
if (resultRefObject.isArray()) {
|
||||
const resultRefArrayObject = resultRefObject as ArrayValueObject;
|
||||
if (resultRefArrayObject.getRowCount() === 1 && resultRefArrayObject.getColumnCount() === 1) {
|
||||
item.push({
|
||||
value: resultRefArrayObject.getFirstCell().getValue(),
|
||||
formula: formulaString,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
item.push({
|
||||
value: resultRefArrayObject.toValue(),
|
||||
formula: formulaString,
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
item.push({
|
||||
value: resultRefObject.getValue(),
|
||||
formula: formulaString,
|
||||
});
|
||||
}
|
||||
|
||||
result[unitId]![sheetId]![row]![column] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this.lexerTreeBuilder.suffixExpressionHandler(lexerNode); // suffix Express, 1+(3*4=4)*5+1 convert to 134*4=5*1++
|
||||
return result;
|
||||
}
|
||||
|
||||
// console.log('sequence', this.lexerTreeBuilder.sequenceNodesBuilder(formulaString));
|
||||
async calculate(formulaString: string) {
|
||||
// TODO how to observe @alex
|
||||
// this.getObserver('onBeforeFormulaCalculateObservable')?.notifyObservers(formulaString);
|
||||
const lexerNode = this._lexer.treeBuilder(formulaString);
|
||||
|
||||
// this.getObserver('onAfterFormulaLexerObservable')?.notifyObservers(lexerNode);
|
||||
|
||||
// const astTreeBuilder = new AstTreeBuilder();
|
||||
if (Object.values(ErrorType).includes(lexerNode as ErrorType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const astNode = this._astTreeBuilder.parse(lexerNode as LexerNode);
|
||||
|
||||
// console.log('astNode', astNode?.serialize());
|
||||
astNode?.serialize();
|
||||
const interpreter = this._interpreter;
|
||||
|
||||
// const interpreter = Interpreter.create();
|
||||
if (astNode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (astNode == null) {
|
||||
// return;
|
||||
// }
|
||||
const nodeData = {
|
||||
node: astNode,
|
||||
refOffsetX: 0,
|
||||
refOffsetY: 0,
|
||||
};
|
||||
|
||||
// if (interpreter.checkAsyncNode(astNode)) {
|
||||
// const resultPromise = interpreter.executeAsync(astNode);
|
||||
if (interpreter.checkAsyncNode(astNode)) {
|
||||
return await interpreter.executeAsync(nodeData);
|
||||
} else {
|
||||
return interpreter.execute(nodeData);
|
||||
}
|
||||
}
|
||||
|
||||
// resultPromise.then((value) => {
|
||||
// console.log('formulaResult', value);
|
||||
// });
|
||||
// } else {
|
||||
// console.log(interpreter.execute(astNode));
|
||||
// }
|
||||
async getAllDependencyJson(): Promise<IFormulaDependencyTreeJson[]> {
|
||||
return this._formulaDependencyGenerator.getAllDependencyJson();
|
||||
}
|
||||
|
||||
async getCellDependencyJson(unitId: string, sheetId: string, row: number, column: number): Promise<IFormulaDependencyTreeFullJson | undefined> {
|
||||
return this._formulaDependencyGenerator.getCellDependencyJson(unitId, sheetId, row, column);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import type { IUnitRange, LocaleType, Nullable, Workbook } from '@univerjs/core';
|
||||
import type {
|
||||
IArrayFormulaRangeType,
|
||||
IArrayFormulaUnitCellType,
|
||||
IDirtyUnitFeatureMap,
|
||||
IDirtyUnitOtherFormulaMap,
|
||||
IDirtyUnitSheetDefinedNameMap,
|
||||
@@ -113,6 +114,8 @@ export interface IFormulaCurrentConfigService {
|
||||
getFilteredOutRows(unitId: string, sheetId: string, startRow: number, endRow: number): number[];
|
||||
|
||||
setSheetNameMap(sheetIdToNameMap: IUnitSheetIdToNameMap): void;
|
||||
|
||||
loadDataLite(formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData?: IUnitRowData): void;
|
||||
}
|
||||
|
||||
export class FormulaCurrentConfigService extends Disposable implements IFormulaCurrentConfigService {
|
||||
@@ -345,6 +348,25 @@ export class FormulaCurrentConfigService extends Disposable implements IFormulaC
|
||||
this._mergeNameMap(this._sheetNameMap, this._dirtyNameMap);
|
||||
}
|
||||
|
||||
loadDataLite(formulaData: IFormulaData, arrayFormulaCellData: IArrayFormulaUnitCellType, arrayFormulaRange: IArrayFormulaRangeType, rowData?: IUnitRowData) {
|
||||
const { allUnitData, unitSheetNameMap, unitStylesData } = this._loadSheetData();
|
||||
|
||||
this._unitData = allUnitData;
|
||||
|
||||
this._unitStylesData = unitStylesData;
|
||||
|
||||
this._sheetNameMap = unitSheetNameMap;
|
||||
|
||||
this._formulaData = formulaData;
|
||||
|
||||
this._arrayFormulaCellData = convertUnitDataToRuntime(arrayFormulaCellData);
|
||||
|
||||
this._arrayFormulaRange = arrayFormulaRange;
|
||||
|
||||
// apply row data, including rows hidden by filters
|
||||
rowData && this._applyUnitRowData(rowData);
|
||||
}
|
||||
|
||||
getDirtyData(): IFormulaDirtyData {
|
||||
return {
|
||||
forceCalculation: this._forceCalculate,
|
||||
|
||||
Reference in New Issue
Block a user