Guide
Read a Cell Value From Excel With openpyxl
Read Excel cell values with openpyxl: load_workbook, ws['B2'].value, ws.cell(), iter_rows, ranges, and data_only for cached formula results instead of formula text.
When you need the value of one cell — or a precise rectangle of cells — rather than a whole DataFrame, openpyxl is the direct tool. It opens a workbook, exposes every cell by coordinate, and lets you choose between a formula's text and its cached result. This guide, part of Using openpyxl for Excel File Manipulation, walks through load_workbook, both cell-access styles, iterating rows, reading a range, and the data_only flag — with every snippet building its own sample file.
Prerequisites
Install openpyxl:
pip install openpyxl
Create a sample workbook
These examples read this file. It includes a formula in column C so the data_only section has something to demonstrate:
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.title = "Sales"
ws["A1"], ws["B1"], ws["C1"] = "SKU", "Qty", "Total"
ws["A2"], ws["B2"], ws["C2"] = "A-100", 3, "=B2*10"
ws["A3"], ws["B3"], ws["C3"] = "B-200", 5, "=B3*10"
wb.save("sales.xlsx")
print("wrote sales.xlsx")
Read one cell by coordinate
Load the workbook, pick a worksheet, and read .value. The ["B2"] syntax mirrors the spreadsheet UI:
from openpyxl import load_workbook
wb = load_workbook("sales.xlsx")
ws = wb["Sales"] # or wb.active for the first sheet
print(ws["B2"].value) # -> 3
ws["B2"] returns a Cell object; the data lives on its .value attribute. Forgetting .value gives you the cell wrapper, not the number.
Read a cell by row and column number
ws.cell(row=2, column=2) reaches the same cell numerically — the form you want inside loops or when coordinates are computed. openpyxl is 1-based: row 1 and column 1 are the top-left cell, so row=2, column=2 is B2:
from openpyxl import load_workbook
wb = load_workbook("sales.xlsx")
ws = wb.active
print(ws.cell(row=2, column=2).value) # -> 3, same cell as B2
Iterate rows with values only
To sweep a sheet, iter_rows(values_only=True) yields plain tuples of values instead of Cell objects — less overhead and easier to unpack:
from openpyxl import load_workbook
wb = load_workbook("sales.xlsx")
ws = wb.active
for sku, qty, total in ws.iter_rows(min_row=2, values_only=True):
print(sku, qty, total)
Drop min_row=2 to include the header row. Use min_col/max_col to bound the columns you read.
Read a rectangular range
Index the worksheet with a range string to get a tuple of rows, each a tuple of cells. Pull .value from each to flatten it:
from openpyxl import load_workbook
wb = load_workbook("sales.xlsx")
ws = wb.active
values = [[cell.value for cell in row] for row in ws["A1:B3"]]
print(values) # [['SKU', 'Qty'], ['A-100', 3], ['B-200', 5]]
Formula text vs. cached result with data_only
By default openpyxl returns the formula string for a calculated cell. Pass data_only=True to get the cached result Excel last computed and stored in the file instead:
from openpyxl import load_workbook
formula = load_workbook("sales.xlsx")
print(formula.active["C2"].value) # -> '=B2*10' (the formula text)
cached = load_workbook("sales.xlsx", data_only=True)
print(cached.active["C2"].value) # -> None until Excel saved a result
The catch: openpyxl never evaluates formulas itself. data_only=True only returns a value if a real spreadsheet application — Excel, LibreOffice, or similar — opened the file, recalculated, and saved the cached results. A workbook that openpyxl created and saved (like our sales.xlsx) has no cached values, so data_only=True returns None for every formula cell. Open and resave the file in Excel once, and the cached results appear.
Common pitfalls
| Symptom | Cause | Fix |
|---|---|---|
Got a <Cell> repr, not the value | Read the cell object, not its data | Append .value: ws["B2"].value |
IndexError or wrong cell with cell() | Used 0-based indices | openpyxl is 1-based; top-left is row=1, column=1 |
data_only=True returns None | File has no cached formula results | Open and save the file in Excel first; openpyxl won't compute |
MemoryError on a huge file | Loaded the whole workbook into RAM | Use load_workbook(path, read_only=True) and stream iter_rows |
Edits don't stick after read_only | read_only mode is non-writable | Drop read_only when you need to modify cells |
A second subtlety: you can't have both the formula text and the cached result from one load_workbook call. Open the file twice — once plain, once with data_only=True — if you need both.
Performance and scale
For large workbooks where you only read, load_workbook(path, read_only=True) switches openpyxl to a streaming parser that loads rows lazily, keeping memory flat as the file grows. It pairs naturally with iter_rows(values_only=True). Note that read-only mode disables writing and some cell attributes, so use it only for pure extraction.
Frequently asked questions
Why does my cell return the formula string instead of the number?
That's the default. Reload with load_workbook(path, data_only=True) to get the cached result — provided Excel computed and saved it.
Is openpyxl 0-based or 1-based?
1-based, everywhere. ws.cell(row=1, column=1) is A1. This matches the spreadsheet UI but differs from Python list indexing.
How do I read just the value, not the cell object?
Always go through .value — ws["B2"].value or ws.cell(row=2, column=2).value. iter_rows(values_only=True) does this for you across a whole sweep.
Can openpyxl calculate formulas for me? No. It reads formula text or the cached result, but never evaluates. For live computation, use a tool that drives Excel itself, such as xlwings.
Conclusion
openpyxl gives you two equivalent ways to reach a cell — ws["B2"].value for readability and ws.cell(row=2, column=2).value for computed coordinates — both 1-based. To sweep a sheet, iter_rows(values_only=True) is fastest; to scope a region, index with a range string. The one rule to remember about formulas: openpyxl doesn't calculate, so data_only=True returns the cached result only when a spreadsheet app saved one, and None otherwise.
Where to go next
Return to Using openpyxl for Excel File Manipulation for the broader read-and-edit workflow. To write back to a file you've opened, see Append Data to an Existing Excel Sheet with openpyxl. For when to use openpyxl versus a faster write-only engine, read openpyxl vs xlsxwriter vs pandas.ExcelWriter.