Edit Google Sheets
Append rows, update cells, and add or remove rows and columns in a Google Sheet.
Overview
The Edit Google Sheets node performs structural and value edits against a Google Sheets spreadsheet using a connected Google account. Pick the operation you need from a single node — append data to the bottom, overwrite a range of cells, or insert/delete blank rows and columns.
Use it to:
- Append new rows of data after each item processed by the workflow
- Overwrite a specific range with computed values
- Append objects to a table where keys map to the table's headers
- Update specific rows in a table by ID column or by row number
- Insert blank rows or columns ahead of writing
- Delete a contiguous range of rows/columns, or specific row/column numbers
All operations batch automatically. Per-item parameters are evaluated for every input item, then collected and sent to Google Sheets in the minimum number of API calls (almost always one, regardless of how many input items the node receives). The Batch Size setting is irrelevant for this node.
For operations on Lido's own spreadsheets (worksheet management, grid resizing, etc.), use Edit Spreadsheet instead.
Parameters
| Parameter | Description | Required |
|---|---|---|
| Credential | Google account credential (the Google Drive / googleDocs type used by the spreadsheet formulas) | Yes |
| Spreadsheet URL | Google Sheets URL to operate on | Yes |
| Operation | Which edit to perform (see below) | Yes |
Once Credential and Spreadsheet URL are filled in, every operation's Worksheet field becomes a populated dropdown (worksheet names are fetched live from the spreadsheet).
The googleDocs credential type uses Google's per-file (drive.file) scope. To reach a spreadsheet without going through the Google Picker each time, share the spreadsheet with files@lido.app with editor permissions — the node falls back to Lido's shared service account when the per-file scope can't reach the file.
Operations
Append Rows
Adds new rows after the last row of data in the worksheet (or in a specific table area if Start Cell is set). Maps to values.append. Across input items: rows targeting the same (worksheet, start cell) pair are concatenated and sent in one API call per unique pair (usually one).
| Parameter | Description | Required |
|---|---|---|
| Worksheet | Worksheet to append to (dropdown, populated from the spreadsheet) | Yes |
| Start Cell | Optional cell within the worksheet whose data area Google should append after (e.g. B3). Leave blank to use the whole worksheet | No |
| Values | 2D array of cell values, one inner array per row | Yes |
Update Cells
Writes a 2D array of values starting at a single cell. Maps to values.batchUpdate; the size of the write area is inferred from the shape of Values (a 2x3 array starting at A1 writes A1:C2). Across input items: every (cell, values) pair is bundled into one batchUpdate call.
| Parameter | Description | Required | Default |
|---|---|---|---|
| Worksheet | Worksheet to write to (dropdown) | Yes | — |
| Start Cell | Top-left cell to start writing at (e.g. A1, B3) | No | A1 |
| Values | 2D array of cell values (rows of columns) | Yes | — |
Append to Table
Appends rows to a table whose first header is at the (Worksheet, Start Cell) pair. The node reads the header row, looks up each data key's column, and appends rows below the existing data. Across multiple input items, all rows are combined into a single values.append call.
| Parameter | Description | Required | Default |
|---|---|---|---|
| Worksheet | Worksheet containing the table (dropdown) | Yes | — |
| Start Cell | Cell of the first header (e.g. A1, B3). Header row, header column, and data area are derived from it | No | A1 |
| Data | A single object or an array of objects. Keys are matched to header names; unknown keys are ignored | Yes | — |
Example data per item:
[
{ "Name": "Alice", "Email": "alice@example.com", "Status": "active" },
{ "Name": "Bob", "Email": "bob@example.com", "Status": "pending" }
]
If the table headers are Name | Email | Status | Notes, two new rows are appended; the Notes column is left empty. With 100 input items each producing one such row, the node makes one values.append call with all 100 rows.
Update in Table
Updates rows in an existing table. Each input item updates one row, identified either by the value of an ID column or by an explicit row number expression. Only keys present on the input object are written; cells whose header isn't in the object are left untouched. Across all input items, updates are combined into a single values.batchUpdate call.
| Parameter | Description | Required | Default |
|---|---|---|---|
| Worksheet | Worksheet containing the table (dropdown) | Yes | — |
| Start Cell | Cell of the first header (e.g. A1, B3) | No | A1 |
| Data | A single object representing the row to update. Array data per item is rejected — split into multiple items if needed | Yes | — |
| Update By | ID Column (default) or Row Number | Yes | idColumn |
In ID Column mode:
| Parameter | Description | Required |
|---|---|---|
| ID Field | Header name to match on. The matching row is found by looking up the object's value in this header column | Yes |
In Row Number mode:
| Parameter | Description | Required |
|---|---|---|
| Row Number | 1-based spreadsheet row number to update (expression). Use {{$item.spreadsheetRow}} (from Import Table) or any per-item field | Yes |
Example item data (ID Column, ID Field = Email):
{ "Email": "alice@example.com", "Status": "verified" }
The first row with matching Email is updated; only Status changes. With 100 items each carrying one update, the node makes one batchUpdate call.
Insert Blank Rows
Maps to spreadsheets.batchUpdate with insertDimension. Across items: all insertions (across worksheets) are combined into one batchUpdate. Within each worksheet, ranges are applied highest-index-first so user-supplied 1-based indices remain stable across the batch.
| Parameter | Description | Required | Default |
|---|---|---|---|
| Worksheet | Target worksheet (dropdown) | Yes | — |
| Row Index | 1-based row index where blank rows should be inserted | Yes | — |
| Number of Rows | How many blank rows to insert | No | 1 |
Delete Rows
Two selection modes — pick a contiguous range, or list specific row numbers. Maps to spreadsheets.batchUpdate with deleteDimension. Across items: all deletions (across worksheets) are combined into one batchUpdate, applied highest-index-first within each worksheet.
| Parameter | Description | Required | Default |
|---|---|---|---|
| Worksheet | Target worksheet (dropdown) | Yes | — |
| Selection mode | Contiguous range (default) or Specific row numbers | Yes | range |
In Contiguous range mode:
| Parameter | Description | Required | Default |
|---|---|---|---|
| Start Row Index | 1-based row index of the first row to delete | Yes | — |
| Number of Rows | How many rows to delete | No | 1 |
In Specific row numbers mode:
| Parameter | Description | Required |
|---|---|---|
| Row Numbers | Array of 1-based row numbers, e.g. [2, 5, 9]. Order doesn't matter; duplicates and gaps are handled | Yes |
Consecutive numbers are merged into a single delete and applied in descending order so the indices you supply stay valid across the batch.
Insert Blank Columns
Same batchUpdate + insertDimension model as Insert Blank Rows. Across items: combined into one batchUpdate.
| Parameter | Description | Required | Default |
|---|---|---|---|
| Worksheet | Target worksheet (dropdown) | Yes | — |
| Column Index | 1-based column index where blank columns should be inserted | Yes | — |
| Number of Columns | How many blank columns to insert | No | 1 |
Delete Columns
Same two-mode pattern as Delete Rows. Across items: combined into one batchUpdate.
| Parameter | Description | Required | Default |
|---|---|---|---|
| Worksheet | Target worksheet (dropdown) | Yes | — |
| Selection mode | Contiguous range (default) or Specific column numbers | Yes | range |
In Contiguous range mode:
| Parameter | Description | Required | Default |
|---|---|---|---|
| Start Column Index | 1-based column index of the first column to delete | Yes | — |
| Number of Columns | How many columns to delete | No | 1 |
In Specific column numbers mode:
| Parameter | Description | Required |
|---|---|---|
| Column Numbers | Array of 1-based column numbers, e.g. [2, 5, 9]. Order, duplicates, gaps all handled | Yes |
Settings
| Setting | Description |
|---|---|
| Execution Mode | Once per item (default) or Once — Once only processes the first input item |
| Output Mode | How to output results when running once |
| Batch Size | Ignored — this node always combines all items into one Sheets API call |
| Stop on Error | Stop workflow on operation failure |
Output
{
"status": {
"operation": "appendRows",
"success": true,
"message": "appendRows succeeded"
}
}
Access in expressions:
{{$item.data.status.operation}}— Which operation ran{{$item.data.status.success}}— Whether it succeeded{{$item.data.status.message}}— Operation summary
Examples
Append a Row per Processed Item
[Google Drive Trigger] → [Data Extractor] → [Edit Google Sheet (Append Rows)]
Configure Append Rows with:
- Range:
Sheet1 - Values:
[[ "{{$item.data.fileName}}", "{{$item.data.extractedTotal}}" ]]
Each item produces a new row at the bottom of Sheet1.
Overwrite a Header Row
[Manual Trigger] → [Edit Google Sheets (Update Cells)]
- Worksheet:
Sheet1 - Start Cell:
A1 - Values:
[[ "Name", "Email", "Status" ]]
Append Records by Header Name (one row per item, batched)
[Import Table] → [Process per row] → [Edit Google Sheets (Append to Table)]
- Worksheet:
Customers - Data:
{{$item}}(one{Name, Email, Status}object per item)
100 input items become a single values.append call with 100 rows. Keys not in the table headers are ignored, so it's safe to pipe through extra fields.
Update Rows by ID
[Import Table] → [Filter] → [Edit Google Sheets (Update in Table, ID Column = "Email")]
- Worksheet:
Customers - Update By:
ID Column - ID Field:
Email - Data:
{{$item}}(each item's data hasEmailplus the columns to overwrite)
One row updated per item; all updates batched into one values.batchUpdate call. Cells whose header isn't included in the data object are left alone — safe for partial updates.
Update Rows by Row Number
[Import Table (with row numbers)] → [Process...] → [Edit Google Sheets (Update in Table, Row Number = {{$item.spreadsheetRow}})]
- Worksheet:
Customers - Update By:
Row Number - Row Number:
{{$item.spreadsheetRow}}(or any per-item field) - Data:
{{$item}}(the columns to overwrite)
Import Table attaches each row's spreadsheet row number; the Row Number expression evaluates per item, and all updates batch into one API call.
Make Room Before Bulk Insert
[Aggregate (count)] → [Edit Google Sheet (Insert Blank Rows)] → [Edit Google Sheet (Update Cells)]
- Count how many rows you need.
- Insert that many blank rows at the target index.
- Write data into the newly created range.
Delete Failed Rows
[Import Table] → [Filter (status = "error")] → [Aggregate] → [Edit Google Sheet (Delete Rows, Specific row numbers)]
- Selection mode: Specific row numbers
- Row Numbers:
{{$item.data.failedRowNumbers}}
Failed row numbers don't have to be consecutive — any combination is handled.
Authentication
Requires a connected Google Drive (a.k.a. googleDocs) credential — the same credential type used by the APPENDTOGOOGLESHEET and UPDATECELLINGOOGLESHEET spreadsheet formulas. This credential uses Google's per-file drive.file OAuth scope, so it can only reach files the user has explicitly authorized. There are two ways to grant access to a sheet:
- Share with
files@lido.app— give Lido's shared service account editor permissions on the spreadsheet. The node detects 404s and retries the call as the service account. Recommended for workflows that operate on many sheets. - Pick via Google Picker — the picker grants per-file authorization for the duration of the credential.
Tips
- Indices are 1-based to match what you see in the Google Sheets UI (row 1, column 1).
- For
Append Rows, the range can be just a worksheet name (e.g.Sheet1) — Google Sheets finds the last row of data automatically. - For
Update Cells, the values 2D array shape must fit the range — extra rows/columns are ignored, missing ones leave existing cells unchanged. - For
Append to TableandUpdate in Table, the headers are read from the spreadsheet at run time. Keys that don't match a header are ignored, so it's safe to pass through extra metadata. - Every operation batches across input items into one Sheets API call (Append Rows is one call per unique (worksheet, Start Cell) pair — usually one). 100 items → 1 HTTP round-trip, not 100. The Batch Size setting has no effect on this node.
- All items must resolve to the same credential, spreadsheet URL, worksheet, and (for table operations) Start Cell. Per-item variation throws an error.
Update in Tablerequires exactly one row per item — array data is rejected. Split your data into multiple items if you need to update multiple rows.Update in Tableonly writes the cells whose key is present in the data object — other cells in the row are not cleared. To explicitly clear a cell, include its header with an empty string.Update in Tablewith ID Column mode requires every input item's data to include the ID field. Duplicates in the ID column resolve to the first matching row.Start Cell's column part is meaningful for table operations: tables that don't start at column A are supported by setting e.g.B3.- The Worksheet dropdown calls the server with the same
googleDocspathway as the write operations, so it benefits from the samefiles@lido.appfallback. - Delete operations in
Specific row numbersmode are batched into a single API call regardless of how scattered the indices are. - Each workflow item runs its own API call. For high-volume appending, consider aggregating items first and passing a single 2D array of values.