Shop DataPythonWindows · Python 3.8+ · xlwings · Microsoft ExcelMIT licenseAdvanced
Push live shop-floor numbers into an open Excel dashboard (xlwings)
Nobody on a shop floor wants to learn a new dashboard app — they already know Excel. This script is the other half of the openpyxl report: instead of writing a file once, it connects to a workbook someone already has open and updates five cells every second, live, while Excel does what it's always done — formatting, conditional colors, a chart if you want one. Tested here against a real, running Excel instance, including a real formatting trap it caught along the way.
Before you run it
pip install xlwings- Microsoft Excel installed and running (Windows) — this drives Excel over COM, it doesn't work headless
- A workbook named
dashboard.xlsxalready open, with a sheet namedDashboard
The code
"""Push live shop-floor numbers into an already-open Excel workbook, once a
second - the "Excel front-end, Python back-end" pattern for a dashboard
nobody has to learn a new tool to read.
Usage: python xlwings_dashboard.py
"""
import random
import time
import xlwings as xw
WORKBOOK_NAME = "dashboard.xlsx" # must already be open in Excel
SHEET_NAME = "Dashboard"
def read_live_numbers():
"""Stand-in for a real data source (PLC tag, database, FOCAS poller...).
Replace this with whatever actually produces your shop-floor numbers."""
return {
"parts_today": random.randint(280, 320),
"scrap_today": random.randint(2, 12),
"cycle_time_s": round(random.uniform(38, 45), 1),
"machine_status": random.choice(["RUNNING", "RUNNING", "RUNNING", "HOLD"]),
}
def main():
wb = xw.Book(WORKBOOK_NAME) # connects to the ALREADY OPEN workbook
sheet = wb.sheets[SHEET_NAME]
sheet["B6"].number_format = "@" # Text - a time-like string would otherwise
# get reinterpreted as an Excel time serial
print(f"Connected to {WORKBOOK_NAME} / {SHEET_NAME}. Ctrl+C to stop.")
try:
while True:
data = read_live_numbers()
sheet["B2"].value = data["parts_today"]
sheet["B3"].value = data["scrap_today"]
sheet["B4"].value = data["cycle_time_s"]
sheet["B5"].value = data["machine_status"]
sheet["B6"].value = time.strftime("%H:%M:%S")
time.sleep(1)
except KeyboardInterrupt:
print("\nStopped. The workbook keeps whatever it last showed.")
if __name__ == "__main__":
main()What you get
$ python xlwings_dashboard.py
Connected to dashboard.xlsx / Dashboard. Ctrl+C to stop.
^C
Stopped. The workbook keeps whatever it last showed.
dashboard.xlsx — Dashboard sheet
A B
2 Parts today 294
3 Scrap today 2
4 Cycle time (s) 44.1
5 Machine status RUNNING
6 Last update 22:19:26 <- stays literal text (number_format="@")How it works
xw.Book(WORKBOOK_NAME)connects to an already-open workbook instead of creating a new one — the whole point of this pattern is that someone already has the file open on a monitor, and the script updates it live behind the scenes.- Setting
number_format = "@"(Text) on the timestamp cell before writing to it is the fix for a real trap this script hit in testing: write a string like"14:32:07"to a plain cell and Excel silently reinterprets it as a time serial number, showing a bare decimal fraction instead of the text you sent. read_live_numbers()is a deliberate stand-in — swap it for a FOCAS poller, a database query, or an OPC UA read, and everything downstream (writing cells, the dashboard itself) doesn't change.- No custom UI, no PyQt, no WinForms — Excel already does formatting, conditional colors, and charts; this script's only job is keeping five cells current.
Gotchas & honest limits
- The workbook must already be open —
xw.Book()raises if it can't find a workbook by that name among currently-open Excel instances, and it does not silently create one. - String values that look like times, dates, or numbers get reinterpreted by Excel unless the target cell is pre-formatted as Text — this bit the timestamp cell during testing; watch for it on any other text-that-looks-numeric field.
- This writes cell-by-cell in a tight loop — fine for five values once a second; batch a full range write (
sheet["B2:B6"].value = [[...]]) if you're updating dozens of cells at that cadence. - xlwings drives Excel over COM, which means this only runs on Windows with Excel installed — there's no cross-platform equivalent for the live-write half of this pattern. Reading/writing
.xlsxwithout Excel open is a different, portable job — see the openpyxl report script.
Goes deeper
Want this adapted to your shop — or built into a real tool?
Samples are the free 80%. The last 20% is the part I do for a living.