Python实现Excel工作表的批量复制功能
1. 问题背景:为什么要把一个工作簿的所有工作表复制到其他工作簿
本文主题是:将一个工作簿的所有工作表批量复制到其他工作簿。这个场景很典型,也很贴近日常办公自动化:我们手里有一个标准来源工作簿,里面放着固定模板表或基础资料表,现在需要把这些表批量追加到多个目标工作簿中。
比如来源工作簿里有 员工信息、产品分类、价格体系、填表说明 这几张标准表,而目标文件夹里有很多业务工作簿,例如 华北销售.xlsx、华东销售.xlsx、华南销售.xlsx。如果每个文件都手动打开、复制、粘贴、保存,几十个文件处理下来,效率很低,而且特别容易漏表、贴错位置或者忘记保存。
推荐做法是:把这类“来源固定、目标多个、动作重复”的任务交给 Python 处理。人只负责确认模板是否正确、目标文件是否完整,脚本负责批量打开、复制、写入、保存。
这张图展示的是本文的整体目标:通过 Python + Excel 自动化,把一个来源工作簿中的多个工作表,批量复制到多个目标工作簿中。

从图中可以看出,整个任务不是“复制一个表到一个文件”,而是“一份来源,复制到多个目标”。这个判断很重要,因为一旦目标文件数量变多,手动操作就不可靠了,脚本化处理才有明显价值。
2. 场景说明:标准模板表批量下发
这个案例最适合处理一种办公场景:多个业务工作簿需要统一追加相同的标准工作表。例如销售部门每个区域都有自己的工作簿,但每个文件都必须包含统一的基础信息表、分类表、价格表和填写说明。
这种场景的关键不是数据多复杂,而是文件多、动作重复、标准要求一致。只要模板表结构固定,目标文件格式相对稳定,就可以通过脚本批量下发。
这里有一个容易忽略的点:不要把“能复制”误解成“可以随便覆盖”。如果目标工作簿里已经存在同名工作表,要先明确业务规则:是跳过、覆盖、清空后重写,还是改名追加。这个规则不先定好,脚本写得越快,风险越大。
这张图展示的是标准模板表批量下发的应用场景:把同一套标准资料包,统一追加到多个销售业务工作簿中。

从图中可以看出,来源工作簿中的 员工信息、产品分类、价格体系、填表说明 不是临时数据,而是多个目标工作簿都需要的标准模板表。这个场景下,用脚本批量追加,可以减少手动复制带来的格式不一致和漏操作问题。
3. 核心原理:读取来源簿,遍历目标簿,逐表写入
这个案例的核心逻辑可以拆成四步:第一,打开来源工作簿;第二,读取来源工作簿中的所有工作表;第三,遍历目标文件夹中的每一个目标工作簿;第四,将来源工作表逐张写入目标工作簿,并保存结果。
本质上,这不是简单的复制粘贴,而是一个批处理流水线。来源工作簿提供模板,目标文件夹提供批量处理对象,脚本负责把模板表逐个分发到每一个目标文件中。

从图中可以看出,处理顺序必须清楚。先读取来源簿,再处理目标簿;不能一边随意打开文件一边写入,否则很容易出现文件未关闭、目标表冲突、保存失败等问题。自动化脚本越是批量处理,越要先把流程想清楚。
4. 实现代码:批量复制来源工作簿中的所有工作表
下面这份代码使用 xlwings 实现。整体思路是:先打开来源工作簿,获取来源簿中的全部 sheet;然后遍历目标文件夹中的 Excel 文件;对每一个目标文件,按来源 sheet 名称新增或定位同名工作表,再把来源表数据写进去。
import os
import xlwings as xw
# ====== 需要根据实际情况修改的参数 ======
source_file = r"e:\file\来源模板.xlsx" # 来源工作簿
target_folder = r"e:\file\target" # 目标工作簿所在文件夹
# ======================================
app = xw.App(visible=False, add_book=False)
try:
# 1. 打开来源工作簿
src_wb = app.books.open(source_file)
# 2. 获取来源工作簿中的所有工作表
src_sheets = src_wb.sheets
# 3. 遍历目标文件夹下的所有文件
for file in os.listdir(target_folder):
# 跳过 Excel 临时文件
if file.startswith("~$"):
continue
# 只处理 Excel 文件
if not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
continue
target_path = os.path.join(target_folder, file)
tgt_wb = None
try:
tgt_wb = app.books.open(target_path)
# 读取目标工作簿中已有的工作表名称
tgt_sheet_names = [s.name for s in tgt_wb.sheets]
# 4. 将来源工作簿中的每张表写入目标工作簿
for src_sht in src_sheets:
sheet_name = src_sht.name
# 从 A1 开始读取连续表格区域
contents = src_sht.range("A1").expand("table").value
# 如果目标簿中没有同名表,则新增
if sheet_name not in tgt_sheet_names:
tgt_wb.sheets.add(sheet_name)
tgt_sheet_names.append(sheet_name)
# 写入目标同名工作表
tgt_sht = tgt_wb.sheets[sheet_name]
tgt_sht.clear()
tgt_sht.range("A1").value = contents
tgt_wb.save()
print(f"已处理:{file}")
finally:
if tgt_wb is not None:
tgt_wb.close()
src_wb.close()
finally:
app.quit()
这份脚本不是最短写法,但比较稳。它跳过了 ~$ 开头的 Excel 临时文件,也用 try/finally 确保目标工作簿能够关闭。 办公自动化脚本不是越短越好,而是越可控越好。
5. 关键代码逻辑:src_wb.sheets 与 expand(‘table’)
这类脚本最重要的不是背代码,而是理解关键对象和关键动作。本文里最核心的几个点是:src_wb.sheets 获取来源工作簿中的全部工作表;range("A1").expand("table").value 从 A1 开始读取连续数据区域;tgt_sht.range("A1").value = contents 将数据写入目标工作表。
expand('table') 的含义是:以指定单元格为起点,自动扩展到连续的表格区域。这里从 A1 开始读取,如果来源表是一个规范连续表格,就可以一次性拿到整块数据。
这张图展示的是关键代码逻辑:从来源工作表读取整块数据,再写入目标工作表的 A1 位置。

从图中可以看出,expand('table') 适合读取结构连续的数据表。如果来源表中间存在空行或空列,自动扩展区域可能会提前截断。 所以来源模板表必须尽量保持连续区域,不要在数据中间随意插入空行空列。
如果只是读取单张工作表的数据,可以单独理解下面这句:
contents = src_sht.range("A1").expand("table").value
它会把来源工作表中从 A1 开始的连续数据区域读取出来。随后通过下面这句写入目标表:
tgt_sht.range("A1").value = contents
这两句配合起来,就完成了“来源表数据复制到目标表”的核心动作。后面的遍历文件夹、循环工作表、保存关闭,本质上都是为了让这个动作批量执行。
6. 操作步骤:从测试文件到批量处理
如果第一次写这类脚本,我不建议直接对真实业务文件夹执行。更稳妥的步骤是:先准备一个来源模板文件,再复制两三个目标工作簿作为测试样本,确认追加结果正确后,再扩大到完整目录。
第一步,准备来源工作簿。来源工作簿中放入需要批量下发的工作表,例如 员工信息、产品分类、价格体系、填表说明。这些表名最好保持简洁、规范,不要包含特殊字符。
第二步,准备目标文件夹。把需要处理的目标工作簿统一放到一个目录中。目录里尽量不要混入无关文件,尤其不要把正在打开的 Excel 临时文件也当成目标文件处理。
第三步,先运行小范围测试。比如目标文件夹里只放 2 个测试工作簿,运行后检查是否成功追加了所有标准表,表名是否正确,内容是否完整。
第四步,再对正式目录执行。执行前最好备份原始目标文件夹,尤其是涉及真实业务数据时,不能只依赖脚本逻辑。
我的建议是:批量脚本第一次运行时先打印日志,不要急着处理全量文件。确认日志里列出的目标文件和工作表名称都符合预期,再正式保存处理结果。
print(f"准备处理目标文件:{target_path}")
print(f"准备复制来源工作表:{sheet_name}")
日志看起来不起眼,但实际排错时很有用。尤其是处理几十个 Excel 文件时,日志可以快速告诉你脚本处理到了哪个文件、哪张表出了问题。
7. 效果验证:不要只看脚本有没有报错
脚本运行结束后,不代表任务就完成了。真正要验证的是目标文件中是否已经成功追加了来源工作簿中的所有工作表,数据是否完整,原有业务表是否被误删或误覆盖。
我建议至少检查四个点:目标工作簿是否都被处理;每个目标工作簿是否都有新增的标准表;标准表中的数据区域是否完整;原目标文件中的原有工作表是否仍然存在。
如果目标文件数量多,可以写一个简单的检查脚本,把每个目标工作簿的 sheet 名称打印出来,确认标准表是否存在。
import os
import xlwings as xw
target_folder = r"e:\file\target"
required_sheets = ["员工信息", "产品分类", "价格体系", "填表说明"]
app = xw.App(visible=False, add_book=False)
try:
for file in os.listdir(target_folder):
if file.startswith("~$"):
continue
if not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
continue
path = os.path.join(target_folder, file)
wb = None
try:
wb = app.books.open(path)
sheet_names = [s.name for s in wb.sheets]
missing = [s for s in required_sheets if s not in sheet_names]
if missing:
print(f"缺少工作表:{file} -> {missing}")
else:
print(f"检查通过:{file}")
finally:
if wb is not None:
wb.close()
finally:
app.quit()
这个检查脚本的价值在于:它不修改文件,只验证结果。对于批量处理任务来说,验证脚本和处理脚本一样重要。只会执行,不会验证,这种自动化还不够稳。
8. 常见问题:复制工作表前后必须检查的坑
批量复制工作表最大的风险不是代码语法,而是文件状态和业务规则。Excel 文件经常会有临时文件、占用状态、同名工作表、格式残留等问题。如果这些问题不提前处理,脚本很容易中途失败。
这张图展示的是复制工作表前后要重点检查的几个坑:临时文件、同名工作表、未关闭工作簿,以及运行后的结果验证。

从图中可以看出,~$ 开头的文件是 Excel 临时文件,不能当成正式工作簿处理。目标工作簿中如果已经存在同名工作表,也必须先明确处理策略,否则可能出现覆盖、清空或复制失败。还有一个很现实的问题:如果工作簿没有关闭,文件可能会被占用,后续保存、删除、移动都会受影响。
这里我更建议保守处理:脚本默认跳过临时文件;遇到同名工作表时,不要偷偷覆盖,而是先记录日志或明确清空重写;处理每个目标文件时,都用 try/finally 确保关闭工作簿。
if file.startswith("~$"):
continue
这一句看似简单,但非常必要。很多 Excel 自动化脚本报错,就是因为把临时文件也拿去打开了。
try:
tgt_wb = app.books.open(target_path)
# 处理逻辑
finally:
if tgt_wb is not None:
tgt_wb.close()
这一段则是为了释放资源。批量处理几十个文件时,如果打开的工作簿不及时关闭,Excel 后台进程可能越来越多,脚本也会越来越慢,甚至直接卡死。
9. 举一反三:只复制某一张工作表到多个目标工作簿
上面的代码是复制来源工作簿中的所有工作表。但真实工作中,有时候只需要复制某一张表,比如只把 员工信息 追加到多个目标工作簿。这时可以把来源表名单独作为参数,提高脚本的可控性。
import os
import xlwings as xw
source_file = r"e:\file\来源模板.xlsx"
source_sheet_name = "员工信息"
target_folder = r"e:\file\target"
target_sheet_name = "员工信息"
app = xw.App(visible=False, add_book=False)
try:
src_wb = app.books.open(source_file)
src_sht = src_wb.sheets[source_sheet_name]
src_data = src_sht.range("A1").expand("table").value
for file in os.listdir(target_folder):
if file.startswith("~$"):
continue
if not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
continue
target_path = os.path.join(target_folder, file)
tgt_wb = None
try:
tgt_wb = app.books.open(target_path)
sheet_names = [s.name for s in tgt_wb.sheets]
if target_sheet_name not in sheet_names:
tgt_wb.sheets.add(target_sheet_name)
tgt_sht = tgt_wb.sheets[target_sheet_name]
tgt_sht.clear()
tgt_sht.range("A1").value = src_data
tgt_wb.save()
print(f"已追加:{file} -> {target_sheet_name}")
finally:
if tgt_wb is not None:
tgt_wb.close()
src_wb.close()
finally:
app.quit()
这份脚本比“复制所有工作表”更精确,适合只下发某一张标准表的场景。 如果你的需求不稳定,经常只复制某一张表,我更推荐这种参数化写法。
10. 总结提升:把复制工作表理解成批量分发能力
这一节表面上是在学习“复制工作表”,实际上是在训练一种很重要的办公自动化能力:把标准内容批量分发到多个业务文件中。这个能力很实用,因为很多办公文件的痛点不是不会做,而是重复做、反复做、每次都容易漏。
这类任务的核心不是炫技,而是稳定。路径要明确,来源要固定,目标要筛选,临时文件要跳过,同名表要有规则,文件资源要关闭,运行后要验证结果。只要这些点都考虑到,脚本才真正接近可复用。
不要只追求脚本跑通。跑通只是第一步。真正能用于工作场景的脚本,必须能解释处理逻辑、能输出日志、能避免误操作、能验证结果,还要能在出错时知道问题发生在哪个文件。
我对这一节的理解是:Excel 自动化不是简单替代鼠标操作,而是把一套明确的办公规则固化下来。批量复制工作表,就是把“标准模板表下发”这件事变成可重复、可检查、可沉淀的流程。
以上就是Python实现Excel工作表的批量复制功能的详细内容,更多关于Python复制Excel工作表的资料请关注脚本之家其它相关文章!


最新评论