Skip to main content

Undo and redo

Press Ctrl+Z to reverse the last operation, and Ctrl+Shift+Z (or Ctrl+Y) to re-apply it. The same commands are in the Edit menu. On macOS, use Cmd instead of Ctrl.

Undo is scoped to what you are looking at: Ctrl+Z reverses the last operation on the current table or view, never one you performed somewhere else. That includes tables shown inside the current view, such as the results of a function. Switching to another view and back brings the history with you.

What can be undone​

AreaOperations
Grid editingEditing a cell, clearing a cell (Del), toggling a checkbox, pasting a cell or a block
RowsRemoving selected rows, the grid's − and + icons, Edit | Add Rows
ColumnsRemoving columns, changing a column's type, adding or editing a formula column, renaming a column and editing its properties
ValuesFind and Replace
MetadataColor coding and format changes from the column menu
SelectionReset Selection Filter (Esc)
LayoutClosing a viewer (it comes back where it was) or a view, adding a viewer, View | Layout | Clear
AIOperations performed by the assistant (add/close viewer, change properties, filter, select)

Everything else — sorting, filtering, creating new tables, and anonymizing data — is not recorded. Operations that produce a new table are non-destructive, so nothing is lost by not undoing them.

Editors with their own undo​

Sketchers, the form designer, molecule and sequence editors, and graph editors keep their own undo stacks. While the focus is inside one of them, Ctrl+Z goes to that editor; everywhere else it goes to the platform. Ctrl+Z in a text field always does what it does in any browser — it undoes typing, and it does not touch the table.

While a dialog is open, Ctrl+Z never reaches the table. A dialog is its own editing session, and undoing something underneath it while you are filling in a form is never what you meant. Close the dialog first.

For developers​

Plugins can make their own operations undoable:

const before = column.get(0);
column.set(0, 42);
DG.UndoService.push('Set value', () => column.set(0, before), {
redo: () => column.set(0, 42),
context: column.dataFrame
});
  • grok.shell.undo() / grok.shell.redo() — run the commands programmatically
  • grok.shell.canUndo / canRedo — enablement
  • grok.shell.onUndo / onRedo — observables carrying {name, context}
  • DG.UndoService.ownScope(element) — claim Ctrl+Z for an embedded editor while focus is inside it, instead of installing a document-level key handler

Records hold values, not row indexes of live objects: capture what you need before the change, and pass context so the record is released with its table.

See also: Keyboard shortcuts.