HOW-TO · DATA SYNC

Get an Excel workbook into BigQuery without a script.

By Chris Davidson, founder of yForest · Updated September 26, 2026

A budget workbook with three tabs doesn't need a Python script to get into BigQuery. It needs a mapped sync.

Start 14-day free trial Download on theMac App Store

No credit card. 14 days. Cancel in one click.

macOS 15+ · Apple Silicon native · 14-day free trial · No credit card

Quick answer: Add the Excel file as a connection, pick the sheet, then build a Data Sync into a BigQuery table: map columns, choose Insert, Update or Upsert, and run it, or save it as a job for the next time the workbook gets refreshed. Pipelines tier.

When the source of truth is a workbook

Someone in ops keeps the real numbers in Excel. A vendor sends a workbook with three sheets and a header row that isn't quite where you'd expect. Before that data is useful for anything past a single meeting, it has to land in BigQuery next to everything else you already query. Google Sheets sync covers the spreadsheet case; this is the same problem for an actual .xlsx file sitting on someone's Mac.

Before you start

Steps

  1. Add the file as a connection: click the + next to Databases and pick CSV/Excel, then select the workbook and sheet.
  2. Open Pipelines → Build and click New Sync.
  3. On the left, pick the Excel connection as your source.
  4. On the right, pick your BigQuery connection and the target table, or create one.
  5. Drag columns across, or click AI Map to pair them by name.
  6. Pick a MODE: Insert for a fresh load, Update or Upsert if rows already exist and you're refreshing them.
  7. For Update or Upsert, set a MATCH ON field, a column that's unique per row.
  8. Click Dry Run, check the preview, then Save or run it now.

A worked example

A quarterly budget workbook, one sheet per department, needs its Actuals tab loaded into a shared BigQuery table finance already queries from:

-- target table
CREATE TABLE IF NOT EXISTS `my-gcp-project.finance.dept_actuals` (
  department STRING,
  cost_center STRING,
  actual_spend NUMERIC,
  period DATE
);

Map the sheet's Dept, Cost Center, Actual and Month columns to department, cost_center, actual_spend and period. If this is the first load, set MODE to Insert. If finance sends a corrected workbook later in the month, switch to Upsert with MATCH ON set to cost_center plus period so a resend replaces the old numbers instead of doubling them.

Check it worked

Dry Run shows exactly what would write before anything does. After a real run:

SELECT department, SUM(actual_spend) AS total
FROM `my-gcp-project.finance.dept_actuals`
GROUP BY department
ORDER BY total DESC;

and check that against a quick sum in the workbook itself. A mismatch usually means a header row got picked up as data, or a merged cell in the sheet left a blank the sync read as null.

Troubleshooting

If you seeFix
Wrong sheet loadedRe-open the file connection and confirm the sheet name matches the tab you meant.
Numbers imported as textA currency symbol or thousands separator in the cell can make Excel store it as text; clean the column before syncing or cast it after.
Duplicate rows after a resendSwitch MODE to Upsert with a MATCH ON key instead of re-running Insert on the same file.

What this doesn't do

This reads a workbook as it exists at the moment you sync it. It doesn't watch the file for changes or reopen it automatically when someone edits and re-saves. If the workbook gets replaced on a predictable schedule, save the sync as a job and swap in the new file before each run; if it needs to reflect edits the instant they happen, a live Google Sheet is the better source, not a static Excel file.

When to switch to Google Sheets instead

If the same people keep editing this workbook by hand every week, moving it to Google Sheets and syncing from there directly cuts out the file-handoff step entirely, since QueryFlow can read a live sheet instead of a new file export each time. Excel still makes sense when the file genuinely is the deliverable, like a report a vendor hands you as-is.

Handling a workbook with more than one useful sheet

A single Excel connection points at one sheet at a time. If a workbook has separate tabs per region or per department that all need to land in BigQuery, add a separate file connection for each sheet you need, pointing at the same underlying file, and build one sync per tab. It's more setup up front than a single all-in-one load, but each sync stays simple to read and debug on its own, rather than one large sync trying to branch logic based on which tab a row came from.

A note on numeric precision

Excel stores numbers as floating point internally, which occasionally introduces tiny rounding differences that only show up once the data lands in BigQuery's NUMERIC type and gets compared against a source system's exact figure. For anything involving money, round explicitly in the mapping or in a downstream query rather than trusting that a spreadsheet's displayed value and its stored value are always identical.

Related syncs

See also: Integrations Load a CSV into BigQuery on Mac Sync Databricks to BigQuery.

Integrations Load a CSV into BigQuery on Mac Sync Databricks to BigQuery
QueryFlow Studio $9.99/mo · $99/yr
QueryFlow Pipelines $29.99/mo · $199.99/yr

Frequently asked

Does the workbook need one sheet or can it have several?

It can have several. Pick the specific sheet you want as the source when you add the file connection.

What happens to formulas in the workbook?

QueryFlow reads calculated values, not the underlying formulas.

Can I schedule this if the file changes weekly?

Yes, save the sync as a job. If the file's location or name changes each time, update the file connection before the next run.

Is there a row limit?

Practical limits come from BigQuery load limits and available memory for very large workbooks; splitting a huge file before loading can help.

Skip the script.

14-day free trial, no card. Map the sheet once, run it whenever the file shows up.

Start 14-day free trial

No credit card. 14 days. Cancel in one click.