openpyxl 读取 ExcelPython 帮你"看"表格
一、课堂故事
「同学们,今天班主任给我发了一份全班期中成绩表,让我帮她统计全班平均分和各科的最高分。我一看——50个学生,8门课,400个格子……」
我在讲台上打开一个 Excel 文件,投影到大屏幕上。密密麻麻的数字,一眼望不到头。
「如果用计算器一个一个加,这节编程课就变成数学课了。」我顿了顿,「但你们已经学了 pip 安装库,上节课还亲手装了 openpyxl。现在——是时候让它干活了。」
「老师,openpyxl 能帮我们读这个 Excel 吗?」小明举手。
「不仅能读。」我敲下第一行代码,「它就像一个戴着眼镜的小助手,帮你一行一行地看表格,比你眼睛还快。」
全班安静。屏幕上出现了 load_workbook。
「你们发给我的成绩单不是 CSV——是班主任用 Excel 做的,带表头、带格式、有颜色。CSV 拿它没办法。但 openpyxl 可以。」
我敲完最后一行 print,回车。屏幕上哗啦啦刷出了全班 50 个人的名字和成绩。
「你们刚才看到的这个操作,叫『读取 Excel 文件』。今天这节课——Python 帮你『看』表格。」
二、概念解释
Excel 文件的三个层级
先理清一个概念。一个 Excel 文件里面,是三层结构:
📁 成绩单.xlsx ← 工作簿(Workbook) ├─ 📄 Sheet1(语文成绩) ← 工作表(Worksheet) ├─ 📄 Sheet2(数学成绩) ← 工作表 └─ 📄 Sheet3(总分排名) ← 工作表 │ └─ 每个工作表里面是一个个格子: A1 → "姓名",B1 → "语文",C1 → "数学" A2 → "张三",B2 → 85,C2 → 92 A3 → "李四",B3 → 78,C3 → 88 ...每个格子叫 单元格(Cell)你之前在 Excel 里点来点去,就是在工作簿→工作表→单元格三层之间跳。openpyxl 也是同样的思维模型。
核心概念
读取 Excel 的三步走
第 1 步:load_workbook("文件名.xlsx") → 把"账本"翻开第 2 步:wb["Sheet1"] 或 wb.active → 翻到某一页第 3 步:ws["A1"].value 或 逐行遍历 → 读出格子的内容就这么简单。三步对应你在 Excel 软件里的三个动作:双击打开→点标签页→看格子。
三、拆开看
3.1 打开工作簿 + 选工作表
import openpyxl# 第1步:翻开账本wb = openpyxl.load_workbook("成绩单.xlsx")# 第2步:翻到第一页(两种写法都可以)ws = wb.active # 默认打开的那一页# 或者:ws = wb["Sheet1"] # 按名字选某一页wb.active 是打开文件时默认显示的那个工作表,通常是 Sheet1。如果你知道表名,直接用 wb["表名"] 更靠谱。
3.2 读单个格子
# 方法1:像Excel一样用地址name = ws["A2"].value # 读 A2 格子,拿到"张三"score = ws["B2"].value # 读 B2 格子,拿到 85# 方法2:用行号和列号name = ws.cell(row=2, column=1).value # 第2行第1列 = A2score = ws.cell(row=2, column=2).value # 第2行第2列 = B2关键点:.value 不能忘!没有 .value 你拿到的是 Cell 对象本身,不是里面的内容。
print(ws["A2"]) # 输出:<Cell 'Sheet1'.A2> ← 这是个对象print(ws["A2"].value) # 输出:张三 ← 这才是内容3.3 遍历整张表——逐行读
一个格子一个格子读太傻了。openpyxl 支持一行一行遍历:
# 遍历所有行(从第1行开始)for row in ws.iter_rows(values_only=True): print(row) # 输出:(None, None, None) ← 第1行如果是空行 # 输出:('姓名', '语文', '数学') ← 第2行是表头 # 输出:('张三', 85, 92) ← 第3行是数据 # 输出:('李四', 78, 88)values_only=True 的意思是「我只要格子里的值,不要 Cell 对象」。每一行是一个元组,元组里的元素就是这一行从左到右每个格子的内容。
常见用法:跳过表头,从数据行开始读:
for row in ws.iter_rows(min_row=2, values_only=True): name = row[0] # 第一列:姓名 chinese = row[1] # 第二列:语文 math = row[2] # 第三列:数学 print(f"{name}:语文{chinese},数学{math}")min_row=2 意思是「从第2行开始」,跳过第1行的表头。
3.4 获取表格尺寸
print(f"总共有 {ws.max_row} 行")print(f"总共有 {ws.max_column} 列")这俩属性告诉你表格有多大。后面做统计特别有用。
3.5 查看所有工作表名
print(wb.sheetnames)# 输出:['语文成绩', '数学成绩', '总分排名']3.6 完整示例:读取成绩单并计算平均分
import openpyxlwb = openpyxl.load_workbook("成绩单.xlsx")ws = wb.activetotal = 0count = 0# 从第2行开始(跳过表头),遍历所有学生for row in ws.iter_rows(min_row=2, values_only=True): name = row[0] chinese = row[1] math = row[2] avg = (chinese + math) / 2 print(f"{name}:语文{chinese},数学{math},平均{avg}") total += avg count += 1print(f"\n全班平均分:{total / count:.1f}")这段代码读 50 个人的成绩,不到 1 秒出结果。手动算至少半小时。
四、常见坑
坑 1:文件找不到——FileNotFoundError
wb = openpyxl.load_workbook("成绩单.xlsx")# 报错:FileNotFoundError: [Errno 2] No such file or directory原因:Python 在「当前工作目录」里找这个文件,而文件可能放在别的地方。
解决三招:
- 把 .xlsx 文件拖到和 .py 文件同一个文件夹里(最省事)
- 或者写完整路径:
load_workbook(r"C:\Users\你的名字\Desktop\成绩单.xlsx")
- 或者先
import os; print(os.getcwd()) 看看 Python 当前在哪个文件夹
别忘了 路径前面加 r,不然 \n、\t 会被当成转义字符!
坑 2:表名写错了
ws = wb["Sheet1"] # 但实际表名叫 "语文成绩"# 报错:KeyError: 'Worksheet Sheet1 does not exist.'解决:先打印所有表名确认一下:
print(wb.sheetnames) # 看看实际有哪些表坑 3:忘了 .value
name = ws["A2"] # 拿到的是 Cell 对象print(name) # <Cell 'Sheet1'.A2>这是新手最容易犯的错——以为自己读到了数据,实际上拿到了一个对象。读内容一定要加 .value。
坑 4:遍历时包含了表头
for row in ws.iter_rows(values_only=True): score = int(row[1]) # 第1行是表头"语文",int("语文") 会报错!解决:加 min_row=2 跳过表头。
坑 5:空行/合并单元格
Excel 里如果有空行或合并单元格,iter_rows 也会读出来。空行读出来是 (None, None, None, ...),处理前最好判断一下:
for row in ws.iter_rows(min_row=2, values_only=True): if row[0] is None: # 第一列是空的,跳过 continue # 正常处理...五、生活类比
🔍 放大镜类比
读 Excel 文件的过程,就像你拿一个放大镜看一本账本:
唯一的区别:你用眼睛看一个格子要 1 秒,Python 1 秒能看几千个格子。
📖 读书类比
也可以把 Excel 比作一本书:
load_workbook 是翻开书,wb["章节名"] 是翻到某一章,.value 是读出那个字。
六、练一练
第 1 题:手动建一个 Excel 并读取
用 Excel 新建一个文件叫 成绩表.xlsx,做成这样:
保存到和你的 .py 文件同一个文件夹。然后写代码:
import openpyxlwb = openpyxl.load_workbook("成绩表.xlsx")ws = wb.active# 分别读 A1、B1、A2、B2 的值,打印出来print(ws["A1"].value)print(ws["B1"].value)print(ws["A2"].value)print(ws["B2"].value)你看到了什么?
第 2 题:遍历成绩表
用第 1 题的成绩表,写代码遍历所有学生的成绩并打印:
import openpyxlwb = openpyxl.load_workbook("成绩表.xlsx")ws = wb.activefor row in ws.iter_rows(min_row=2, values_only=True): print(f"{row[0]}:语文{row[1]},数学{row[2]}")修改代码,在每行后面加上两科的平均分。
第 3 题:统计全班数据
继续用成绩表,写代码统计:
提示:用 ws.max_row 获取行数,在遍历过程中累加分数、比较大小。
第 4 题(挑战题):读取多个工作表
新建一个 Excel,包含两个工作表:Sheet1 叫「期中成绩」,Sheet2 叫「期末成绩」。每个表里都有张三、李四、王五的成绩。
写代码分别读取两个表,计算每个人期中+期末的总平均分,打印排名。
提示:wb.sheetnames 获取所有表名,wb["期中成绩"] 选表。
小结
ws.iter_rows(min_row=2, values_only=True)
- 常见坑:文件找不到、表名写错、忘了 .value、没跳表头
- Excel 的三层结构:工作簿 → 工作表 → 单元格,和你在软件里的操作一模一样
下节课,我们不止读 Excel——我们要写 Excel。把字典里的成绩数据,一键导出成班主任要的那种带格式的 .xlsx 文件!
📦 本篇练习答案 + 全套习题包
做完题卡住了?别硬憋——这一篇的练习答案,以及已发各篇(while / for / 字符串切片 / 列表 vs 元组 / range / 字典键值对……)的答案 PDF,我都打包好了,在下面网盘里。
🔗 网盘链接:
https://pan.baidu.com/s/1QCLD4qj0wEuJgokiZf5SdQ?pwd=i273
💡 提取码 i273 已嵌在链接里,点开直接下,不用再输~
卡住了随时在公众号留言问我,或者直接回复关键词 答案 也能拿到。我看到都会回 👋