# Google Sheets

Read, add and update rows in Google Sheets.

## Connect Google Sheets

1. In the sidebar, open **Connections** and press **Add connection**.
2. Type `sheets` and choose **Google Sheets**.
3. Press **Sign in with Google**.
4. Choose your account in Google’s window and allow access.

You should see **Signed in as** and the account’s address. GoRunner can then see, edit and create its spreadsheets.

You can also connect from a step: under **Connection**, press **New**.

**What if it says “Google sign-in isn’t set up here”?**

This installation has no Google app yet. An admin of the installation sees **Set up Google sign-in** instead, and sets it up once for everyone:

1. In Google Cloud, create an OAuth client of type **Web application**, and turn on the API for Google Sheets.
2. In GoRunner, copy the **Redirect address to add in Google Cloud**, and add it to the client.
3. Paste the **Client ID** and **Client secret**, then press **Save and sign in**.

Publish the app in Google Cloud. An app left in Testing signs everyone out after 7 days.

Everyone else sees who to ask. Until it is set up, **Paste an access token instead** lets you try a step. A pasted token lasts about an hour and can’t renew itself.

[Set up Google sign-in for connections](https://docs.gorunner.io/self-host/oauth-apps)

**Can I use my own Google app?**

Yes. In the sheet, open **Use your own Google app** and paste its **Client ID** and **Client secret**. Add the **Redirect address to add in Google Cloud** to your app first. The connection then signs in through your app instead of the installation’s.

[Connections](https://docs.gorunner.io/build/connections) says how to sign in again, rename or delete it. In a product that embeds GoRunner, **Add connection** can be missing: then [your provider makes connections](https://docs.gorunner.io/embed/customer-connections) for you.

## Start a workflow

Add a trigger and choose **Google Sheets**. The trigger uses the same connection as the steps.

### On Row Added/Updated

Polls the sheet (about once a minute) and fires for each new or changed row. The header row becomes the row's keys.

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab name to watch.
- **Trigger On · Optional**: When to fire: a new row, a changed row, or either. Options: Row Added, Row Updated, Row Added or Updated. Default: Row Added.
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.
- **First Data Row · Optional**: 1-indexed first row of data. Default: 2.
- **Row Identity Column (optional) · Optional**: Header of a column whose value identifies each row, such as ID or Email. Blank = rows are identified by their row number, so inserting, deleting or sorting rows fires every row that moved (as updated, and an insert as added with the last row's data). With a column set, rows are matched by its value wherever they move, and a row fires once that cell is filled.

A later step can use its data, such as `{{trigger.change_type}}`, `{{trigger.row_number}}`. See [Use data from earlier steps](https://docs.gorunner.io/build/use-data-from-earlier-steps).

## Do things in Google Sheets

Add a **Google Sheets** step, choose a **Resource**, then an **Operation**. Choose a row to see its fields.

- [Spreadsheet](https://docs.gorunner.io/apps/google-sheets#fields-f-spreadsheet): Create · Get · Delete
- [Sheet (Rows)](https://docs.gorunner.io/apps/google-sheets#fields-f-sheet): Get Rows · Append Row(s) · Update Row(s) · Append or Update Row(s) · Clear · Create Sheet · Delete Sheet · Delete Rows or Columns

Later steps read a step’s output by its name: see [Use data from earlier steps](https://docs.gorunner.io/build/use-data-from-earlier-steps).

Not in your list? See [When an app isn’t here](https://docs.gorunner.io/apps/when-an-app-isnt-here#q-not-in-list).

## For developers

In the API, which calls apps pieces, Google Sheets is `pieceId: "googlesheets"` with `actionId: "googlesheets"`, set by `resource` and an `operation_…` field, such as `operation_sheet`. Its trigger is `googlesheetstrigger` / `googlesheets_poll`. [Get an app](https://docs.gorunner.io/api/apps/get-app) returns every field.

It can change something outside the run (`writes_external`). See [How versions and side effects work](https://docs.gorunner.io/apps#q-versions).

### Google Sheets › Spreadsheet

### Create

- **Title · Required**: Name of the new spreadsheet.
- **Initial Sheet Names · Optional**: Comma-separated names for the initial sheets/tabs (blank = a default Sheet1).
- **Locale · Optional**: Spreadsheet locale, such as en_US.
- **Recalculation Interval · Optional**: How often volatile functions recalculate. Options: Default, On change, Every minute, Every hour. Default: Default.

### Get and Delete

- **Spreadsheet · Required**: The spreadsheet's URL or ID.

### Google Sheets › Sheet (Rows)

### Get Rows

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab (search by name, or type its title).
- **Filter Column · Optional**: Optional: only return rows where this column equals the value below (blank = all rows).
- **Filter Value · Optional**: The value to match in the filter column.
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.
- **First Data Row · Optional**: 1-indexed first row of data (below the header). Default: 2.
- **Range (A1) · Optional**: Optional A1 range to read (such as A:F). Blank = the whole sheet.
- **Return Only First Match · Optional**: When filtering, return only the first matching row. Off by default.
- **Filters (JSON) · Optional**: Multiple column filters, such as [{"column":"Status","value":"open"},{"column":"Owner","value":"me"}]. Overrides the single Filter above.
- **Combine Filters · Optional**: Whether a row must match all filters (AND) or any (OR). Options: AND (all), OR (any). Default: AND (all).
- **Output Formatting · Optional**: How cell values are returned. Options: Unformatted, Formatted (as displayed), Formula. Default: Unformatted.
- **Date/Time Output · Optional**: How date/time cells are returned. Options: Formatted string, Serial number. Default: Formatted string.
- **Read Rows Until · Optional**: Read to the last row in the sheet, or stop at the first fully-empty row. Options: Last row in sheet, First empty row. Default: Last row in sheet.

### Append Row(s)

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab (search by name, or type its title).
- **Data · Required**: The row(s) to write: a JSON object {"Name":"Ada"} or an array of objects. Keys map to column headers.
- **Value Input Mode · Optional**: USER_ENTERED parses values like a user typing (formulas, dates); RAW stores them verbatim. Options: User Entered (parse), Raw. Default: User Entered (parse).
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.
- **Handle Extra Fields · Optional**: What to do with data keys that aren't existing columns. Options: Add as new column, Ignore, Error. Default: Add as new column.
- **Append (don't fill gaps) · Optional**: On = add after the table that holds your data, inserting rows; off = write into the first empty row below the data. Either way, two appends at the same time each keep their rows. Off by default.

### Update Row(s)

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab (search by name, or type its title).
- **Data · Required**: The row(s) to write: a JSON object {"Name":"Ada"} or an array of objects. Keys map to column headers.
- **Column to Match On · Required**: The header whose value identifies which row to update (such as id or email), spelled exactly as in the header row.
- **Value Input Mode · Optional**: USER_ENTERED parses values like a user typing (formulas, dates); RAW stores them verbatim. Options: User Entered (parse), Raw. Default: User Entered (parse).
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.
- **First Data Row · Optional**: 1-indexed first row of data (below the header). Default: 2.
- **Handle Extra Fields · Optional**: What to do with data keys that aren't existing columns. Options: Add as new column, Ignore, Error. Default: Add as new column.

### Append or Update Row(s)

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab (search by name, or type its title).
- **Data · Required**: The row(s) to write: a JSON object {"Name":"Ada"} or an array of objects. Keys map to column headers.
- **Column to Match On · Required**: The header whose value identifies which row to update (such as id or email), spelled exactly as in the header row.
- **Value Input Mode · Optional**: USER_ENTERED parses values like a user typing (formulas, dates); RAW stores them verbatim. Options: User Entered (parse), Raw. Default: User Entered (parse).
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.
- **First Data Row · Optional**: 1-indexed first row of data (below the header). Default: 2.
- **Handle Extra Fields · Optional**: What to do with data keys that aren't existing columns. Options: Add as new column, Ignore, Error. Default: Add as new column.
- **Append (don't fill gaps) · Optional**: On = add after the table that holds your data, inserting rows; off = write into the first empty row below the data. Either way, two appends at the same time each keep their rows. Off by default.

### Clear

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab (search by name, or type its title).
- **Range to Clear (A1) · Optional**: Optional A1 range to clear (such as A2:F). Blank = the whole sheet.
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.
- **Keep Header Row · Optional**: When clearing the whole sheet, preserve the header row (row 1). Off by default.

### Create Sheet

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **New Sheet Name · Required**: Name for the new sheet/tab to add.
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.
- **Position Index · Optional**: 0-based position of the new sheet among the tabs.
- **Hidden · Optional**: Hide the new sheet. Off by default.
- **Right-to-Left · Optional**: Lay the sheet out right-to-left. Off by default.
- **Tab Color (hex) · Optional**: Tab colour as a hex code, such as 0aa55c.

### Delete Sheet

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab (search by name, or type its title).
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.

### Delete Rows or Columns

- **Spreadsheet · Required**: The spreadsheet's URL or ID.
- **Sheet · Required**: The sheet/tab (search by name, or type its title).
- **Delete · Required**: Whether to delete rows or columns. Options: Rows, Columns. Default: Rows.
- **Start Position · Required**: 1-indexed first row/column to delete (1 = row 1 / column A; row 1 is usually the header). Default: 1.
- **How Many · Required**: Number of rows/columns to delete. Default: 1.
- **Header Row · Optional**: 1-indexed row that holds the column names. Default: 1.

Source: https://docs.gorunner.io/apps/google-sheets
