4. 工作表操作:创建/删除工作表、重命名、切换活动工作表、复制工作表
工作表操作,说白了就是Excel里的「页面管理」。
你想想看,一个工作簿里动辄几十个Sheet,要是不会批量操作,光靠鼠标点来点去,效率低得让人抓狂。我刚开始做RPA项目时,就吃过这个亏——手动复制了十几个表,结果格式全乱套了。
今天咱们就把这些操作一次性讲透。
4.1 创建与删除工作表
创建新表,最直接的方式就是调用create_sheet()方法。我个人习惯在创建时直接指定名称,避免后面再改。
from openpyxl import Workbook
wb = Workbook()
# 默认会有一个Sheet,我们叫它"原始数据"
ws = wb.active
# 创建新工作表,指定名称
ws_new = wb.create_sheet(title="销售报表")
# 创建在指定位置(比如最前面)
ws_front = wb.create_sheet(title="汇总", index=0)
print(wb.sheetnames) # 输出:['汇总', 'Sheet', '销售报表']
删除工作表更简单,用remove()方法。但这里有个坑——删除操作不可撤销。
# 安全删除工作表
sheet_name = "临时数据"
if sheet_name in wb.sheetnames:
wb.remove(wb[sheet_name])
print(f"已删除工作表:{sheet_name}")
else:
print(f"工作表 {sheet_name} 不存在,跳过删除")
4.2 重命名工作表
重命名很简单,直接给title属性赋值就行。但要注意,工作表名称不能超过31个字符,也不能包含冒号、斜杠等特殊符号。
ws = wb["Sheet"]
ws.title = "2024年Q1数据" # 重命名
# 批量重命名:给所有工作表加前缀
for i, sheet in enumerate(wb.worksheets, 1):
sheet.title = f"模块{i}_{sheet.title}"
4.3 切换活动工作表
活动工作表,就是当前被激活的那个Sheet。在openpyxl里,通过active属性来切换。
# 切换到指定工作表
wb.active = wb["销售报表"]
current_sheet = wb.active
print(f"当前活动工作表:{current_sheet.title}")
# 或者直接用索引切换
wb.active = wb.worksheets[2] # 切换到第3个工作表
嗯,这里要注意:active属性返回的是Worksheet对象,不是名称字符串。我见过不少新手在这里踩坑,直接写wb.active = "销售报表",结果报错了。
4.4 复制工作表
复制工作表,是实际项目中最常用的操作之一。openpyxl提供了copy_worksheet()方法,但有个限制——只能复制内容,不能复制图表、图片等复杂对象。
# 复制工作表
source_sheet = wb["模板"]
new_sheet = wb.copy_worksheet(source_sheet)
new_sheet.title = "复制_模板_2024"
# 复制后调整位置
wb.move_sheet(new_sheet, offset=-1) # 往前移一位
🔑 核心要点:
- 复制后的新表默认放在最后
- 新表会继承原表的所有单元格格式、公式、数据验证
- 但图表、数据透视表、图片不会被复制
- 复制后记得重命名,否则会报错(名称重复)
为什么会这样?因为openpyxl的复制机制是「浅拷贝」——它复制了单元格对象,但复杂对象(如图表)的引用关系没法自动重建。我在做报表自动化时,就因为这个特性,不得不手动重新绑定图表数据源。
4.5 实战:批量创建月度报表模板
咱们来一个综合案例。假设你要为2024年每个月创建一个报表,每个表都基于同一个模板。
from openpyxl import Workbook
from copy import copy
wb = Workbook()
# 先创建一个模板
template = wb.active
template.title = "模板"
template["A1"] = "月份"
template["B1"] = "销售额"
template["C1"] = "利润"
# 批量创建12个月的工作表
months = ["1月", "2月", "3月", "4月", "5月", "6月",
"7月", "8月", "9月", "10月", "11月", "12月"]
for month in months:
# 复制模板
new_sheet = wb.copy_worksheet(template)
new_sheet.title = f"2024年{month}"
# 填入月份标识
new_sheet["A2"] = month
# 删除模板表(可选)
if "模板" in wb.sheetnames:
wb.remove(wb["模板"])
print(f"共创建了 {len(wb.sheetnames)} 个工作表")
print(wb.sheetnames)
4.6 工作表操作的常见错误
| 错误类型 | 错误示例 | 正确做法 |
|---|---|---|
| 名称重复 | 创建两个同名工作表 | 创建前检查名称是否已存在 |
| 名称超长 | 工作表名称超过31字符 | 截断或使用缩写 |
| 删除未保存 | 删除后直接关闭工作簿 | 删除后调用wb.save() |
| 复制后未重命名 | 复制后直接使用默认名称 | 复制后立即设置title |
嗯,这些错误我基本都犯过。尤其是名称超长那个,有一次在服务器上跑脚本,突然报错,查了半天才发现是工作表名称多了一个字符。从那以后,我写了个校验函数:
def safe_sheet_name(name):
"""确保工作表名称合法"""
# 截断到31字符
if len(name) > 31:
name = name[:31]
# 替换非法字符
illegal_chars = ['\\', '/', '?', '*', '[', ']', ':']
for char in illegal_chars:
name = name.replace(char, '_')
return name
# 使用
ws.title = safe_sheet_name("2024年销售数据报表(第一季度)")
好了,工作表操作这块就讲到这里。说白了就是四个动作:创建、删除、重命名、复制。但每个动作背后都有细节,尤其是复制和删除,一定要谨慎。下一章咱们聊聊单元格的读写操作,那才是真正的重头戏。