Modifying Data

When adding rows, deleting rows, or modifying cell values, always use the functions documented in this API. Use addRow() to add a row, deleteBy() or deleteSelected() to delete a row, and the setValue() family of functions to modify values. Even though setValue will call putValue and that may be defined by the plugin itself, do not modify rows manually. This also means that rows should not be added or removed from sheet.rows directly.

Always use these functions, as they do some important bookkeeping for features like deferred modifications.


Return new blank row compatible with this sheet. Overrideable.

visidata.TableSheet.editCell(self, vcolidx=None, rowidx=None, value=None, **kwargs)

Call vd.editText for the cell at (rowidx, vcolidx). Return the new value, properly typed.

  • rowidx: numeric index into self.rows. If negative, indicates the column name in the header.

  • value: if given, the starting input; otherwise the starting input is the cell value or column name as appropriate.

  • kwargs: passthrough args to vd.editText.

visidata.TableSheet.deleteBy(sheet, func, commit=False, undo=True)

Delete rows on sheet for which func(row) returns true. Return number of rows deleted. If sheet.defer is set and commit is True, remove rows immediately without deferring. If undo is set to True, add an undo for deletion.

Deferred Modification

On sheets where putValue changes the source directly, like SQLite and DirSheet, it would be undesirable for modifications to happen immediately. For these cases, the modifications are cached, shown visually on the sheet in a different color, and deferred until they are committed with an explicit commit-sheet (bound to z Ctrl+S).

Sheet types can add this deferring behavior by setting their defer attribute to True (either on the class type or on the individual sheet instance), but they may have to implement their own Sheet.putChanges.

visidata.Column.getSourceValue(col, row)

For deferred sheets, return value for row in this col as it would be in the source, without any deferred modifications applied.

visidata.TableSheet.commit(sheet, *rows)

Commit all deferred changes on this sheet to original sheet.source.


Return changes made to deferred sheets that have not been committed, as a tuple (added_rows, modified_rows, deleted_rows). modified_rows does not include any added_rows or deleted_rows.

  • added_rows: { rowid:row, … }

  • modified_rows: { rowid: (row, { col:val, … }), … }

  • deleted_rows: { rowid: row }

rowid is from Sheet.rowid(row). col is an actual Column object.


Commit changes to sheet.source. May overwrite source completely without confirmation. Overrideable.


When a function adds, removes, or modifies data–including metadata–as part of a user action, it needs to ensure that operation is undoable. For many operations, this is already handled internally by existing functions. For instance, if the user executes a command which modifies cell values via Column.setValues, the undo command will undo those modifications automatically.

If a new operation changes the data or metadata and undo is not already handled by existing functionality, then the new operation needs to call addUndo() to add an undo function to the currently executing command.

For performance reasons, undo functions should generally be as large as possible. For instance, Column.setValues adds a single undo function to undo all changes in one go. By contrast, Column.setValue does not add an undo function at all. Therefore, commands should always use Column.setValues, unless for some special reason the modification should not be undoable. Undo functions, however, should use Column.setValue, so it doesn’t add an undo function for the undo itself. (Redo is handled by replaying the previous command, not by undoing the undo).

visidata.vd.addUndo(undofunc, *args, **kwargs)

On undo of latest command, call undofunc(*args, **kwargs).

visidata.vd.addUndoSetValues(cols, rows)

Add undo function to reset values for rows in cols.



Sheet.editCell requires row and column indexes for its parameters. For example, cursorVisibleColIndex and cursorRowIndex are sheet attributes that can be passed to Sheet.editCell.

Sheet.addCommand('e', 'edit-cell',
                 'cursorCol.setValues([cursorRow], editCell(cursorVisibleColIndex))',
                 'edit contents of current cell')
# equivalent to Sheet.deleteSelected but slower