How to take governed answers from semantic views and Cortex all the way into the Excel and Google Sheets models where your business actually runs.
If you run a Snowflake environment, you have probably lived this sequence. You spend a quarter building a clean, governed reporting layer. You stand up a semantic view so Cortex Analyst can answer questions in natural language. Leadership loves the demo. And then, on the first day of month-end close, someone on the finance team exports the whole thing to CSV, pastes it into a spreadsheet, and builds the real forecast there.
Nobody did anything wrong. The warehouse is where data is governed; the spreadsheet is where decisions are made. The problem is the gap between them, and every CSV export that crosses that gap silently discards your row access policies, your column masking, and your single definition of revenue.
This post is a practical walkthrough for closing that gap. By the end, you will have:
- A governed reporting layer with secure views and a semantic view that Cortex Analyst can reason over
- A least-privilege Snowflake role scoped for spreadsheet consumption
- Live, scheduled, query-pushdown delivery of that same governed data into Google Sheets and Excel using Coefficient, a Snowflake connected app
- Query tagging so you can see exactly what the spreadsheet tier costs you
| TLDR Snowflake Intelligence solves trusted answers. It does not solve where business users work, which is still Excel and Google Sheets. Instead of fighting that, extend the governed layer into it: build secure views and a semantic view in Snowflake, create a read-only role scoped to the reporting schema, and connect spreadsheets through a connected app that pushes queries down to Snowflake instead of duplicating data. Same definitions, same governance, zero CSV exports. |
The architecture in one picture
The pattern has four layers, and the important property is that nothing to the right of Snowflake ever becomes a second source of truth. Every layer reads through to the same governed objects.
| Raw + modeled data ANALYTICS.FINANCE tables (dbt, Dynamic Tables) | → | Governed layer Secure views, masking, row access policies | → | Intelligence Semantic view + Cortex Analyst | → | Last mile Live Sheets / Excel via connected app (pushdown) |
Figure 1: One governed path from modeled data to the spreadsheet. No exports, no copies.
Step 1: Build the governed reporting layer
Start with a schema that exists only to be consumed, separate from your modeling schemas. Everything downstream (BI, Cortex, spreadsheets) reads from here and nowhere else.
Step 2: Add a semantic view so Cortex Analyst speaks finance
Snowflake Intelligence is only as good as the semantics you give it. A semantic view declares your tables, relationships, dimensions, and metrics once, so Cortex Analyst answers “what was recognized revenue in EMEA last quarter” with your definition of recognized revenue, not a plausible guess.
Now analysts, agents, and anyone using Snowflake Intelligence gets consistent answers. Which makes it all the more painful if the last mile still runs on a CSV from three weeks ago. Let’s fix that part.
Step 3: Create a least-privilege role for spreadsheet consumption
Spreadsheet users should reach exactly one schema: the reporting layer. Create a dedicated role and a small warehouse so the workload is isolated and measurable.
Two things to notice. The role has no access to ANALYTICS.FINANCE or any raw schema, so even a hand-written query from a spreadsheet can only touch governed views. And because row access policies evaluate against CURRENT_ROLE(), the entitlements you defined in Step 1 follow the data into the sheet automatically.
Step 4: Connect the spreadsheet with query pushdown
This is where a connected app like Coefficient comes in. It runs as a sidebar inside Google Sheets & Excel and executes queries directly against Snowflake under the role you just created. The data lands in the grid, but it is never copied into a second system of record: every refresh is a fresh SELECT pushed down to Snowflake.
The setup is UI work rather than code:
- Install the add-in from the Google Workspace Marketplace or Microsoft AppSource and open the sidebar.
- Add a Snowflake connection: your Snowflake account name, database (ANALYTICS), and warehouse (SHEETS_WH), authenticating as FINANCE_SVC_USER. Prefer OAuth or key-pair authentication over passwords; Snowflake is retiring password-only sign-in in 2026. The connection runs under the user’s default role, which you pinned to SHEETS_READONLY above.
- Import data either through the visual query builder (pick the REVENUE_MONTHLY view, choose columns and filters) or with custom SQL when the sheet needs a specific shape:
— Import backing a board-pack pivot. {{business_unit}} is a SQL
— parameter linked to a spreadsheet cell, so editing that cell
— re-runs the query in Snowflake with the new value.
SELECT close_month, region, product_line,
recognized_revenue, billed_amount
FROM ANALYTICS.REPORTING.REVENUE_MONTHLY
WHERE close_month >= DATEADD(month, -12, CURRENT_DATE())
AND business_unit = {{business_unit}}
ORDER BY close_month;
- Set a refresh schedule on the import: hourly (down to every hour), daily, or weekly, with a manual refresh button in the sheet header for ad hoc pulls. Monthly Snapshots can archive each month-end state to its own tab for audit.
From the finance team’s perspective nothing changed: they are still in their spreadsheet, with their formulas and their pivot tables. From your perspective everything changed: the numbers in that model are now the same numbers Cortex Analyst gives, refreshed on a schedule, filtered by the same row access policy, with zero CSVs in flight.
Step 5: Make the spreadsheet tier observable
Because all spreadsheet traffic flows through one role and one warehouse, measuring it is a single query against ACCOUNT_USAGE:
In practice this tier is cheap. Reporting views are aggregated, the warehouse is an XSMALL that suspends after 60 seconds, and scheduled refreshes batch naturally. What you get back is significant: every refresh in QUERY_HISTORY is a spreadsheet that did not become a stale, ungoverned copy of your data.
Why this complements Snowflake Intelligence rather than competing with it
It is tempting to treat natural-language analytics and spreadsheets as rivals for the same users. They are not. Cortex Analyst and Snowflake Intelligence are how people ask questions of governed data. Spreadsheets are where people operate on it: building driver-based forecasts, reconciling billing, running headcount scenarios. The semantic view you built in Step 2 serves the first need. The live connection you built in Step 4 serves the second. Both read the same secure views, so for the first time the answer in the AI chat and the number in cell C14 of the board pack agree by construction.
Wrapping up
What you built, in order: a secure reporting schema with row access policies, a semantic view for Cortex Analyst, a least-privilege role and isolated warehouse for spreadsheet workloads, a live pushdown connection into Sheets and Excel with scheduled refresh, and an observability query to keep it honest.
The takeaway for builders: the last mile is not a tooling problem to ignore or a user habit to break. It is a surface to govern. Snowflake already gives you the primitives; the only decision is whether business users reach the governed layer directly, or through CSVs that quietly undo all of it.