INSIGHTS · ANALYTICS & BI

We rebuild the same management report every month. How do we automate it without making it more fragile?

Automating a monthly report the wrong way just moves the fragility somewhere you can no longer see it. What to move upstream, what to leave in Excel, and how to keep it auditable.

The Bredge··8 min read

Automation done well moves calculation and joins upstream into tested logic, and leaves Excel for the last mile of judgement and presentation.
On this page

The short answer

The safe way to automate a monthly report is to separate the mechanical work from the judgement, and to add checks so that automation cannot fail silently.

Automate the parts that are mechanical and repeatable: collecting the data, joining it, calculating the figures, and checking them. Move that work upstream, into tested logic that runs the same way every month, rather than leaving it inside a workbook that one person rebuilds by hand. Keep the spreadsheet for the last mile: the judgement, the commentary, and the presentation that a person still has to do.

Excel is not the problem. A spreadsheet is an excellent place to shape a final view and add human judgement. It is a poor place to store the definitive calculation for a report that several people depend on every month. The fix is to give each part of the work the right home, not to ban the tool.

Above all, add review controls. Automation without checks does not remove fragility; it hides it. A pipeline that breaks quietly is worse than a manual step that breaks loudly, because no one notices until the wrong number is already in the board pack: the monthly summary that leadership relies on.

What this usually looks like

Most monthly reporting starts as a sensible spreadsheet and grows into something no one meant to build.

The routine is familiar. Someone exports data from several systems: the CRM, the billing platform, the general ledger, perhaps a payroll or operations tool. They paste each export into a master workbook. They line the exports up by hand, matching a customer here and an account code there. Formulas then turn the raw rows into the figures the board sees. Finally, the numbers are copied into a formatted pack and sent out.

This works, until it does not. The joins are manual, so a renamed column or an extra header row breaks them without warning. The calculations live in cells that only one person fully understands. The workbook has become load-bearing: a single tab, formula, or paste can change a reported number, and nothing flags it. When that person is on leave, the report stops. When a figure looks wrong, no one can quickly say why, because there is no record of where each number came from.

None of this is a failure of care. It is what happens when a quick spreadsheet quietly becomes critical infrastructure without ever being designed as such. It is also, incidentally, closely related to why the numbers disagree in the first place: the same manual joins and private definitions that make one report fragile are what make two reports contradict each other.

What the map tells you

The map sorts the work for you, before you write a line of code.

The mechanical steps are your automation targets. Anything that follows fixed rules (an export, a join on a known key, a recurring calculation, a standard check) can move upstream into tested logic and run without you. These are the steps that are the same every month, and that a machine repeats more reliably than a person.

The judgement steps stay with a person. Deciding why a variance happened, what to say about it, and how to present it is not mechanical. Automating it would only produce confident nonsense. These steps belong in the last mile, in the spreadsheet, where a person can apply context.

The timing drives the schedule. A report cannot be correct before its slowest source is final. The map shows the true earliest moment the report can run, and where the close cut-off really sits. Automating the calculation does not help if the pipeline runs before the ledger is closed; it just produces a fast, wrong answer.

The single points of failure are your priority list. Each one is a place where today’s process can stop, or go wrong, with no warning. These are the steps that most need a reliable, owned replacement, and the ones where automation, done properly, removes the most risk.

What to move, and what to keep in Excel

Underneath the tidy version of this workflow are a few well-understood engineering ideas. None is exotic; together they are what separate a controlled report from a fragile one.

Upstream transformation means doing the joining and calculating before the spreadsheet, in a place built for it, usually SQL over a database or data warehouse, rather than in workbook formulas. To transform data is to turn raw source rows into the shaped figures a report needs. The output is a tested data model: a defined table, with a clearly stated grain (what one row represents, for example one account per month), that the report reads from. The logic lives in version-controlled code, not in cells, so it can be reviewed, tested, and reused.

Data quality tests are automated assertions about that model. An assertion is a rule that must always hold; if it does not, the run fails and stops. Typical assertions check row counts (did every source arrive?), nulls (is any key or amount missing?), and totals (does the model tie back to a trusted control figure, such as the ledger balance?). These tests are what stop a broken join from ever reaching the board pack.

A small, concrete example. The model below builds one profit-and-loss line per account per month, joined on a resolved account key rather than on the account name. Two tests follow it. Each test is written so that it returns rows only when something is wrong. A healthy run returns nothing.

-- model: mart_monthly_pnl
-- Grain: one row per account per month.
select
    date_trunc('month', gl.posted_at) as period,
    coa.report_line                   as line,
    sum(gl.amount)                    as amount
from raw_ledger.entries as gl
join ref.chart_of_accounts as coa
    on coa.account_id = gl.account_id          -- resolved key, not the name
where gl.posted_at < date_trunc('month', current_date)  -- closed periods
group by 1, 2;

-- test 1: every entry must map to a report line (a broken join)
select gl.entry_id
from raw_ledger.entries as gl
left join ref.chart_of_accounts as coa
    on coa.account_id = gl.account_id
where coa.report_line is null;

-- test 2: a cost line must never post a positive amount
select period, line, amount
from mart_monthly_pnl
where line = 'cost_of_sales' and amount > 0;

The first test lists any ledger entry that did not match a report line — a broken join, the classic silent failure of a manual workbook. The second lists any cost line that has posted a positive amount, which usually signals a sign or mapping error. Because each query returns rows only on failure, the orchestrator can treat any returned row as a reason to stop and raise an alert, before anyone sees the number.

Refresh and orchestration timing decide when this runs. Orchestration is simply the scheduling and ordering of the steps (extract, transform, test, publish) so that each waits for the one before it. The schedule must fit the close process: the monthly routine by which each source is finalised and the period is locked. Running before the close produces numbers that are correct only for unfinished data.

Exception handling is the plan for when a test fails. A controlled workflow does not carry on regardless; it stops, tells a named person, and records what happened. Source ownership makes that possible: each input has an owner who is responsible for it and who is contacted when it breaks. Distribution (sending the finished pack to its readers) happens only after the checks pass and a person signs off, not automatically the moment the pipeline finishes.

Finally, auditability, or lineage. Lineage is the traceable path from a figure in the final pack, back through the model, to the exact source rows that produced it. With lineage, any number can be explained and defended. Without it, a disputed figure becomes an argument no one can settle.

What good looks like

A controlled monthly report looks calm, because the fragile parts have been designed out.

  • The sources are owned. Each input has a named owner and a known refresh time, so there is no mystery about when data is ready or who to ask.
  • The logic is tested. Joins and calculations live in version-controlled code with data quality tests, not in workbook cells. A broken join fails a test instead of quietly changing a number.
  • The refresh is timed to the close. The pipeline runs after the last source is final, never before, so the figures are built on complete data.
  • Excel does the last mile. The spreadsheet is where a person adds judgement, commentary, and presentation — the work that genuinely needs a human. It reads from the tested model; it does not re-derive the numbers.
  • There is an audit trail. Every figure can be traced back to its source, and every run records what it did and whether the checks passed.

Common ways this goes wrong

The same few mistakes turn automation into a new kind of fragility.

  • Automating the mess unchanged. Wrapping a script around a broken manual process just makes the same errors faster and harder to see. Map and fix the process first.
  • Hiding manual fixes inside macros. A recorded macro that quietly patches known problems moves the fragility out of sight. When it breaks, it breaks silently.
  • No tests, so breakage is silent. Without data quality checks, a failed join or a missing source produces a plausible but wrong number that no one questions.
  • No owner. If no one is responsible for the pipeline and its sources, a failure has no one to catch it, and the report simply stops or misleads.
  • No audit trail. If a figure cannot be traced to its source, a dispute cannot be settled, and trust in the report erodes.
  • Automating before the definition is agreed. If the business has not agreed what a figure means, automation only entrenches one team’s version of it. Settle the definition first, then automate.

When this becomes a system

A single, well-owned spreadsheet, updated calmly once a month, may not need any of this. Do not build a pipeline to solve a problem you do not have. But a monthly report tends to cross a line (from a personal spreadsheet into a small system that the business runs on), and past that line the manual approach costs more than it saves.

A decision guide

Once the map is done, most steps sort cleanly into one of three homes: an upstream model, a review control, or the Excel last mile. Use this as a starting point.

Report stepWhat it involvesWhere it belongs
Collecting source dataExtracting or exporting from each systemUpstream (automated pipeline)
Joining systemsMatching records on a shared, resolved keyUpstream model
Recurring calculationMargins, variances and totals by fixed rulesUpstream model
Quality checkRow counts, nulls, tie-out to a control totalReview control (data tests)
ReconciliationTying the model back to a trusted figureReview control
Judgement and commentaryExplaining why a figure movedExcel (last mile)
PresentationFormatting the board packExcel (last mile)
Sign-offA person approves the pack before it is sharedReview control
DistributionSending the finished pack to its readersAutomated, only after sign-off

The pattern holds across almost every monthly report: move the mechanical middle upstream into tested logic, wrap it in checks, and keep Excel for the judgement and presentation it is genuinely good at. That is the shape of most well-scoped reporting automation projects — less dramatic than a rebuild, and far harder to break.

If the monthly close depends on one person and a fragile workbook, reporting automation is a well-scoped project.reporting automation projects.