@syncfusion/ej2-spreadsheet
Version:
Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel
121 lines (99 loc) • 8.91 kB
Markdown
# Find & Replace Module data flow
## What It Does
Provides find and replace/search functionality across the Spreadsheet and Workbook layers, including:
- Single-sheet and workbook-wide searches (next/previous), and Find All.
- Case-sensitive / case-insensitive search, exact-match and partial-match modes.
- Search by row or by column, with start-position control and wrap-around behavior.
- Replace single occurrences and Replace All with optional action events and UI confirmation.
- UI tool (Find dialog, Find toolbar) integration with Ribbon/Dialogs and lightweight inline find widget.
- Counting matches and producing an address collection for Find All or Replace All flows.
## Entry Points
**Spreadsheet UI Class (`FindAndReplace`)**
- `constructor(parent: Spreadsheet)` — initializes UI state, controls and event listeners.
- `addEventListener()` / `removeEventListener()` — wire up UI notifications and native events.
- `findToolDlg(args)` — lightweight find toolbar that sits over the sheet panel (quick-find input and prev/next controls).
- `renderFindDlg(args?)` — full Find & Replace dialog rendering (Find/Replace/Goto views, options, buttons).
- `findandreplaceContent()` / `GotoContent()` — dialog content builders for Find/Replace and Goto.
- `findHandler()` / `replaceHandler(action)` — collect UI options and forward find/replace requests to Core via `parent.notify`.
- `replaceAllDialog(options)` / `showFindAlert()` — render results/alerts after bulk operations.
- `destroy()` / `getModuleName()` — lifecycle helpers.
**Workbook Core Class (`WorkbookFindAndReplace`)**
- `constructor(parent: Workbook)` — registers core event listeners and holds search state.
- `addEventListener()` / `removeEventListener()` — subscribe to core events: `find`, `replace`, `replaceAll`, `count`, `findAllValues`.
- `find(args: FindOptionsArgs)` — orchestrates search parameters (sheet/workbook mode), computes start positions, and delegates to `findNext` or `findPrevious`.
- `findNext(args, findArgs)` / `findPrevious(args, findArgs)` — top-level traversal across sheets honoring workbook mode and wrapping.
- `findNextOnSheet(...)` / `findPrevOnSheet(...)` — scan a single sheet row- or column-wise, skipping hidden rows/columns and honoring activeCell.
- `checkMatch(...)` — determine a per-cell match using display text, formatting and locale considerations.
- `replace(args)` / `replaceAll(args)` — perform single replacement and Replace All flows, including event triggers, validation, and actual `updateCell`/`updateCellDetails` calls.
- `totalCount(args)` — computes counts and the "n of m" display used by the UI.
- `findAllValues(findAllArguments)` — gather addresses and values for a Find All operation.
- `getDisplayText(cell, rowIdx, colIdx, localeObj)` / `getCellVal(cell, localeObj)` — helpers to obtain formatted display text and canonical searchable values.
- `getModuleName()` — module identifier.
## Core Logic Flow
```
User Action (UI quick-find or Find dialog -> Next/Previous/Replace/Replace All)
↓
UI collects options (Find value, Case/Exact, Search within Sheet/Workbook, By Row/Column)
↓
UI -> `parent.notify('find'|'replace'|'replaceAll'| 'count' | 'findAllValues', args)`
↓
WorkbookFindAndReplace.find(args): normalize start, compute `findArgs` + sheets list
↓
Delegates to `findNext` / `findPrevious`:
- iterate sheets (if Workbook mode)
- call `findNextOnSheet` / `findPrevOnSheet` for per-sheet scan
- call `checkMatch` per cell and respect hidden/locked/protected state
↓
Match found -> `parent.notify('goto', { address })` (UI navigates) OR no-match -> `parent.notify('showFindAlert')`
↓
Replace flows:
- `replace`: validate protection/read-only, trigger `beginAction` events, call `updateCell`
- `replaceAll`: build `addressCollection`, compute `replaceCount`, optionally show replace-confirm dialog, call `updateCellDetails` or `updateCell` (using `requestAnimationFrame` for UI pacing)
↓
UI updates: highlight selection, update count text, show alerts/dialogs
```
## Operations Handled
1. Initialization & Event Wiring
- UI wiring: attaches Find/Goto dialog requests, toolbar find widget, keyboard handlers (`findKeyUp`) and refresh on `activeSheetChanged`.
- Core wiring: listens for `find`, `replace`, `replaceAll`, `count`, and `findAllValues` notifications.
2. Search State & Parameters
- UI collects: `value`, `mode` (`Sheet|Workbook`), `isCSen` (case), `isEMatch` (exact), `searchBy` (`By Row|By Column`), `findOpt` (`next|previous`), `sheetIndex`.
- Core normalizes: `startRow`, `startCol`, `findVal` (lowercased when not case-sensitive), `sheets` array, and `sheetIdx` for current sheet.
3. Scanning & Matching
- Per-sheet scanning performed by `findNextOnSheet` / `findPrevOnSheet` using either row-major or column-major order.
- Skip hidden rows/columns (`isHiddenRow` / `isHiddenCol`) and protect/locked cells checks (`isLocked`, `isReadOnly`).
- `checkMatch` compares either the display text (`getDisplayText`) or raw cell value (`getCellVal`) depending on formatting and `isCSen`/`isEMatch` options.
- Handle wrapped searches across sheet boundaries when workbook mode provided.
4. Replace & Replace All
- Single `replace` validates protection and readonly state, optionally fires `beginAction` and `actionComplete` notifications, and calls `updateCell` to persist the replacement.
- `replaceAll` builds an `addressCollection`, matches each target (using regex/contains rules consistent with case/exact options), and applies changes asynchronously for large sets using `requestAnimationFrame` where available.
- `replaceAll` informs UI via `replaceAllDialog` with replacement counts and optionally triggers `actionBegin` with `beforeReplaceAll`.
5. Counting & Find All
- `totalCount` iterates sheet rows/cells and computes `count` and `totalCount` using the same matching heuristics as search.
- `findAllValues` returns a collection of matching cell addresses and values for UI consumption (Find All list).
6. UI Presentation & Interaction
- Full Find dialog: options, Replace, Replace All buttons, Goto tab, and result messages (`showFindAlert`, `replaceAllDialog`).
- Lightweight Find toolbar (`findToolDlg`): inline input, previous/next buttons, quick-count updates.
- Dialog lifecycle: beforeOpen/beforeClose/close hooks to maintain focus and selection.
## Validation & Safety
- Prevent operations on protected sheets: check `sheet.isProtected` and `protectSettings`; show `workBookeditAlert` or `workbookReadonlyAlert` as applicable.
- Respect read-only cells and locked columns/rows; abort or skip replacements when `isReadOnly` or `isLocked` prevents changes.
- Skip hidden rows/columns during scans to mimic visible search behavior.
- Handle formatted cells and localized numbers/dates: use `getFormattedCellObject` / `getNumericObject` and `getCellVal` to compare canonical values (decimal separators, date formatting).
- Avoid replacing while the workbook is in edit mode; UI prevents searching while in-cell edit state.
- Replace All uses batched updates and optional async pacing to avoid blocking the UI and to keep animation/visual updates responsive.
## Desired Outputs
User-Facing:
- Keyboard + dialog driven Find/Replace that mirrors typical spreadsheet apps (next/previous, match-case, whole-cell match).
- Clear Replace All confirmation with counts and final summary messages.
- Inline quick-find toolbar for fast navigation and a full dialog for advanced options.
System-Level:
- `FindAndReplace` (UI) and `WorkbookFindAndReplace` (Core) as distinct responsibilities: UI gathers options and renders dialogs; Core executes searches and mutations.
- Notifications used: `find`, `replace`, `replaceAll`, `count`, `findAllValues`, `goto`, `showFindAlert`, `replaceAllDialog`, `beginAction`/`actionComplete`.
- `addressCollection` (array of cell addresses) produced for Replace All / Find All flows.
- Match helpers: `getDisplayText`, `getCellVal` and `checkMatch` used consistently across count, find, and replace operations.
- Async-safe replace flow using `requestAnimationFrame` and `updateCellDetails`/`updateCell`.
## Implementation Notes / Integration Points
- UI components referenced: `Dialog`, `Toolbar`, `TextBox`, `DropDownList`, `CheckBox`, and a `FindDialog` wrapper class.
- Core helpers and utilities: `getCell`, `getCellAddress`, `getRangeIndexes`, `getCellIndexes`, `isHiddenRow`, `isHiddenCol`, `isLocked`, `isReadOnly`, `updateCell`, `updateCellDetails`, `getFormattedCellObject`, `getNumericObject`.
- Events the rest of the system may listen to: navigation (`goto`), replacement lifecycle (`beginAction` with `beforeReplace`/`beforeReplaceAll`, `actionComplete`), and UI alerts.