Connect Salesforce to Google Sheets
Why teams connect Salesforce and Google Sheets
A sheet is where a non-technical stakeholder wants a report, and where a team wants to keep a lookup table they can edit without a ticket. The manual version is a rep exporting a report each Monday, or an ops person copy-pasting a routing table into a flow's configuration.
- A pipeline or forecast sheet is refreshed on a schedule, with headers, formatting, and a last-updated cell, so a manager reads current data without a Salesforce seat
- A routing, pricing, or threshold sheet is read live by a flow, so a change the sales ops team makes takes effect on the next run with no deploy
- Rows are matched on a key column you choose, an ID or an email, rather than the row number, so an insert or a sort does not corrupt the sync
- Every write is a run you can inspect with the range and the values, so a bad refresh can be traced and run again
Worked example
The two flows most revenue-ops teams turn on first.
A refreshed open-pipeline sheet, and a routing sheet that drives lead assignment
One scheduled export flow, and one flow that reads the sheet as a config.
- Export trigger: a schedule every weekday at 07:00 in the sales leader's timezone.
- Query: Salesforce
Query (SOQL)for open opportunities with the owner, stage, amount, close date, and next step. - Write: Google Sheets clears
Pipeline!A2:Hand writes the result there with the values update operation, keeping the header row and a formula summary below untouched, and setsMeta!B1tonow(). - Routing trigger: a lead-routing flow starts on the Salesforce
New leadtrigger and continues when the lead has no assigned owner. - Read the table: read
Routing!A:Dfrom Google Sheets, then a Lookup step finds the row wherecountryandsegmentmatch and returnsowner_email. A catch-all row withcountry = ANYcovers the gaps. - Assign: a Salesforce update sets
OwnerIdfrom the resolved email. If no rule matches, the flow appends a row toUnrouted!A:Dfor sales ops to fix. - Reprocess: a second flow polls
Unroutedand re-runs assignment once a matching rule is added.
Field mapping
The starting map for the open-pipeline export. The header row is the schema; the key column is what a later update matches on.
| Salesforce field | Sheet column (header) | Notes |
|---|---|---|
Opportunity.Id | opp_id | Key column. A row update matches on this, never on position. |
Opportunity.Name | name | |
Account.Name | account | Resolved in the SOQL, written flat. |
Owner.Name | owner | |
StageName | stage | |
Amount | amount | Written as a number, not a currency string, so the sheet can sum it. |
CloseDate | close_date | Written as an ISO date string so Sheets parses it as a date. |
NextStep | next_step | Truncated to keep the row readable. |
| (flow-generated) | Meta!B1 last-updated | Set to now() on every successful refresh, outside the data range. |
For the routing sheet the direction reverses: the sheet's columns (country, segment, owner_email, notes) are the source, and the Lookup step returns owner_email for the flow to write to Lead.OwnerId.
What syncs, each direction
- Scheduled exports. Pipeline, forecast, activity, and renewal reports refreshed on a schedule with a last-updated stamp. (Salesforce to Sheets)
- Row-level updates. A specific opportunity or account row is updated in place when the record changes, found by the key column. (Salesforce to Sheets)
- Config tables. Routing rules, discount thresholds, territory maps, and enum lookups are read live by flows so a business team owns them. (Sheets to Salesforce)
- Bulk edits and imports. A sheet a team fills in, new leads, account updates, is validated row by row and upserted into Salesforce, with errors written to a status column. (Sheets to Salesforce)
Governance and audit
The same controls apply to this sync as to every other Neblex workload.
- Run history. Every write records the spreadsheet, the range, and the values. A failed refresh can be replayed from the step that failed, or simply run again.
- Approval on bulk import. A sheet-to-Salesforce import can include a Wait for form step, so a person reviews the rows before a mis-keyed column updates a thousand records.
- Scoped access. Google uses OAuth as an account that only has access to the sheets the flows need. Salesforce uses a permission set limited to the objects read and written.
- Environments. Build against a Salesforce sandbox and a copy of the sheet, then promote the same flow to production with the production spreadsheet.
Frequently asked questions
Can it update one row without rewriting the whole sheet?
Yes. The flow reads the range, finds the row by a key column such as an ID or an email, and writes only that row's cells. Matching on a key avoids relying on the row number, which shifts when rows are inserted or sorted.
How fresh is an exported sheet?
As fresh as the schedule. Common choices are every weekday morning for a pipeline sheet, or every 15 minutes for an ops dashboard. A row-level flow can also update a specific record on change.
Is a Google Sheet a safe place for a routing table?
For a small, human-maintained table, yes. Past tens of thousands of rows or with several flows writing it, move the data to a database and keep the sheet as a view.
What happens if the sheet is missing a required column?
Add an Assert Data Quality step that requires the columns, and the flow stops with an error naming what is missing rather than writing to the wrong place. Fix the header and run it again.
Can it react to a sheet edit as it happens?
Not natively. Google Sheets has no change webhook. The flow polls on a schedule, from every minute upward, or an Apps Script trigger in the sheet calls a Neblex Webhook trigger for an immediate start.
Connectors used
Salesforce
CRM & Sales
- Operations
- 1,296
- Operations with typed output
- 57.9%
- Change triggers
- 31 (poll)
- Signs in with
- OAuth 2.0 sign-in
Google Sheets
Productivity & Project Management
- Operations
- 17
- Operations with typed output
- 100%
- Change triggers
- Poll or inbound webhook
- Signs in with
- OAuth 2.0 sign-in
Bring one real integration
We will build it with you against your own systems, with the run log open.