早上九点,我刚打开电脑,同事小张就抱着一摞Excel文件冲了过来。
“帮帮忙,我这二十多个Excel文件,每个里面都要加一个汇总工作表,还要把那个旧的测试表删掉。我一个一个手动操作,弄到明年也弄不完啊。”
我看了看他那生无可恋的表情,笑了笑说:“别急,Python几行代码就搞定了。”
小张一脸怀疑:“Python还能干这个?”
当然能。而且比你想象的要简单得多。
准备工作:装个库就行
要用Python操作Excel,我们需要一个叫openpyxl的库。它就像是一个翻译官,让Python能听懂Excel说的话。
打开命令行,输入这一行:
pip install openpyxl
如果你用的是Jupyter Notebook或者Anaconda,也可以用:
conda install openpyxl
装好了之后,我们就可以开始玩了。
第一个例子:打开一个Excel文件
假设我们有一个叫“销售数据.xlsx”的文件,里面已经有一些工作表了。
from openpyxl import load_workbook
# 加载Excel文件
wb = load_workbook('销售数据.xlsx')
# 看看里面有哪些工作表
print(wb.sheetnames)
运行这段代码,你会看到类似这样的输出:
['一月销售', '二月销售', '三月销售', '旧数据_不要动']
好了,现在我们能看到这个Excel文件里到底藏了几个工作表。
添加新工作表:真的就一行代码
小张的第一个需求是加一个汇总表。怎么做呢?
# 在最后面添加一个叫“季度汇总”的工作表
wb.create_sheet('季度汇总')
# 保存文件
wb.save('销售数据.xlsx')
就这么简单。create_sheet这个方法就是用来创建新工作表的。
如果你想把这个新工作表放在最前面,可以这样写:
# 在第一个位置插入新工作表
wb.create_sheet('季度汇总', 0)
那个0表示位置索引。0就是第一个,1就是第二个,依此类推。
小张看完这段代码,瞪大了眼睛:“就这?我手动点半天,你一行代码就搞定了?”
我点点头:“Python就是干这个用的。”
删除工作表:同样简单
小张的第二个需求是删掉那个叫“旧数据_不要动”的工作表。
删除操作也很直接:
# 获取要删除的工作表
old_sheet = wb['旧数据_不要动']
# 删除它
wb.remove(old_sheet)
# 保存
wb.save('销售数据.xlsx')
注意一个坑:删除工作表之后,一定要记得保存。不保存的话,原文件不会发生任何变化。
还有一个更简洁的写法:
# 一行搞定
wb.remove(wb['旧数据_不要动'])
wb.save('销售数据.xlsx')
小张看到这里,已经开始兴奋了:“那我要处理二十多个文件,是不是写个循环就行了?”
“聪明。”
批量处理:让电脑帮你干活
小张的实际情况是:一个文件夹里有二十多个Excel文件,每个都要做同样的操作——添加“汇总”表,删除“临时”表。
我们写个循环来解决:
import os
from openpyxl import load_workbook
# 存放Excel文件的文件夹路径
folder_path = 'C:/销售数据/'
# 遍历文件夹里所有的文件
for filename in os.listdir(folder_path):
if filename.endswith('.xlsx'): # 只处理Excel文件
file_path = os.path.join(folder_path, filename)
# 打开文件
wb = load_workbook(file_path)
# 添加汇总表(如果还没有的话)
if '汇总' not in wb.sheetnames:
wb.create_sheet('汇总')
# 删除临时表(如果存在的话)
if '临时' in wb.sheetnames:
wb.remove(wb['临时'])
# 保存修改
wb.save(file_path)
print(f'处理完成:{filename}')
print('全部搞定!')
跑完这个脚本,小张那二十多个文件就全部处理好了。他只需要去泡杯咖啡,回来就能看到结果。
避坑指南:新手最容易踩的五个坑
坑一:忘记保存
这是最常见的问题。代码写完了,运行也没报错,但打开Excel一看,什么都没变。
原因很简单:忘了写wb.save()。
记住一个原则:load_workbook只是把文件读到内存里,所有修改都只是在内存中。只有执行save,才会真正写回硬盘。
坑二:删除不存在的工作表
如果你试图删除一个不存在的工作表,Python会直接报错。
# 这样写,如果工作表不存在就会报错
wb.remove(wb['不存在的表']) # 报错!
安全的写法是先判断一下:
if '不存在的表' in wb.sheetnames:
wb.remove(wb['不存在的表'])
坑三:工作表名字不能重复
Excel不允许同一个文件里有重名的工作表。如果你尝试创建两个同名的表,Python会报错。
wb.create_sheet('汇总')
wb.create_sheet('汇总') # 报错!名字重复了
要么先检查是否存在:
if '汇总' not in wb.sheetnames:
wb.create_sheet('汇总')
要么换个名字:
wb.create_sheet('汇总_v2')
坑四:文件被占用
如果你在运行Python脚本的时候,Excel文件正被其他程序(比如你手动打开的Excel)打开着,Python就没法写入。
解决方法:关掉那个文件,或者换个没被占用的文件。
坑五:openpyxl不支持.xls文件
openpyxl只能处理.xlsx格式的文件。如果你遇到老旧的.xls文件,需要用另一个库叫xlrd和xlwt。
如果实在需要处理.xls文件,最简单的办法是先用Excel把它另存为.xlsx格式。
玩点高级的:添加带数据的工作表
光添加一个空表可能还不够。有时候我们想在新表里填上一些数据,比如汇总统计。
来看个例子:把所有月份的数据汇总到一个新表里。
from openpyxl import load_workbook
wb = load_workbook('销售数据.xlsx')
# 创建汇总表
summary_sheet = wb.create_sheet('自动汇总')
# 写个标题
summary_sheet['A1'] = '月份'
summary_sheet['B1'] = '总销售额'
# 从各个月份的表里收集数据
row_num = 2
for month in ['一月销售', '二月销售', '三月销售']:
if month in wb.sheetnames:
month_sheet = wb[month]
# 假设每个月的表里,B列是销售额,从第2行到第10行
total = 0
for row in range(2, 11):
cell_value = month_sheet.cell(row, 2).value
if cell_value and isinstance(cell_value, (int, float)):
total += cell_value
# 写入汇总表
summary_sheet.cell(row_num, 1, month)
summary_sheet.cell(row_num, 2, total)
row_num += 1
wb.save('销售数据_带汇总.xlsx')
这样跑完之后,新生成的Excel文件里就多了一个“自动汇总”表,里面整整齐齐地列着每个月的总销售额。
更优雅的写法:使用with语句
每次都要手动save,有时候会忘记。Python提供了一个更优雅的写法,叫做上下文管理器。不过openpyxl本身不直接支持,我们可以自己封装一下:
from openpyxl import load_workbook
def process_excel(file_path):
wb = load_workbook(file_path)
# 在这里做各种操作
wb.create_sheet('新表')
# 自动保存
wb.save(file_path)
process_excel('我的文件.xlsx')
把操作写成一个函数,调用完自动保存,这样就不容易忘了。
实战小项目:清理Excel工具箱
最后,我们来做一个实用的小工具。它可以:
- 删除所有名字里带“备份”的工作表
- 在每个文件开头添加一个“目录”工作表
- 把所有工作表的名字列在目录里
import os
from openpyxl import load_workbook
def clean_and_add_catalog(folder_path):
for filename in os.listdir(folder_path):
if not filename.endswith('.xlsx'):
continue
file_path = os.path.join(folder_path, filename)
print(f'正在处理:{filename}')
wb = load_workbook(file_path)
# 找出所有带“备份”的工作表并删除
sheets_to_delete = [s for s in wb.sheetnames if '备份' in s]
for sheet_name in sheets_to_delete:
wb.remove(wb[sheet_name])
print(f' 已删除:{sheet_name}')
# 在第一个位置创建目录表
catalog = wb.create_sheet('目录', 0)
catalog['A1'] = '工作表目录'
catalog['A2'] = '序号'
catalog['B2'] = '工作表名称'
# 列出所有剩余的工作表
for idx, sheet_name in enumerate(wb.sheetnames[1:], start=1): # 跳过目录表自己
catalog.cell(idx + 2, 1, idx)
catalog.cell(idx + 2, 2, sheet_name)
wb.save(file_path)
print(f' 完成!剩余工作表:{wb.sheetnames[1:]}\n')
# 使用
clean_and_add_catalog('C:/我的Excel文件/')
这个工具跑完,每个文件都会变得更干净、更好用。
总结一下(别担心,很短)
Python操作Excel工作表,核心就三个动作:
- 加载:
load_workbook('文件.xlsx') - 添加:
create_sheet('表名') - 删除:
remove(工作表对象) - 保存:
save('文件.xlsx')
会了这三个,再加上一个循环,就能处理成百上千个文件。
小张后来请我喝了杯咖啡。他说:“早知道Python这么方便,我过去那些加班的晚上都白费了。”
我说:“没事,现在开始用,以后就不用加班了。”
他笑了笑,回去继续写他的Python脚本去了。这次不是为了加班,而是为了早点下班。