type
TCellEdit_ = record
Row, Col: integer;
OldValue, NewValue: variant;
end;
TUndoRedoList = array of TCellEdit_;
var
UndoStack, RedoStack: array of TUndoRedoList;
OldCellValue, NewCellValue: variant;
procedure Undo;
var
LastActions: TUndoRedoList;
Act: TCellEdit_;
i: integer;
begin
if Length(UndoStack) = 0 then Exit;
// Pop the last group of actions
LastActions := UndoStack[High(UndoStack)];
SetLength(UndoStack, Length(UndoStack) - 1);
// Push the whole group to Redo stack (important for batch undo)
SetLength(RedoStack, Length(RedoStack) + 1);
RedoStack[High(RedoStack)] := LastActions;
// Revert all actions in the group
for i := 0 to High(LastActions) do
begin
Act := LastActions[i];
Form1.WorksheetGrid.Cells[Act.Col, Act.Row] := Act.OldValue;
end;
// Optional: if you want the edit box to show the current (now old) value
if Length(LastActions) > 0 then
begin
Act := LastActions[High(LastActions)]; // last edited cell
end;
end;
procedure Redo;
var
LastActions: TUndoRedoList;
Act: TCellEdit_;
i: integer;
begin
if Length(RedoStack) = 0 then Exit;
// Pop the last group from redo
LastActions := RedoStack[High(RedoStack)];
SetLength(RedoStack, Length(RedoStack) - 1);
// Push the whole group back to Undo stack
SetLength(UndoStack, Length(UndoStack) + 1);
UndoStack[High(UndoStack)] := LastActions;
// Reapply all actions
for i := 0 to High(LastActions) do
begin
Act := LastActions[i];
Form1.WorksheetGrid.Cells[Act.Col, Act.Row] := Act.NewValue;
end;
// Update edit box to show the new value of the last edited cell
if Length(LastActions) > 0 then
begin
Act := LastActions[High(LastActions)];
end;
end;
procedure TForm1.WorksheetGridEditingDone(Sender: TObject);
var
Action_: TCellEdit_;
CurrentValue: variant;
begin
CurrentValue := WorksheetGrid.Cells[WorksheetGrid.Col, WorksheetGrid.Row];
edit1.Text := vartostr(OldCellValue);
// Only record if value actually changed
if vartostr(CurrentValue) <> vartostr(OldCellValue) then
begin
Action_.Row := WorksheetGrid.Row;
Action_.Col := WorksheetGrid.Col;
Action_.OldValue := OldCellValue;
Action_.NewValue := CurrentValue;
// Add a new group containing this single edit
SetLength(UndoStack, Length(UndoStack) + 1);
SetLength(UndoStack[High(UndoStack)], 1);
UndoStack[High(UndoStack)][0] := Action_;
// Clear redo stack when new edit is made (standard undo/redo behavior)
SetLength(RedoStack, 0);
//ShowMessage('add data');
end;
end;
procedure TForm1.WorksheetGridSelectCell(Sender: TObject; aCol, aRow: integer;
var CanSelect: boolean);
begin
OldCellValue := WorksheetGrid.Cells[aCol, aRow];
end;