Fix "Workbook contains no default style" Warning in openpyxl
Reading a workbook exported by another system prints this, sometimes once per file in a batch job's log:
UserWarning: Workbook contains no default style, apply openpyxl's default
It is a warning, not an error, and in most cases the DataFrame is exactly what you expected. The file's stylesheet — the xl/styles.xml part that holds fonts, fills and number formats — is missing the entry for Excel's "Normal" style, and openpyxl fills the gap with its own. Programs that are not Excel often write a minimal stylesheet like this. There is a close cousin, though, that is not harmless, and the two are easy to confuse. This page, part of Troubleshooting Common Python Excel Errors, shows how to tell them apart and what to do about each.
Prerequisites
pip install pandas openpyxl
pip install python-calamine # optional, for Step 4
The examples use two small files that reproduce each case: export.xlsx, whose stylesheet lacks the Normal style, and bare.xlsx, whose stylesheet lacks cell formats altogether. Both hold the same two rows: a posting date and an amount.
Step 1 — Check which warning you have and what it touched
Capture the warnings rather than reading them off the console, so you can see the exact text and compare the data from each file:
import warnings
import pandas as pd
for name in ("export.xlsx", "bare.xlsx"):
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
frame = pd.read_excel(name)
print(name, [str(w.message) for w in caught])
print(frame.to_dict("records"))
export.xlsx warns about the default style and still gives you Timestamp('2026-03-01 00:00:00'). bare.xlsx warns that there is no stylesheet and gives you 46082 — the date's serial number. A number format is what marks a cell as a date in an .xlsx file; the value underneath is always a plain number. Remove the formats and the reader has no way to know those numbers were ever dates.
Look inside the stylesheet
An .xlsx file is a zip archive, and the stylesheet is one XML file inside it. Opening it directly shows which section is missing, which is useful evidence when you report the problem to whoever produces the files. The two sections that matter here are cellXfs, the list of cell formats that every styled cell points into, and cellStyles, the list of named styles such as Normal:
import re
import zipfile
def stylesheet_report(path):
with zipfile.ZipFile(path) as z:
if "xl/styles.xml" not in z.namelist():
return "no styles.xml part at all"
xml = z.read("xl/styles.xml").decode("utf-8")
parts = {}
for tag in ("numFmts", "cellXfs", "cellStyles"):
m = re.search(rf'<{tag} count="(\d+)"', xml)
parts[tag] = int(m.group(1)) if m else "missing"
return parts
for name in ("source.xlsx", "export.xlsx", "bare.xlsx"):
print(name, stylesheet_report(name))
The file Excel or pandas writes has all three sections. export.xlsx is missing only cellStyles — the Normal style — which is what the default-style warning reports. bare.xlsx is missing cellXfs, so no cell can point at a date format, and that is why its dates come back as plain numbers. The report takes a fraction of a second, so it is cheap to run over a whole folder of exports when you want to know how many files are affected before deciding between a filter and a conversion.
Step 2 — Silence the harmless warning precisely
For the default-style case, filter the warning — but only that warning, from that module. A blanket warnings.filterwarnings("ignore") also hides the ones you need, including the no-stylesheet warning that tells you dates are about to go wrong:
warnings.filterwarnings(
"ignore",
message="Workbook contains no default style",
category=UserWarning,
module="openpyxl",
)
print(pd.read_excel("export.xlsx").dtypes.to_dict())
message is a regular expression matched against the start of the warning text, and module is matched against the module that raised it — here openpyxl.styles.stylesheet, which the pattern openpyxl covers. Put the filter at the top of the script's entry point, not inside a library function, so it is visible to whoever reads the job next.
When only one call should be quiet, scope the filter to it with a context manager instead:
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message="Workbook contains no default style",
category=UserWarning, module="openpyxl")
ledger = pd.read_excel("export.xlsx")
print(len(ledger))
Step 3 — Repair dates when the stylesheet is missing
For the no-stylesheet case, convert the affected columns yourself. Excel's serial numbers count days from 30 December 1899, so pd.to_datetime with that origin and unit="D" turns them back into dates:
bare = pd.read_excel("bare.xlsx")
print(bare.dtypes.to_dict())
bare["posted"] = pd.to_datetime(bare["posted"], unit="D", origin="1899-12-30")
print(bare.to_dict("records"))
Convert only columns you know are dates. A quantity column holding 46082 is a quantity, and there is nothing in the file to distinguish it. If the export's layout is fixed, list the date columns in the job's configuration and convert them by name; Fix Excel Serial Numbers Showing Instead of Dates covers the conversion in depth, including time fractions and the 1904 date system.
Step 4 — Repair the file, or read it with a different engine
If the file is an intermediate you control — something your pipeline downloads and then processes in several steps — repair it once. Loading with openpyxl and saving writes a complete stylesheet, including a Normal style, so later readers see no warning:
from openpyxl import load_workbook
with warnings.catch_warnings():
warnings.simplefilter("ignore")
wb = load_workbook("export.xlsx")
wb.save("export_repaired.xlsx")
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
pd.read_excel("export_repaired.xlsx")
print(len(caught))
# 0
Resaving does not bring back lost date formats in the no-stylesheet case — the information is not in the file to restore. It only stops the warning.
The calamine engine reads the workbook without going through openpyxl's stylesheet code, so it does not emit the warning at all. It is also considerably faster, which makes it a sensible default for batch jobs that only need values:
try:
print(pd.read_excel("export.xlsx", engine="calamine").to_dict("records"))
except ImportError:
print("pip install python-calamine to use this engine")
calamine sees the same file, so the no-stylesheet case still gives serial numbers — switching engines hides the warning but not the underlying problem.
Step 5 — Report it upstream
If the files come from a system your organisation runs, tell its owners. A minimal stylesheet is valid enough for Excel to open, which is why nobody on their side has noticed, but it costs every consumer a workaround — and the no-stylesheet variant silently strips date information that downstream reports depend on. A one-line bug report with the warning text and a sample file is usually enough.
Common pitfalls
warnings.filterwarnings("ignore")with no arguments. It hides every warning in the process, including pandas deprecation notices and the no-stylesheet warning that signals lost dates.- Filtering on the wrong module. The warning is raised inside openpyxl, not pandas; a filter with
module="pandas"does nothing. - Converting every numeric column to dates. Only columns known to be dates should be converted; the file gives no way to tell them apart.
- Treating the warning as a sign of corruption. It is not; the file opens in Excel and the values are correct. Do not route these files to a repair or quarantine path on the strength of the warning alone.
- Assuming a resave restores formats. It writes a valid stylesheet, but formats that were never in the file stay missing.
Performance notes
The warning itself costs nothing measurable. In a job that reads thousands of such files, the cost is log noise — one line per file — which is reason enough to filter it. If the job is slow, the read is the bottleneck, not the warning; switching to calamine removes both.
Conclusion
"Workbook contains no default style" means the file's stylesheet lacks a Normal style; the data is intact and a filter on that message and module is the right response. "Workbook contains no stylesheet" means number formats are missing, so date columns arrive as serial numbers and must be converted with unit="D" and origin 1899-12-30. Resave intermediates you control with openpyxl, use calamine for fast value-only reads, and tell the producing system's owners.
Frequently asked questions
Is the "no default style" warning dangerous? No. The file's stylesheet is missing its Normal style entry, so openpyxl adds its own. Values, number formats and dates are read correctly. It is safe to silence it with a narrow filter.
How is "no stylesheet" different? That warning means the file has no usable cell formats at all. openpyxl can then no longer tell which numbers are dates, so date columns arrive as serial numbers such as 46082. Convert those columns explicitly.
Why does pandas show the warning? pandas uses openpyxl to read .xlsx files, and openpyxl raises the warning while loading the stylesheet. The warning comes from openpyxl's stylesheet module, which is why the filter must target that module.
Can I fix the file itself? Yes. Loading it with openpyxl and saving it again writes a complete stylesheet, and the warning disappears for every later reader. Do this when the file is an intermediate you control, not when it is someone else's original.
Related
- Up one level: Troubleshooting Common Python Excel Errors — other warnings and errors on read.
- Fix the "Data Validation extension is not supported" Warning in openpyxl — another openpyxl load-time warning.
- Parse Excel Dates into Python datetimes with pandas — date handling in general.
- Log Python Excel Script Output to a File — keeping warnings in the job log where they can be reviewed.
More on errors & fixes
- FixHandle Permission Denied When Writing Excel in Python
- How-toWhat openpyxl Loses When You Save an Existing Workbook
- FixFix Excel Serial Numbers Showing Instead of Dates
- How-toHandle Daylight Saving Time in Excel Timestamps
- How-toHandle Microsoft Graph Throttling in Excel Automation
- GuideError Handling and Logging in Excel Automation