2026-10-08 · 本文所有输出均为作者在本机真实运行结果
同事发来的表,"部门"列是合并单元格:研发部占了 2 行、人事部占了 3 行。看着整齐,但只有每块左上角的格子里有值——你想筛选某个部门、用 vlookup 按部门匹配、或者做透视表,出来的全是空白。手动一格一格填?合并区块一多就疯。
合并只是"显示上合并",底层只有左上角那个单元格存值,其余格子是空的。所以要做的事就两步:解除合并 → 把左上角的值抄进区块里的每个格子。
from openpyxl import load_workbook
def unmerge_fill(path, out):
wb = load_workbook(path)
ws = wb.active
for rng in list(ws.merged_cells.ranges): # 注意必须先拷成 list
v = ws.cell(rng.min_row, rng.min_col).value
ws.unmerge_cells(str(rng))
for rr in range(rng.min_row, rng.max_row + 1):
for cc in range(rng.min_col, rng.max_col + 1):
ws.cell(rr, cc).value = v
wb.save(out)
unmerge_fill('in.xlsx', 'out.xlsx')
测试数据:研发部合并 2 行、市场部 1 行(未合并)、人事部合并 3 行。跑完后:
剩余合并区: 0
['研发部', '张三', 3000]
['研发部', '李四', 4200]
['市场部', '王五', 3500]
['人事部', '赵六', 2800]
['人事部', '钱七', 3100]
['人事部', '孙八', 2900]
横向合并(比如一行里"备注"横跨 B2:C2)同样能补齐——实测 B2/C2 都填上了"重要备注"。
for rng in ws.merged_cells.ranges 直接迭代会崩:unmerge 的过程中你在改这个集合本身,Python 会报错或跳着处理。必须先 list() 拷一份再遍历。这是这个脚本最隐蔽的一处。rng.min_row/min_col 的值再 unmerge,顺序别反。