python-docx实现保留原格式的批量替换

工作需要,每次项目报告都需要填写许多表单,其中有很多字段仅需要简单替换,因此自己做了个根据提示符替换多个word多个内容的小程序,并保留原格式。 

首先我把模板word中的代替换部分全部改为带有启动子#提示符,如#name,#add,再创建一个字典,其键值对分别为提示符替换内容

dic = {'#co_name': '名称', '#co_add': '地址'}

 现在提供三种替换方法:

方法1:段落替换

doc = docx.Document('test.docx')
for para in doc.paragraphs:
    for key,value in dic.items():
        if key in para:
            para.text=para.text.replace(key,value)

这么做的优点是方便快捷,如果你不在乎替换掉的格式,替换内容的样式默认为段落样式,你可以在模板word中设置段落的样式进行统一控制。

若段落样式和替换内容的样式不同,该方法就无法实现。例:这是要替换的内容#name。替换后的#name并不会保持红色加粗,而是和段落样式保持一致。

方法2:runs替换(简易)

在paragraphs之下,还可以分为runs,runs即为连续的字块。

doc = docx.Document('test.docx')
for para in doc.paragraphs:
    for run in para.runs:
        if run.text in list(dic.keys())
            run.text=run.text.replace(run.text,dic[run.text])

这样即可实现替换内容保持原样式,但这么做存在弊端,即提示符可能会被拆分为多个run。如果只做简单替换,提示符为name,采用上述方法即可。若替换内容众多,且提示符需要在word中一目了然,如上述采用了#co_name,那么该提示符会被分成4个runs,如#,co,_,name。此时就需要采用方法3。

方法3:runs替换(复杂)

for para in doc.paragraphs:
    runs = para.runs
    for i, run in enumerate(runs):
        if run.text == '#':
            count = i  # 记录启动子位置
            tmp = '#'  # tmp写入启动子
            while tmp not in list(dic.keys()):  # tmp继续写入启动子后的run,直到tmp和dic中的键匹配
                count += 1
                tmp += runs[count].text
                runs[count].clear()
            runs[i].text = runs[i].text.replace(runs[i].text, dic[tmp])

方法3实现了复杂提示符的替换功能,并保留原样式,实现逻辑如下:

  1. 启动子#会被单独识别为一个run,故遍历到启动子#时,替换过程开启;
  2. count记录该提示符#是第几个run;
  3. 不断向tmp中添加runs,直到tmp等于dic中的某个键名(while循环)
  4. 向tmp添加run的同时,不断删除原本的run,即runs[count].clear()。可以理解为把启动子#后的run剪切到tmp中了;
  5. while循环结束后开始替换,还记的count是记录提示符#的位置吗,直接将提示符#替换为替换内容,替换终止。

以上,我们便完成了三种方法的word文档内容替换,可以做如下总结:

  1. 如果不关心替换内容样式,用方法1
  2. 如果要求替换内容保留原样式,但提示符可以被识别为一个run,用方法2
  3. 如果要求替换内容保留原样式,但提示符不能被识别为一个run,用方法3

注:提示符之间不能有包含关系,如#co_name和#co_name_en,这样会导致后者无法被识别,这在word中手工替换也是同样的道理。 


 此外,如果你还想替换word中的表格、页眉、页脚内容,只需要在上面多加几个循环:

1、表格内容替换

for table in doc.tables:
    for row in table.rows:
        for cell in row.cells
            for para in cell.paragraphs:
'''
后续内容同上述三个方法
'''

2、页眉页脚内容替换

for sec in doc.sections:
    for para in sec.header.paragraphs:
'''
后续内容同上述三个方法,如果想替换页脚,把header改为footer
'''

  • 11
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值