Why Excel Automation Still Matters
Every conversation about automation eventually turns to flashy AI agents, but the actual bottleneck at most businesses is still a spreadsheet — someone manually copying numbers from one Excel file into another, formatting a report the same way every Monday, or reconciling two exports that should agree but don't. Excel automation isn't glamorous, but it's one of the highest-leverage things you can build, and it's a skill I've used directly in the automation and reporting work I do. This post covers the n8n patterns I actually reach for when the task is "get data in or out of a spreadsheet without a human doing it by hand."
Pattern 1: Trigger on File Change, Not on a Fixed Schedule
The naive approach is a cron trigger that runs every morning and hopes the file is ready. The more reliable pattern is triggering off the actual event — a new file landing in a watched folder (Google Drive, OneDrive, or a local/shared drive via a file-watcher node):
{
"nodes": [
{ "name": "Watch Folder", "type": "n8n-nodes-base.googleDriveTrigger",
"parameters": { "event": "fileCreated", "folderId": "{{reports_folder_id}}" } },
{ "name": "Download File", "type": "n8n-nodes-base.googleDrive" },
{ "name": "Read Spreadsheet", "type": "n8n-nodes-base.spreadsheetFile" }
]
}
Triggering on the actual file event rather than a guessed schedule removes an entire class of failure — the "the file wasn't there yet at 9am so the report ran on stale data" bug that shows up constantly in scheduled automation.
Pattern 2: Reading and Transforming Spreadsheet Data
Once you have a file, n8n's Spreadsheet File node converts XLSX/CSV rows into JSON, which is where the real transformation logic lives. A common shape: read raw rows, normalize field names, filter out incomplete rows, then aggregate.
[
{ "name": "Read Spreadsheet", "type": "n8n-nodes-base.spreadsheetFile",
"parameters": { "operation": "fromFile", "fileFormat": "xlsx" } },
{ "name": "Normalize Rows", "type": "n8n-nodes-base.set" },
{ "name": "Filter Incomplete Rows", "type": "n8n-nodes-base.filter" },
{ "name": "Aggregate by Category", "type": "n8n-nodes-base.summarize" }
]
The "Normalize Rows" step matters more than it looks — real-world Excel exports rarely have consistent column names between runs ("Order Total" one week, "OrderTotal" the next), so I typically add a Function node that maps a set of known aliases onto a canonical field name before anything downstream depends on it:
const aliasMap = {
order_total: ['Order Total', 'OrderTotal', 'Total'],
customer_name: ['Customer', 'Customer Name', 'Client'],
};
function normalize(row) {
const out = {};
for (const [canonical, aliases] of Object.entries(aliasMap)) {
const key = Object.keys(row).find(k => aliases.includes(k));
out[canonical] = key ? row[key] : null;
}
return out;
}
return items.map(item => ({ json: normalize(item.json) }));
This one function is what keeps a report workflow from silently breaking every time someone upstream renames a column.
Pattern 3: Generating Recurring Reports
For a weekly or monthly report, the pattern is: aggregate → format → write to a new spreadsheet → deliver. n8n's Spreadsheet File node can also write XLSX output, which means the workflow can produce a formatted report file rather than just raw data:
[
{ "name": "Aggregate Data", "type": "n8n-nodes-base.summarize" },
{ "name": "Format as Report Rows", "type": "n8n-nodes-base.set" },
{ "name": "Write XLSX", "type": "n8n-nodes-base.spreadsheetFile",
"parameters": { "operation": "toFile", "fileFormat": "xlsx" } },
{ "name": "Email Report", "type": "n8n-nodes-base.gmail" }
]
For anything that needs a visual dashboard rather than a static file, I'll route the same aggregated data into Power BI instead of (or alongside) the Excel output — n8n can push the aggregated rows to a database or API endpoint that Power BI reads from, so the same automation feeds both an emailed spreadsheet and a live dashboard without duplicating the aggregation logic.
Pattern 4: Reconciliation Between Two Sources
A very common real business need: two spreadsheets should agree (an order export and a payment export, for example), and someone needs to flag the rows that don't match. This is a straightforward n8n pattern once you frame it as a join-and-diff:
// Function node: compare two datasets by a shared key
const source = $input.all()[0].json.rows;
const target = $input.all()[1].json.rows;
const targetMap = new Map(target.map(r => [r.order_id, r]));
const mismatches = source.filter(r => {
const match = targetMap.get(r.order_id);
return !match || match.amount !== r.amount;
});
return mismatches.map(json => ({ json }));
The output feeds directly into an "exceptions" sheet or a Slack/Telegram alert, so the humans on the team only look at the rows that actually need attention instead of re-checking everything by hand every time.
Pattern 5: Error Handling — Don't Let a Bad Row Kill the Whole Run
Excel files from the real world have blank rows, merged cells, and inconsistent types. A workflow that throws on the first malformed row and stops is worse than useless — it silently fails to produce the Monday report and nobody notices until someone asks where it is. I wrap row-level transformations in a try/catch pattern inside Function nodes and route failures to a separate "needs review" branch rather than halting:
const results = [];
const errors = [];
for (const item of items) {
try {
results.push({ json: normalize(item.json) });
} catch (err) {
errors.push({ json: { row: item.json, error: err.message } });
}
}
return results; // errors get logged to a separate sheet in a parallel branch
This one habit — never let a single bad row take down the whole automation — is the difference between a workflow people trust and one they quietly stop relying on after the second silent failure.
Why This Is Worth Learning Even If You Do "Real" AI Work
It's tempting to treat spreadsheet automation as beneath the more interesting AI automation work, but in my experience the two aren't separate skill sets — the discipline of handling messy real-world data, inconsistent column names, and partial failures gracefully is exactly the discipline that makes an LLM-based workflow reliable too. Excel automation is just the version of that discipline where the mess is visible in a grid instead of hidden in unstructured text.
Let's Talk Automation
If you're building n8n workflows for reporting or reconciliation and want to compare notes, reach me at rishabnishad22@gmail.com, on WhatsApp, or through my contact page.