All writing
Automation3 min read

openpyxl basics: read and write Excel from Python

Every shop-floor automation eventually touches a spreadsheet. openpyxl is the library that makes Excel just another file format — here's the working 90% of it.

A spreadsheet with tabular data and a chart open on screen

Photo: MikeRun · CC BY-SA 4.0

You can dislike it all you want: the shop runs on Excel. Tool inventories, production logs, setup sheets, quality records — I've replaced some of them with real software, but the spreadsheet is the shop floor's lingua franca and it isn't going anywhere. Which is why openpyxl is one of the highest-leverage libraries a manufacturing engineer can learn: it makes .xlsx just another file format your Python scripts read and write. No Excel installation required, no VBA, runs on a server or a scheduled task.

Reading a workbook

from openpyxl import load_workbook

wb = load_workbook("tool_inventory.xlsx", data_only=True)
ws = wb["Endmills"]              # or wb.active for the first sheet

print(ws["B2"].value)            # one cell

# iterate rows as plain values, skipping the header
for row in ws.iter_rows(min_row=2, values_only=True):
    tool_id, diameter, flutes, location, qty = row
    if qty is not None and qty < 2:
        print(f"LOW STOCK: {tool_id} ({qty} left)")

The data_only trap (everyone hits this)

A cell containing =SUM(C2:C40) gives you the formula string by default, not the number. data_only=True gives you the last value Excel calculated — but only if the file has been opened and saved by Excel since the formula changed, because openpyxl doesn't calculate anything. If a workbook is formula-heavy and freshly generated, the cached values may be None. Know which one you're asking for.

Writing a report people will actually open

The classic shop use case: a folder of per-machine CSV logs that someone merges into a weekly summary by hand. Here's the whole job — merge, total, and format it so it looks like a report instead of a data dump:

import csv
from pathlib import Path
from openpyxl import Workbook
from openpyxl.styles import Font

wb = Workbook()
ws = wb.active
ws.title = "Week 27"

headers = ["Machine", "Date", "Parts", "Scrap"]
ws.append(headers)
for cell in ws[1]:
    cell.font = Font(bold=True)

for log in sorted(Path("logs").glob("*.csv")):
    with open(log, newline="") as fh:
        for r in csv.DictReader(fh):
            ws.append([r["machine"], r["date"],
                       int(r["parts"]), int(r["scrap"])])

ws.append([])
last = ws.max_row + 1
ws[f"A{last}"] = "TOTAL"
ws[f"A{last}"].font = Font(bold=True)
ws[f"C{last}"] = f"=SUM(C2:C{last - 2})"
ws[f"D{last}"] = f"=SUM(D2:D{last - 2})"

ws.column_dimensions["A"].width = 14
ws.freeze_panes = "A2"

wb.save("weekly_production.xlsx")

Note the trick in the middle: you can write formulas as strings and Excel evaluates them on open. Bold headers, frozen top row, sensible column widths — ten lines of polish is the difference between "the script output" and "the weekly report," and adoption lives in that difference.

openpyxl or pandas?

  • pandas when the job is analysis: filtering, grouping, joining, statistics. pd.read_excel (which uses openpyxl underneath) gets the data into a DataFrame and out of spreadsheet-land.
  • openpyxl when the job is the spreadsheet itself: formatting, formulas, multiple sheets, templates — producing a file for humans.
  • Both, often: crunch in pandas, then hand the result to openpyxl for presentation. They're teammates, not rivals.
  • `.xlsx` only. Ancient .xls files need a different tool — open and re-save them once, then move on.
  • Excel locks open files. If someone has the workbook open, your save fails. Write to a new filename (report_2026-07-04.xlsx) or handle the PermissionError; on a shared drive, someone always has it open.
  • Dates come back as `datetime` objects — that's a feature, but it surprises people the first time.

If you're new to Python entirely, this is genuinely the best entry point — more so than anything machine-side — because the wins are immediate and visible to everyone. It's step one in my recommended path for manufacturing engineers. And when a spreadsheet has grown into a monster that needs to be an actual application, that's the conversation I'm here for.

Muerus Rodrigues

Applications Engineer

Get in touch

Keep reading

Home
Blog
Tools
Code
Contact
LinkedIn
Request Résumé