The history is held per worksheet, by ws.Actions (an ActionManager).
Using it
using unvell.ReoGrid.Core;
if (ws.Actions.CanUndo) ws.Actions.Undo();
if (ws.Actions.CanRedo) ws.Actions.Redo();
Console.WriteLine(ws.Actions.UndoName); // name of the operation undo would reverse
Console.WriteLine(ws.Actions.RedoName);
With a control, control.Undo() / control.Redo() / control.CanUndo / control.CanRedo
call the same thing. Ctrl+Z and Ctrl+Y are wired up by default.
Getting an edit into the history
Core mutations do not depend on the history. Wrap the operation you want recorded in a recorder.
// wrapping an ordinary mutation is all it takes to get it into the history
ws.RecordCell("Enter value", 0, 0, () => ws.SetNumber(0, 0, 100));
ws.RecordRange("Apply format", RangePosition.Parse("A1:C10"), () =>
{
for (int r = 0; r < 10; r++)
ws.SetNumberFormat(r, 0, "#,##0");
});
| Recorder | Covers |
|---|---|
RecordCell(name, row, col, mutate) | One cell |
RecordRange(name, rect, mutate, parts) | A range |
RecordAxis(name, target, rows, cols, mutate) | Row and column metadata |
RecordEdit(name, target, spec, mutate) | The general form, for naming the target precisely |
Calling ws.SetNumber(...) directly, without wrapping, changes the value but does not
record it. Everything done through a control is wrapped internally, so edits made from the
UI are recorded for you.
What gets captured
The history is a journal: it takes a snapshot before and after the operation and records the difference.
Captured — cells (values, styles, number formats, rich text, formulas), borders, merges, cell types, conditional formats, and row and column metadata.
Capture is sparse, so the cost is proportional to the range you edited. The sheet is never walked from end to end.
Insert and delete
Inserting and deleting rows and columns is handled specially.
- Insert — undone by the inverse operation (a delete)
- Delete — the band being removed is captured, clamped to the used range, and restored on
undo; every formula is then swept to heal
#REF!
Grouping several operations
An operation that is internally two steps — cut then paste — is combined into an
ActionGroup and becomes one step. To the user, a single Ctrl+Z reverses both.
Capacity and events
ws.Actions.Capacity = 200; // 100 by default
ws.Actions.Clear();
ws.Actions.Changed += () => Console.WriteLine("history changed");
bool hasHistory = ws.HasActions; // answers without creating an ActionManager
Beyond the capacity, the oldest entries are dropped.
ws.HasActions answers without creating an ActionManager. On a headless sheet that has
never been edited, the manager is never built.
The control reports the same thing through its HistoryChanged event. Use it to enable and
disable toolbar buttons.
What is not recorded
- Outlines (grouping and ungrouping)
- Loading a file (the whole workbook is replaced)
- View operations (zoom, freeze, scrolling)
Per sheet
The history is per worksheet. Switching sheets switches which history is in play.