在办公自动化场景中,经常需要对多个Excel工作簿统一添加一张指定名称的工作表,例如“汇总”、“备注”或“参数说明”。手动逐个打开文件新增效率极低且容易遗漏。本文介绍如何使用Python的xlwings库遍历文件夹,判断目标工作表是否存在,并仅在工作表不存在时新增,同时给出循环控制、日志记录以及批量删除的扩展思路。
- import os
- import xlwings as xw
- folder_path = r"e:\file" # 存放Excel文件的文件夹
- sheet_name = "汇总" # 需要新增的工作表名称
- app = xw.App(visible=False, add_book=False) # 后台启动Excel,不显示界面
- try:
- for file in os.listdir(folder_path):
- # 跳过Excel临时文件(以~$开头)
- if file.startswith("~$"):
- continue
- # 只处理常见Excel文件格式
- if not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
- continue
- full_path = os.path.join(folder_path, file)
- wb = app.books.open(full_path)
- # 获取当前工作簿中所有工作表名称列表
- sheet_names = [j.name for j in wb.sheets]
- # 仅当目标工作表不存在时才新增
- if sheet_name not in sheet_names:
- wb.sheets.add(sheet_name)
- wb.save()
- print(f"已新增:{file} -> [{sheet_name}]")
- else:
- print(f"已存在:{file} -> [{sheet_name}],跳过")
- wb.close()
- finally:
- app.quit()
复制代码
**核心逻辑:先判断,再操作**
Excel工作簿不允许存在两个同名的表。因此不能直接对所有文件执行add()操作。上述代码通过列表推导式sheet_names = [j.name for j in wb.sheets]获取已有工作表名称,再用not in判断,确保仅在不存在时才新增。这种做法是批处理的安全机制,可避免因重复创建导致的中断。
**循环控制:continue与break的区分**
- 外层文件遍历中,遇到~$临时文件或不支持的扩展名时使用continue:跳过当前文件,继续处理下一个。
- 在内层工作表查找场景(如批量删除示例)中,找到目标表后可使用break结束当前工作簿内部的查找循环,不影响其他文件的处理。注意break只跳出当前最内层循环。
**批量删除工作表的扩展案例**
删除操作风险更高,必须确保目标表存在再删除,并建议先备份。同套路遍历文件,找到工作表后调用delete()方法:
- import os
- import xlwings as xw
- folder_path = r"e:\file"
- target_sheet = "汇总"
- app = xw.App(visible=False, add_book=False)
- try:
- for file in os.listdir(folder_path):
- if file.startswith("~$"):
- continue
- if not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
- continue
- full_path = os.path.join(folder_path, file)
- wb = app.books.open(full_path)
- found = False
- for sht in wb.sheets:
- if sht.name == target_sheet:
- sht.delete()
- wb.save()
- found = True
- print(f"已删除:{file} -> [{target_sheet}]")
- break
- if not found:
- print(f"未找到:{file} -> [{target_sheet}],跳过")
- wb.close()
- finally:
- app.quit()
复制代码
**效果验证与日志记录**
脚本不报错不代表结果正确。建议打印处理状态或生成日志Excel:
- import os
- import xlwings as xw
- import pandas as pd
- folder_path = r"e:\file"
- sheet_name = "汇总"
- log_list = []
- app = xw.App(visible=False, add_book=False)
- try:
- for file in os.listdir(folder_path):
- if file.startswith("~$"):
- continue
- if not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
- continue
- full_path = os.path.join(folder_path, file)
- wb = app.books.open(full_path)
- sheet_names = [j.name for j in wb.sheets]
- if sheet_name not in sheet_names:
- wb.sheets.add(sheet_name)
- wb.save()
- status = "已新增"
- else:
- status = "已存在,跳过"
- log_list.append({
- "文件名": file,
- "目标工作表": sheet_name,
- "处理结果": status
- })
- wb.close()
- finally:
- app.quit()
- log_df = pd.DataFrame(log_list)
- log_df.to_excel(r"e:\file\处理日志.xlsx", index=False)
复制代码
**踩坑提醒**
1. Excel临时文件:打开Excel时产生的~$文件不可处理,需用if file.startswith("~$"): continue跳过。
2. 工作表名称合法性:避免在目标名称中使用/、\、?、*等特殊字符,否则add()会失败。
3. 文件占用:正在打开的Excel或被网盘同步锁定的文件保存可能失败。建议先复制到本地临时目录处理。
4. 释放Excel进程:xlwings使用后需调用app.quit()(放在finally块中),否则后台残留Excel进程会导致后续操作缓慢或文件锁定。
**总结**
批量新增工作表的核心不是add()本身,而是存在性判断。同一套思路可扩展至批量删除或批量改名。所有批处理脚本都应包含文件过滤、条件判断、日志记录和异常处理。正式使用前务必测试于备份文件,避免直接操作原始数据。 |