@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
Markdown
# 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.
---