
Last checked: 27 October 2026. Tool availability and licensing change often, so I’ve linked every claim to its source.
Short version
- Spreadsheets fail in boring, repeatable ways: copy-paste, silent limits, silent auto-conversion. Python is good at exactly those jobs.
- Python doesn’t fix bad logic. It gives you something Excel can’t easily give you: a script you can diff, test, and rerun the same way every time.
- The best documented evidence for automation is the failures of manual processes (UK COVID data, JPMorgan’s risk model, gene-name corruption in published research). Reported time savings exist, but almost all are self-reported, and I label them that way below.
- Start with consolidation and report generation. Leave the spreadsheet’s formulas alone until you have a reason to touch them.
Why I’m not opening with a “save 10 hours a week” promise
Most articles on this topic start with a happy analyst who gets her Fridays back. I went looking for independently verified versions of that story and mostly didn’t find them. What I found instead was a pile of vendor testimonials, consultant blog posts, and tutorials with unnamed “financial analysts in Toronto.”
The case for automating spreadsheets is stronger than those anecdotes, though. It rests on what happens when people don’t automate. So that’s where we’ll start.
Part 1: Three documented failures
Case 1: England loses 15,841 COVID cases to a file format (2020)
Between 25 September and 2 October 2020, Public Health England left 15,841 positive cases out of its daily figures. Test results arrived from labs as CSV files, then went into Excel as part of a manual-ish pipeline.
The most widely reported explanation is that the data landed in the old .xls format, which caps a sheet at 65,536 rows, while modern .xlsx allows 1,048,576. The Register reported that each test result took several rows, so the real case limit per sheet was far lower, and anything past the cutoff was dropped without a warning. The agency itself described it as a “technical issue” in the data load process, so the exact mechanism rests on press reporting, not a full public post-mortem. (Early speculation about a column limit circulated too and was less plausible.)
The data was fixed by splitting the files into batches. Only 51% of the affected positive cases had been reached by contact tracers when the Healthcare IT News report was written.
What it teaches: the failure wasn’t that Excel is bad. Nobody checked that rows-in equalled rows-out. An IT expert quoted by LBC said a basic sanity check would have caught the limit. That is a two-line assertion in Python (you’ll see it in Part 3). Python alone wouldn’t have saved them, though. A script that doesn’t count its rows can truncate just as quietly.
Case 2: JPMorgan’s value-at-risk spreadsheet (2012)
JPMorgan’s internal task force report on the “London Whale” losses described a risk model that “operated through a series of Excel spreadsheets, which had to be completed manually, by a process of copying and pasting data from one spreadsheet to another” (quoted via the New Statesman; the primary source is the task force report PDF). Bloomberg summarised it as an “error-prone” system requiring employees to cut and paste data.
The report also describes a formula error in the model’s calculation of relative changes: it divided by the sum of two rates rather than their average, which likely muted volatility by a factor of two and lowered the VaR, though the report says it’s unclear when the error was introduced.
The review group had noted the manual process was “error-prone” and “not easily scalable,” and asked for automation. It approved the model anyway, without a basis for believing automation was possible on that timetable.
An honest caveat: the roughly $6.2 billion loss came from the trading positions. The spreadsheet error was one contributor that made the risk look smaller than it was. It did not “cause” the loss on its own, and anyone who tells you it did is simplifying.
Case 3: Gene names turned into dates (2004 to now)
Excel has been converting gene symbols like SEPT1 and MARCH 1 into dates since at least 2004. Researchers at Deakin University scanned supplementary files in PubMed Central and found that 30.9% (3,436 of 11,117) of articles with supplementary Excel gene lists contained gene-name errors, across 2014 to 2020. That was after a 2016 report had flagged the problem. The rate stayed roughly flat year to year.
The naming body (HGNC) ended up renaming genes (SEPT1 became SEPTIN1, MARCH 1 became MARCHF1) rather than wait for software to change. The paper’s authors recommend Python or R notebooks over spreadsheets for large genomics data.
What it teaches: this error happens when a file is opened in a spreadsheet. A script that reads the raw CSV as text never triggers it. Limits of the study: it covers genomics papers only, and the authors have a stated preference for code over spreadsheets.
The background rate
Raymond Panko’s synthesis of field audits found that 94% of 88 audited operational spreadsheets contained errors, with an average cell error rate of 5.2% (the cell rate was measured on 43 of them). Treat that carefully. The audits are old (mostly 1995 to 2004), definitions of “error” vary, and some studies only counted serious errors. Even critics of the number accept the direction: errors are common.
The same literature has a sobering line for Python fans: fault rates in ordinary software run at 1.5% to 2.6% per statement. Code isn’t magically clean. The advantage is that code can be reviewed, versioned, tested and rerun, and a typo in cell F412 can’t hide.
Part 2: What time savings are actually reported
I’m separating this by how much I’d trust it.
| Source | Reported result | My confidence |
|---|---|---|
| xlwings user testimonial (named analyst at a U.S. custody bank, on the xlwings site) | Monthly reports: 20–30 hours of VBA-based work down to 6–7 hours | PROBABLE, but vendor-hosted, unverifiable |
| Another xlwings testimonial (anonymous, same page) | 1–2 days of monthly manual data-feed work saved | SPECULATIVE |
| Consultancy case study (From Excel to Python) | Branch consolidation: 24 analyst hours down to under 30 seconds | SPECULATIVE: the author sells this service |
| Intern write-up (Medium) | Daily FX-rate update automated with xlwings and Task Scheduler | Useful as a pattern, no savings figure |
The “30 seconds” figure compares compute time to human time, which flatters the result. It ignores build time, maintenance, and the day someone renames a column. Most of these also come from sellers of Python tooling.
My own read, based on what I’d expect from the evidence and not on a study: the savings are real for work that is repetitive, rule-based, and recurring (monthly consolidation, standard reports, file cleanup). They shrink fast for one-off or judgment-heavy work, where writing the script costs more than doing the task once.
Part 3: A working example you can adapt
This is the pattern behind the PHE lesson: merge many files, fail loudly if anything looks wrong, then write a clean report. I ran this on pandas 3.0.2, openpyxl 3.1.5 and XlsxWriter 3.2.9 with test data (three regional files, 9 rows), and it produced the expected summary and a frozen header row. It hasn’t been tested on your data, so run it on a copy first.
python
from pathlib import Pathimport pandas as pdEXPECTED = ["region", "month", "revenue"]frames, problems, rows_in = [], [], 0for f in sorted(Path("regional").glob("*.xlsx")): df = pd.read_excel(f, sheet_name="Data", engine="openpyxl") df.columns = df.columns.str.strip().str.lower() # "Month " -> "month" missing = set(EXPECTED) - set(df.columns) if missing: problems.append(f"{f.name}: missing columns {sorted(missing)}") continue rows_in += len(df) df["source_file"] = f.name frames.append(df[EXPECTED + ["source_file"]])if problems: raise SystemExit("Stopped:\n" + "\n".join(problems))combined = pd.concat(frames, ignore_index=True)# The two lines the UK data pipeline didn't haveassert len(combined) == rows_in, "Rows were lost or duplicated during the merge"assert combined["revenue"].notna().all(), "Blank revenue cells found"summary = combined.groupby("region", as_index=False)["revenue"].sum()with pd.ExcelWriter("report.xlsx", engine="xlsxwriter") as xw: summary.to_excel(xw, sheet_name="Summary", index=False) combined.to_excel(xw, sheet_name="Detail", index=False) ws = xw.sheets["Summary"] ws.set_column("A:A", 20) ws.set_column("B:B", 14, xw.book.add_format({"num_format": "#,##0.00"})) ws.freeze_panes(1, 0)Two habits that matter more than any library choice:
- Count in, count out. Every pipeline gets a row-count check and a null check before it writes anything.
- Stop on surprise. A missing column should end the run with a message, not produce a plausible-looking wrong report.
For the gene-name problem, the equivalent habit is to read identifiers as text (dtype=str in pd.read_csv) and never round-trip them through a spreadsheet you open by hand.
Part 4: Picking the right tool
| Tool | Needs Excel installed? | Good for | Watch out for |
|---|---|---|---|
| pandas | No | Merging, cleaning, pivots, big tables | Not a formatting tool |
| XlsxWriter | No | Writing new, formatted reports | Write-only, can’t edit existing files |
| openpyxl | No | Reading and editing .xlsx | Never evaluates formulas; older docs warn images and charts can be lost when you reopen and resave |
| xlwings | Yes (Windows or macOS) | Live Excel control, macros, UDFs | Needs a local Excel; UDFs are Windows-only |
The “never evaluates formulas” point bites people: openpyxl writes =SUM(A1:A5) as text, and the number only appears once Excel opens and recalculates the file. If your script needs the result of a formula, compute it in pandas instead of reading it back.
Where Python in Excel fits
Microsoft’s own feature is a different animal. Per Microsoft’s security page, Python formulas run in a hypervisor-isolated cloud container with no network access, no access to your computer, and no user token. Data isn’t persisted. Separately, Microsoft says the code can’t see workbook formulas, charts, PivotTables, or macros, and can only return values or images.
That makes it a good fit for in-sheet analysis and a poor fit for file automation (nothing here can open a folder of workbooks). On availability, Microsoft’s page says Windows customers on Business or Enterprise subscriptions in the Current Channel can use it at standard compute speed without a paid license; free consumer and perpetual licenses aren’t supported, and a paid add-on adds premium compute. Mac support for Business and Enterprise started at Excel version 16.96, per the Chinese-language edition of the same page. This is the part most likely to have changed by the time you read this, so check the page.
Part 5: What could go wrong
Maintenance is the hidden cost. A script that saves 5 hours a month but breaks every quarter, with only one person who understands it, can be a net loss. Python also moves the single point of failure from “the spreadsheet” to “the person who wrote the script.” Write a README. Put the code in version control.
Garbage still gets through. My example catches missing columns and blank revenue. It does not catch a region reporting in the wrong currency. Validation is only as smart as the rules you write down.
Some jobs shouldn’t move. If finance owns a model with intricate formulas that auditors read cell by cell, rewriting it in Python can make it less reviewable to the people who sign off on it. Automate the plumbing around the model first.
I haven’t proven the ROI. The failure cases above are documented. The savings numbers are reported by interested parties. Measure your own: time the manual task for two cycles before you write a line of code.
A sensible first month
- Pick the one task you do on a schedule that involves opening several files and copy-pasting.
- Time it for two cycles.
- Write the merge script with the row-count and null checks first. Add formatting last.
- Run the script and the manual process side by side for one cycle and compare totals.
- Only then retire the manual version.
Skipping step 4 is how you end up with a faster way to be wrong.
FAQ
Do I need Excel installed to automate it with Python? Not for pandas, openpyxl, or XlsxWriter, which read and write the file format directly. xlwings does need Excel.
Is Python in Excel the same as running Python scripts on my files? No. It runs inside the workbook, in Microsoft’s cloud, on cell data you reference. It can’t loop over files on your disk.
Will Python fix my formula errors? No. It moves the logic somewhere you can test and review. Wrong logic stays wrong.
What about VBA? VBA is still fine for small in-workbook macros. Python wins when you work across many files, need real data tooling, or want version control.
How do I avoid gene-name or ID mangling? Read identifiers as text and avoid opening the files in a spreadsheet during the pipeline.
Where did the numbers in this article come from? Every figure is linked. Where I couldn’t find an independent source (the time-saving claims), I’ve said so.
Scope note: I researched this from public sources on 27 October 2026 and tested only the code shown above, on synthetic data. I have no sponsorship or affiliate relationship with any tool mentioned. I haven’t audited any company’s spreadsheets, so everything about the failures above comes from published reporting and papers.
The last word: a spreadsheet will happily hand you a wrong number with total confidence, so the best thing automation buys you is a script that refuses to finish when the totals don’t match.