Taming the Spreadsheet Hydra

There’s a point in every growing company when a spreadsheet stops being a tool and starts behaving like a creature — useful once, now dangerous. At first, it’s just another tab in the ecosystem. Then one day it becomes the “single” source of truth, cobbled together with imports and brittle formulas, and every edit feels like cutting off one head only to watch two more grow back.

You know the signs:

When the Hydra shows up, you don’t need a full data warehouse yet, but you need something sturdier than one person’s heroic copy‑paste rituals. That’s where this script came from: a nightly sync that keeps critical Google Sheets tabs aligned across multiple files. It isn’t glamorous, but it does the job: it keeps the creature contained.

What It Does

Think of it as lightweight ETL (Extract‑Transform‑Load) for teams that live in Sheets.

A Quick Look Under the Hood

The script is a small Node.js function using the Google Sheets API. Instead of hardcoding IDs and ranges (fine for one‑offs), I keep them in a JSON config file:

{
  "syncJobs": [
    {
      "sourceSheetId": "SOURCE_SHEET_ID",
      "sourceTabName": "FinanceData",
      "destinationSheets": [
        {
          "sheetId": "DEST_SHEET_1_ID",
          "tabName": "FinanceData"
        },
        {
          "sheetId": "DEST_SHEET_2_ID",
          "tabName": "FinanceData"
        }
      ]
    }
  ]
}

Adding a new sync is simple — update the config and the script adjusts without touching a line of code.

The flow is straightforward:

Example snippet for reading from the source tab:

const response = await sheets.spreadsheets.values.get({
  spreadsheetId: sourceSheetId,
  range: `${sourceTabName}!A:Z`,
});
const rows = response.data.values || [];
console.log(`Read ${rows.length} rows from ${sourceTabName}`);

Then clear and write:

await sheets.spreadsheets.values.clear({
  spreadsheetId: destSheetId,
  range: `${destTabName}!A:Z`,
});

await sheets.spreadsheets.values.update({
  spreadsheetId: destSheetId,
  range: `${destTabName}!A1`,
  valueInputOption: "RAW",
  requestBody: { values: rows },
});
console.log(`Synced ${rows.length} rows to ${destTabName} in ${destSheetId}`);

Why It Matters

Anyone who’s worked in business ops, rev ops, or finance knows this pain:

This script doesn’t solve every problem. But it buys breathing room — pennies a month to replace frantic midnight copy‑pasting with something automatic and boring. The best ops fixes are like that: invisible once they work.

Glue Code That Grows With You

Most durable systems start small. A single script. A single function. Over time, they evolve — multi‑sheet syncs, logging, notifications, even pub/sub triggers or API webhooks. This pattern bridges the awkward gap between “no system” and “too much system.”

It’s not elegant, not even impressive. But it’s enough to keep the Hydra calm and let you get back to the real work.

Related reading
Latest entries

Like this? Subscribe via email here.