UNPKG

@syncfusion/ej2-spreadsheet

Version:

Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel

91 lines (76 loc) 7.6 kB
# Formula Module data flow ## What It Does Formula subsystem evaluates and manages spreadsheet formulas. It provides parsing, calculation, dependency tracking, named-range management, and formula autor-complete/suggestion UI. Split across core calculation services in the workbook (`WorkbookFormula`) and editor/autocomplete UI and helpers in the spreadsheet (`Formula`). Primary implementation files: `src/workbook/integrations/formula.ts` (Core/WorkbookFormula) and `src/spreadsheet/integrations/formula.ts` (UI/Formula). ## Entry Points (UI) **Class:** `Formula` (Spreadsheet UI layer) - Listens: `formulaOperation`, `keyUp`, `keyDown`, `click`, `refreshFormulaDatasource`. - Key handlers: - `renderAutoComplete()` — create suggestion AutoComplete input (`#{id}_ac`) and wire suggestion lifecycle. - `keyUpHandler()` / `keyDownHandler()` — detect formula editing, drive suggestions, and route keyboard navigation to suggestion popup. - `onSelect()` / `onSuggestionComplete()` — inject selected function text into editor via `editOperation` notification. - `performFormulaOperation()` — bridge actions like `renderAutoComplete`, `endEdit`, `addDefinedName`, `getNames`, `getNameFromRange`, `isFormulaEditing`, and show dialogs (e.g., circular reference). - Popup helpers: `onSuggestionOpen()`, `onSuggestionClose()`, `hidePopUp()`. ## Entry Points (Core) **Class:** `WorkbookFormula` (Workbook core layer) - Listens: `workbookFormulaOperation`, `aggregateComputation`, `getUniqueRange`, `removeUniquecol`, `clearFormulaDependentCells`, `formulaInValidation`, `refreshInsertDelete`, `getUpdatedFormulaOnInsertDelete`, `checkFormulaRef`, `parseFormulaArgument`, `getCellRefValue`, `commputeFormulaValue`, `sheetRenameUpdate`, `importModelUpdate`. - Key responsibilities: - Initialize calculation engine (`Calculate` instance), manage sheet registration and parsing separators. - `refreshCalculate()` / `calculateFormula()` — perform cell formula recalculation, update dependent cells, and integrate with value persistence. - Dependency management: track dependent cells, named ranges, and unique function handling (e.g., UNIQUE/SPILL behaviors). - Defined names: `initiateDefinedNames()`, `addDefinedName()`, `removeDefinedName()` and maintain `sheetInfo` for sheet references. - Structural updates: `refreshInsertDelete()`, `getUpdatedFormulaOnInsertDelete()` to update formulas on insert/delete/rename operations. - Utility/parsing: `parseFormulaArgument()`, `markSpecialChar()`, `autoCorrectFormula()` and cell-reference correction helpers. ## ASCII Core Logic Flow User edits cell (formula) → UI `Formula` captures keys and shows suggestions ↓ User commits formula → `editOperation` triggers write → core receives calculation requests via `workbookFormulaOperation`/`refreshCalculate` ↓ `WorkbookFormula` parses formula (`parseFormulaArgument`, `markSpecialChar`) → `Calculate.valueChanged`/`computeExpression` runs → dependencies updated ↓ Core updates `CellModel.value`/`formula`, notifies UI to refresh views (via existing render/update pipelines) ↓ Structural changes (insert/delete/rename) → `WorkbookFormula` updates formulas and named ranges, emits updates to UI to re-render ## Operations (functions & responsibilities) - UI (`Formula`): - `renderAutoComplete()` — create and populate autocomplete with `workbookFormulaOperation` data (library formulas). - `getSuggestionKeyFromFormula()` — extract token to suggest based on caret position and separators. - `onSelect()` — build insertion text (e.g., `=SUM(`) and notify `editOperation` to refresh editor / formula bar. - `performFormulaOperation()` — handles UI-level commands (defined-name helpers, circular ref dialogs). - Core (`WorkbookFormula`): - `initCalculate()` — create `Calculate` instance, set parse separators, register sheets. - `refreshCalculate(args)` — prepare sheet/family context and call `calculateFormula()`. - `calculateFormula(args, cellRef)` — auto-correct, parse sheet refs, call `calculateInstance.valueChanged` and process results (update `CellModel`, evaluate errors, update dependant cells). - Dependency & named-range handling — `getUniqueRange`, `clearFormulaDependentCells`, `initiateDefinedNames`, `addDefinedName`, `removeDefinedName`, `refreshNamedRange`. - Structural update handlers — `refreshInsertDelete`, `getUpdatedFormulaOnInsertDelete`, `renameUpdation`, `sheetDeletion`. - Parsing helpers — `parseFormulaArgument()`, `markSpecialChar()`, `getUniqueCharVal()` to safely tokenize formulas. ## Validation & Safety - Formula parsing: uses `markSpecialChar()` to escape operators and separators for safe tokenization; `parseFormulaArgument()` returns sanitized argument array. - Auto-corrections: `autoCorrectFormula()` and `autoCorrectCellRef()` attempt to repair common user mistakes and update references safely. - Circular references: UI shows dialogs (via `Dialog` service) when `isCircularReference` detected and core supplies default values. - Named-range validation: `addDefinedName()` enforces naming rules and shows localized dialogs for invalid or duplicate names. - Structural safety: on insert/delete/rename, `WorkbookFormula` updates formulas to prevent broken refs and emits corrected formulas via notifications. - Async safety: long-running calc/update paths are batched; `calculateNow()` (in core) uses Deferred/promise for multi-sheet recalculations. ## Desired Outputs User-facing - Formula autocomplete/suggestion popup anchored to editor/formula bar (id pattern `#{id}_ac` and popup `#{id}_ac_popup`). - Insert Function dialog and function insertion behavior (delegated via `performFormulaOperation` and `workbookFormulaOperation`). - Clear error dialogs for circular references and invalid defined names. System-level - Events & Notifications: - UI → Core: `workbookFormulaOperation` (commands like `renderAutoComplete`, `addDefinedName`, `getNames`, `commputeFormulaValue`) - Core → UI/others: `getCellRefValue`, `getUniqueRange`, and calculation results via cell update notifications in the workbook pipeline. - Others: `aggregateComputation`, `importModelUpdate`, `refreshInsertDelete`, `sheetRenameUpdate` used for integration across modules. - Model artifacts: - Calculation engine: `Calculate` instance holds formula info, dependent cells, named ranges, uniqueRange arrays and token maps. - `sheetInfo[]` used to map visible names to internal sheet ids for ref parsing. - `CellModel.formula` and `CellModel.value` updated by `WorkbookFormula` after calculations; dependent cells tracked in `calculateInstance` maps. - Undo/Redo: - Formula edits and structural changes are integrated into the workbook action pipeline; `WorkbookFormula` respects flags such as `isDelete`, `isRefreshing`, and `isDependentRefresh` to avoid double-application during undo/redo. ## Implementation Notes (short) - Maintain clear separation: `Formula` provides suggestion UI and name helpers; `WorkbookFormula` owns parsing, calculation, dependencies, and structural updates. - Use `Calculate` API for all computation and dependency tracking; avoid duplicating calculation logic in the UI. - Persist and update named ranges through `addDefinedName`/`removeDefinedName` entry points so other modules (name box, formula bar) can query via `workbookFormulaOperation`. - Ensure async `getData`/`calculateNow` callbacks guard against `parent` being null. - Localize dialog strings via `L10n` and reuse `Dialog` service for consistent UX. ---