Python批量替换Excel多个工作簿的行数据
作者:杨利杰YJlio
1. 问题背景:为什么要批量替换多个工作簿的行数据
本文主题是 批量替换多个工作簿的行数据。和前面批量调整格式、批量改文件名不同,这一节已经进入“数据修正”层面,操作风险更高,但实际价值也更大。
在日常办公里,很多 Excel 报表的问题不是格式乱,而是源数据中有一类固定错误。例如部门名称变更、产品名称写错、负责人信息调整、金额或状态字段需要统一修正。如果只改一个文件,手动操作还能接受;如果几十个工作簿里都有同样的问题,继续手工修改就很容易漏改、错改,而且后续也不好追溯。
这张图展示的是本文的核心目标:用 Python 批量打开多个 Excel 工作簿,将符合条件的旧行数据替换成新的标准行数据。

从图中可以看出,本文不是简单替换某个单元格,而是对一整行数据做匹配和替换。例如旧数据是 北京 | 销售 | 张三 | 1000,新数据是 北京 | 销售事业部 | 张三 | 1200。这种处理方式更适合“整条记录需要统一修正”的场景。
风险提醒:整行替换比单元格替换更敏感。因为它会一次性覆盖多个字段,所以必须先确认匹配条件足够准确,不能只凭某一个模糊字段就直接改整行。
2. 场景说明:哪些情况适合整行替换
批量替换行数据最适合处理“多个文件中存在同一类错误记录”的场景。例如分公司报表、区域报表、销售数据、客户信息、订单明细等多个工作簿里,都存在同一条旧记录,现在需要统一替换成新的标准记录。
这张图展示的是批量替换行数据的典型应用场景。

从图中可以看出,多个 Excel 文件中都存在同样的错误数据,统一修正后可以让产品名称、部门名称、订单记录等信息保持一致。这类需求在财务报表、销售报表、客户资料、资产台账里都很常见。
推荐做法:如果只是某一列名称变更,例如“销售”改成“销售事业部”,优先考虑按列替换;如果一条记录中多个字段都要同步修正,再考虑整行替换。不要把简单问题复杂化。
我个人更建议把整行替换用于“确定性很强”的修正任务,比如某条订单记录、某个员工数据、某条资产明细确实需要整体替换。它不适合用来做模糊清洗,也不适合在字段不稳定的情况下直接批量执行。
3. 核心原理:enumerate() 定位行号,if 精确匹配整行
这一节的核心不是 xlwings 本身,而是两个判断动作:第一,遍历每一行时同时拿到行号;第二,判断当前行是否和目标旧行完全一致。前者靠 enumerate(),后者靠 if row == old_row。
这张图展示的是本文最关键的技术原理:用 enumerate() 拿到 Excel 行号,再用 if 判断是否精确匹配旧行。

从图中可以看出,程序会逐行比较当前行数据和 old_row。只有当整行内容完全一致时,才会执行替换,把该行改成 new_row。这里的 idx 非常关键,因为它对应 Excel 中真实的行号。
for idx, row in enumerate(rows, start=2):
if row == old_row:
sht.range(f"A{idx}").value = new_row
原理说明:rows 是去掉表头后的数据行,所以它在 Python 里从第 1 条数据开始遍历,但在 Excel 里真实行号通常从第 2 行开始。因此这里使用 start=2,让 idx 和 Excel 行号对齐。
注意:row == old_row 是精确匹配。只要某个单元格多了空格、数字类型不一致、日期格式不同,匹配就可能失败。所以正式处理前一定要先确认源数据格式。
4. 操作流程:从遍历文件到保存结果
在写代码前,先把处理流程拆清楚。这类脚本不能一上来就写替换逻辑,而要先完成文件筛选、工作表检查、数据读取、行匹配、写回保存这些基本步骤。
这张图展示的是完整执行流程:遍历文件、读取表格、精确匹配、替换整行、保存结果。

从图中可以看出,整行替换并不是单一动作,而是一条完整链路。任何一个环节漏掉,都会影响最终结果。比如不检查目标工作表,就可能打开文件后直接报错;不保存工作簿,就会出现控制台提示替换成功,但文件内容实际没有变化。
推荐做法:正式运行前先做“只打印不保存”的预览模式,把命中的文件名和行号输出出来。确认命中范围没问题,再放开写入和保存。
5. 完整代码:批量替换多个工作簿的整行数据
下面这段代码使用 xlwings 批量打开文件夹中的 Excel 工作簿,读取指定工作表的数据区域,然后通过 enumerate() 逐行匹配 old_row,命中后替换为 new_row。
import os
import xlwings as xw
# ====== 需要根据实际情况修改的参数 ======
folder_path = r"e:\file\target"
sheet_name = "Sheet1"
# 要被替换的整行数据:必须与 Excel 中读取出来的行完全一致
old_row = ["北京", "销售", "张三", 1000]
# 替换后的整行数据
new_row = ["北京", "销售事业部", "张三", 1200]
# =====================================
app = xw.App(visible=False, add_book=False)
try:
for file_name in os.listdir(folder_path):
# 跳过 Excel 临时文件
if file_name.startswith("~$"):
continue
# 只处理 Excel 文件
if not file_name.lower().endswith((".xlsx", ".xls", ".xlsm")):
continue
full_path = os.path.join(folder_path, file_name)
wb = app.books.open(full_path)
try:
sheet_names = [s.name for s in wb.sheets]
if sheet_name not in sheet_names:
print(f"跳过:{file_name},不存在工作表 {sheet_name}")
continue
sht = wb.sheets[sheet_name]
# 读取当前连续数据区域
table_rng = sht.range("A1").current_region
table = table_rng.value
if not table or len(table) < 2:
print(f"跳过:{file_name},没有可处理的数据")
continue
header = table[0]
rows = table[1:]
hit_count = 0
for idx, row in enumerate(rows, start=2):
if row == old_row:
sht.range(f"A{idx}").value = new_row
hit_count += 1
if hit_count > 0:
wb.save()
print(f"已替换:{file_name},命中 {hit_count} 行")
else:
print(f"未命中:{file_name}")
finally:
wb.close()
finally:
app.quit()
这段代码里我额外保留了 hit_count,用于统计当前文件命中了几行。这个细节很实用,因为批量修改数据时,不能只知道“成功或失败”,还要知道到底改了几处。
原理说明:sht.range(f"A{idx}").value = new_row 会从当前行的 A 列开始写入整行数据。只要 new_row 的字段数量和原表列数一致,就可以覆盖这一整行。
风险提醒:如果 new_row 的长度比原表列数短,后面的旧数据可能残留;如果比原表列数长,可能写到表格外侧。整行替换前必须确认字段数量一致。
6. 关键代码理解:为什么 start=2 很重要
很多人写到这里会误以为 enumerate() 只是为了拿序号。这个理解不够准确。在本案例里,enumerate() 的真正价值是让 Python 遍历位置和 Excel 行号建立对应关系。
假设 Excel 第 1 行是表头,真正的数据从第 2 行开始。我们把 table[1:] 取出来后,Python 里的第一条数据其实对应 Excel 第 2 行。如果不使用 start=2,写回时就可能把行写错位置。
rows = table[1:]
for idx, row in enumerate(rows, start=2):
print(idx, row)
输出效果可以理解为:
2 ['上海', '技术部', '李四', 900]
3 ['广州', '市场部', '王五', 1100]
4 ['北京', '销售', '张三', 1000]
5 ['深圳', '财务部', '赵六', 800]
推荐做法:只要你要把 Python 中的行数据写回 Excel,就要先想清楚 Python 索引和 Excel 行号是否对齐。不要凭感觉写 A1、A2,那很容易错位。
7. 常见问题:批量替换前后必须校验
批量替换行数据最容易翻车的地方,通常不是语法,而是运行前没有校验,运行后没有复核。尤其是多个工作簿批量修改,一旦规则写错,影响范围会被快速放大。
这张图展示的是批量替换整行数据时必须注意的几个检查点。

从图中可以看出,至少要检查五件事:跳过 ~$ 临时文件,确认目标工作表存在,整行必须完全一致,替换后要保存,最后还要核对结果。这里每一步都不是装饰,而是防止批量脚本出事故的安全动作。
坑 1:Excel 临时文件没有跳过。打开 Excel 文件时,同目录可能出现 ~$ 开头的临时文件。它不是正常工作簿,必须跳过。
坑 2:目标工作表不存在。多个工作簿的工作表名称不一定完全一致,有的叫 Sheet1,有的可能叫 明细。如果不先判断,脚本容易中途报错。
坑 3:整行数据看似一样,实际不一致。比如金额在 Excel 中读取出来可能是 1000.0,而你写的 old_row 是 1000;又比如文本前后有空格。精确匹配时,这些差异都会影响命中。
如果你遇到明明表里有数据却匹配不到,可以先打印出每一行看真实读取结果:
for idx, row in enumerate(rows, start=2):
print(idx, row)
推荐做法:正式替换前先运行一次预检查,只输出“命中的文件名、行号、旧行内容”,不要直接保存。确认命中范围正确后,再执行正式替换。
8. 效果验证:不要只看控制台提示成功
脚本运行完成后,不要只看控制台输出“已替换”。真正要验证的是:目标文件是否真的被保存,命中数量是否符合预期,替换后的行是否完整,文件是否还能正常打开。
我建议至少做三类验证。第一,检查命中数量。例如预计 6 个文件里都有这条旧记录,那么命中数量就不应该只有 1 个。第二,抽查 Excel 文件中的目标行,确认旧数据已经变成新数据。第三,确认文件可以正常打开,没有因为保存异常导致损坏。
total_hits = 0
# 每个文件命中后累加
total_hits += hit_count
print(f"本次总命中行数:{total_hits}")
原理说明:批量替换的验证逻辑不是“脚本能跑”,而是“修改范围符合预期”。如果命中太多,可能规则过宽;如果命中太少,可能旧行写错、数据格式不一致或目标工作表不对。
不要犯的错误:不要在原始文件夹里直接运行未验证脚本。批量写入 Excel 属于破坏性操作,建议先复制一份测试目录,再对测试目录执行。
9. 总结提升:把整行替换变成可复用脚本模板
这一节的核心,不是记住 enumerate() 这个函数,而是理解“批量遍历多个工作簿、读取数据区域、精确定位目标行、写入新行并保存”的完整流程。
我认为这篇笔记最值得沉淀的经验有三点。
第一,精确匹配适合确定性修正。如果旧数据明确、字段稳定、行内容可控,使用 row == old_row 很安全;如果数据格式混乱,就要先清洗再匹配。
第二,批量脚本必须有命中统计。只输出“已完成”没有意义,应该明确每个文件命中几行、总共命中几行,这样才能复盘。
第三,保存前后都要留证据。正式工作里,建议保留处理日志,至少记录文件名、行号、旧数据、新数据和处理时间。否则一旦用户反馈数据不对,很难追溯。
从办公自动化角度看,这类脚本非常适合作为“批量数据修正模板”。后续可以继续扩展成带界面的小工具,让用户选择目标文件夹、输入旧行和新行、选择工作表名称,再自动生成替换日志。这样才算真正从读书笔记走向可交付工具。
以上就是Python批量替换Excel多个工作簿的行数据的详细内容,更多关于Python批量替换Excel行数据的资料请关注脚本之家其它相关文章!
