Python怎么读取Excel指定Sheet、行或列数据
详细讲解在Python中使用pandas与openpyxl读取Excel指定工作表(Sheet)、指定行和指定列数据的实用方法、参数技巧与避坑指南。
pandas 库(底层配合 openpyxl 解析引擎);如果项目追求轻量依赖或需要保留单元格格式与原始公式,也可以直接使用原生 openpyxl。在 pandas.read_excel() 函数中,通过 sheet_name 参数可直接锁定目标工作表,搭配 usecols 能按列字母或列名精准过滤列,结合 skiprows 与 nrows 或加载后的 iloc 则能自由截取目标行。本文将以清晰的步骤、对照示例和常见避坑点,完整讲解这两种方案在指定抽取数据时的具体操作方式。
一、准备工作与环境依赖
处理 .xlsx 格式的 Excel 表格前,需要准备对应的 Python 运行环境。建议在终端或命令行中安装 pandas 与 openpyxl:
pip install pandas openpyxl
为了使后文的所有示例统一且易于对照验证,我们假设当前目录下存在一个名为 sales_data.xlsx 的工作簿,其内容包含多个工作表,其中名为 "2026年销售明细" 的表格结构如下所示:
| 物理行号 | A列 (订单编号) | B列 (客户名称) | C列 (商品品类) | D列 (销售数量) | E列 (成交金额) |
|---|---|---|---|---|---|
| 第 1 行 (表头) | 订单编号 | 客户名称 | 商品品类 | 销售数量 | 成交金额 |
| 第 2 行 | ORD-2026-001 | 华东科技 | 显示器 | 15 | 19500.00 |
| 第 3 行 | ORD-2026-002 | 北方数码 | 机械键盘 | 40 | 11960.00 |
| 第 4 行 | ORD-2026-003 | 南方通信 | 固态硬盘 | 80 | 38400.00 |
| 第 5 行 | ORD-2026-004 | 西南实业 | 人体工学椅 | 10 | 12800.00 |
二、读取指定 Sheet (工作表)
一个 Excel 工作簿往往包含多个 Sheet。pandas.read_excel() 默认只会读取第 1 个工作表(索引为 0)。若要读取指定 Sheet,只需配置 sheet_name 参数。
1. 按工作表名称读取
直接将目标工作表的名称字符串传递给 sheet_name:
import pandas as pd
file_name = "sales_data.xlsx"
# 通过完整名称读取指定工作表
df_target = pd.read_excel(file_name, sheet_name="2026年销售明细")
print(df_target.head(2))
0 ORD-2026-001 华东科技 显示器 15 19500.0
1 ORD-2026-002 北方数码 机械键盘 40 11960.0
2. 按工作表数字索引读取
如果不确定 Sheet 确切名称,或者名称可能会动态变动,可以传入从 0 开始的整数索引。例如 0 代表第 1 个工作表,1 代表第 2 个工作表:
# 读取工作簿中的第 2 个工作表
df_second = pd.read_excel(file_name, sheet_name=1)
3. 一次读取多个或全部 Sheet
如果需要同时处理工作簿中的多张表,可以传入名称/索引列表,或者传入 sheet_name=None:
# 传入列表:返回字典,键为 Sheet 名称,值为对应 DataFrame
multi_sheets = pd.read_excel(file_name, sheet_name=["2026年销售明细", 1])
# 传入 None:返回包含该工作簿所有工作表的有序字典
all_sheets = pd.read_excel(file_name, sheet_name=None)
for sheet, df in all_sheets.items():
print(f"工作表 [{sheet}] 共有 {len(df)} 行数据")
三、读取指定 行 (Rows) 数据
读取指定行有两种常用思路:一种是在加载阶段直接限制(适用于大文件,避免无谓内存消耗),另一种是在读入内存后利用 DataFrame 切片(适用于灵活查找)。
1. 加载阶段通过参数限制行:skiprows 与 nrows
许多业务报表前几行是标题、填表说明或制表人信息,真正的数据行从第 3 行或第 4 行才开始。此时可以通过 skiprows 跳过无效行,再用 nrows 限制读取行数:
# 跳过前 2 行(例如前两行为合并标题和批注),随后只读取接下来的 10 行数据
df_rows = pd.read_excel(
file_name,
sheet_name="2026年销售明细",
skiprows=2,
nrows=10
)
2. 读入内存后通过 iloc 进行纯数字行切片
当工作表已读入 DataFrame 后,使用 .iloc 可以像 Python 列表一样按行下标连续截取:
df = pd.read_excel(file_name, sheet_name="2026年销售明细")
# 截取第 1 行至第 3 行(不包含第 4 行,左闭右开)
sub_rows = df.iloc[0:3]
# 截取指定的离散单行(例如第 1 行与第 3 行)
specific_rows = df.iloc[[0, 2]]
print(specific_rows[["订单编号", "客户名称"]])
0 ORD-2026-001 华东科技
2 ORD-2026-003 南方通信
四、读取指定 列 (Columns) 数据
在面对几十列的复杂报表时,全量加载不仅占用显存/内存,还会降低执行速度。通过 usecols 参数可以在读取时直接滤除非目标列。
1. 按 Excel 列字母范围读取 (推荐直观写法)
usecols 允许直接传递类似 Excel 坐标的列字母区间字符串,例如 "A:C" 或 "A, C:E":
# 仅读取 A 列、以及 C 列到 E 列,排除 B 列
df_cols_letter = pd.read_excel(
file_name,
sheet_name="2026年销售明细",
usecols="A, C:E"
)
print(df_cols_letter.columns.tolist())
2. 按列名称列表读取 (推荐业务代码写法)
如果报表的列顺序容易变动,但列名相对固定,直接传入表头名称列表是最健壮的写法:
# 仅载入业务关心的两列
df_cols_named = pd.read_excel(
file_name,
sheet_name="2026年销售明细",
usecols=["客户名称", "成交金额"]
)
3. 按列位置索引读取 (从 0 开始计数)
也可以传入列的下标列表。例如提取第 1 列(索引 0)与第 5 列(索引 4):
df_cols_indexed = pd.read_excel(
file_name,
sheet_name="2026年销售明细",
usecols=[0, 4]
)
五、综合实战:同时指定 Sheet、行范围与指定列
在实际工程中,最常见的场景是:在指定工作表中,只截取某一段行,并且只保留关键列。通过组合参数可以一行代码精准定位:
import pandas as pd
# 目标:从工作表 "2026年销售明细" 中,只取第 2~4 行(前3笔数据),且只要“客户名称”与“成交金额”两列
target_data = pd.read_excel(
"sales_data.xlsx",
sheet_name="2026年销售明细",
usecols=["客户名称", "成交金额"],
nrows=3
)
print(target_data)
0 华东科技 19500.00
1 北方数码 11960.00
2 南方通信 38400.00
六、原生轻量方案:使用 openpyxl 定位读取
如果所在运行环境对体积有严格限制(例如 AWS Lambda / 轻量 Docker 容器中不希望引入庞大的 pandas 与 numpy),直接使用 openpyxl 是官方推荐的轻量读写方案。
from openpyxl import load_workbook
# 加载工作簿 (data_only=True 表示读取公式计算结果而非公式原文)
wb = load_workbook("sales_data.xlsx", data_only=True)
# 1. 指定 Sheet:通过键值访问
ws = wb["2026年销售明细"]
# 2. 读取指定行列区域:例如第2行到第4行,第2列到第5列 (B2:E4)
# 注意:openpyxl 的行号和列号均从 1 开始计数
rows_data = []
for row in ws.iter_rows(min_row=2, max_row=4, min_col=2, max_col=5, values_only=True):
rows_data.append(row)
for r in rows_data:
print(r)
('北方数码', '机械键盘', 40, 11960.0)
('南方通信', '固态硬盘', 80, 38400.0)
七、两种方案的关键机制差异与选型依据
理解 pandas 与 openpyxl 的底层差异,能够帮助我们在面对不同业务场景时做出合理选择:
- 索引基数的根本区别:
pandas的切片与行号基于计算机常规的0-based(从 0 开始),而且默认把物理第 1 行作为 DataFrame 的列名;而openpyxl忠实于 Excel 的物理标号体系,是1-based(从 1 开始),min_row=1对应的就是 Excel 界面上行号为 1 的单元格。混用两者时切忌直接代入相同数值。 - 内存解析模型的差异:
pandas在执行read_excel时将整块数据解析并转换为连续内存的 C 数组/NumPy 结构,运算处理速度极快;而openpyxl将单元格包装成 Python 原生Cell对象,元数据丰富,但在十万行级别以上全量遍历时对象创建开销较高。 - 选型结论: 凡是后续涉及数据统计、关联合并、清洗或导出的分析任务,优先使用
pandas;凡是轻量化脚本、微服务、只需抽取单点单元格或必须保留单元格样式与批注的场景,使用openpyxl。
八、常见问题与实用避坑指南
日常业务中,人工导出的 Excel 工作表名称末尾经常带有一个看不见的半角空格(例如 "Sheet1 ")。直接传入 sheet_name="Sheet1" 会抛出 ValueError: Worksheet named 'Sheet1' not found。排查时建议先用代码打印所有工作表名:
# 查看工作簿内所有真实存在的 Sheet 完整名称
excel_file = pd.ExcelFile("sales_data.xlsx")
print(excel_file.sheet_names)
pd.read_excel() 默认设置 header=0,即把 Excel 物理第 1 行提取作为列标题,实际数据从物理第 2 行开始算作第 0 行。如果你的 Excel 文件没有表头,第 1 行就是纯数据,务必显式声明 header=None,否则第 1 行数据会被吞掉变成列名:
# 表格无表头时的安全读取写法
df_no_header = pd.read_excel("sales_data.xlsx", sheet_name=0, header=None)
如果单元格内是 =SUM(E2:E10) 这样的计算公式,openpyxl 默认加载时会读出字符串 "=SUM(E2:E10)"。若需要取得 Excel 保存时的实际数值结果,必须在打开工作簿时传递 data_only=True:
wb = load_workbook("sales_data.xlsx", data_only=True)
注意:如果该 Excel 文件是由第三方程序生成且从未在 Excel 软件中打开保存过,公式缓存值可能为空,此时读取结果可能为 None。
有时 Excel 底部或右侧残留有格式的空白单元格,导致读入的 DataFrame 尾部出现大量 NaN。可以在加载后立即调用 dropna 快速清理:
# 丢弃完全为空的行和列
df_clean = df.dropna(how="all", axis=0).dropna(how="all", axis=1)
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













