Guide

Getting Started With Python Excel AutomationDeep dive

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:

Bash
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:

Python
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:

Python
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:

Python
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:

Python
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:

Python
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:

Python
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

SymptomCauseFix
Got a <Cell> repr, not the valueRead the cell object, not its dataAppend .value: ws["B2"].value
IndexError or wrong cell with cell()Used 0-based indicesopenpyxl is 1-based; top-left is row=1, column=1
data_only=True returns NoneFile has no cached formula resultsOpen and save the file in Excel first; openpyxl won't compute
MemoryError on a huge fileLoaded the whole workbook into RAMUse load_workbook(path, read_only=True) and stream iter_rows
Edits don't stick after read_onlyread_only mode is non-writableDrop 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 .valuews["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.