三、python-docx中paragraph替换内容和模板处理

        实际工作中,通常只有批量处理文档或者需要频繁处理固定格式文档的时候,使用工具的价值比较大。

        使用python-docx处理Word文档的时候,可以创建一个全新的文档,或者修改一个文档。

        如果批量处理或频繁处理的都是固定格式的文档,通常使用文档模板会更简单方便。毕竟工作追求的是效率,而不是技术研究。

        使用文档模板处理工作的思路:

        1、创建一个Word文档,在里面编辑好格式和内容

        2、把里面需要动态填充的内容用占位符替换

        3、组织数据内容到Excel / 数据库 / 文本 或其他地方,作为数据源

        4、编写python程序

                4.1、读取数据源

                4.2、使用python-docx读取Word文档模板

                4.3、替换Word模板文档中的占位符为数据源中的实际内容

                4.4、保存新的Word文档

        下面通过一个示例场景演示如何实现上面的思路,场景为批量生成邀请函。

1、创建Word文档模板

        文档模板示例如下图:

        其中需要动态替换的内容为 #attendee#(参会人),#meetingdate#(会议日期),#meetingplace#(会议地点),#meetingsubject#(会议主题)  。  #attendee# 就是用来占位的,后续会被实际的内容替换掉。

        为了体现演示效果,#meetingdate# 设置为加粗,#meetingsubject# 设置为红色,看替换后生成的文档是不是和我们的预期相符。

2、读取并替换为实际内容(替换paragraph.text里的占位符)

from docx import Document

# 准备演示数据,实际应用时数据可以从Excel中读取,或从数据库读取,或从其他地方获得
dic_values = [
     {'#attendee#':'张三', '#meetingdate#':'2023年11月1日', '#meetingplace#':'西安', '#meetingsubject#':'没有主题'}
    ,{'#attendee#':'李四', '#meetingdate#':'2023年11月1日', '#meetingplace#':'西安', '#meetingsubject#':'没有主题'}
    ,{'#attendee#':'王五', '#meetingdate#':'2023年11月1日', '#meetingplace#':'西安', '#meetingsubject#':'没有主题'}
    ]

# 一份数据生成一个文档
for val in dic_values:
    document = Document('./doc_template1.docx')

    for paragraph in document.paragraphs:
        print(paragraph.text)   # 替换前的段落内容
        for key, value in val.items():
            if paragraph.text.find(key) > 0:
                paragraph.text = paragraph.text.replace(key, value)
                print(paragraph.text)   # 替换后的段落内容

    document.save(f'doc_template_{val["#attendee#"]}.docx')

上面代码运行后的输出结果 

上面的运行结果可以看到,文档是生成了, 但内容格式和我们预期的不一致,显然这不是我们想要的。

3、读取并替换为实际内容(替换run.text里的占位符)

from docx import Document

# 准备演示数据,实际应用时数据可以从Excel中读取,或从数据库读取,或从其他地方获得
dic_values = [
     {'attendee':'张三', 'meetingdate':'2023年11月1日', 'meetingplace':'西安', 'meetingsubject':'没有主题'}
    ,{'attendee':'李四', 'meetingdate':'2023年11月1日', 'meetingplace':'西安', 'meetingsubject':'没有主题'}
    ,{'attendee':'王五', 'meetingdate':'2023年11月1日', 'meetingplace':'西安', 'meetingsubject':'没有主题'}
    ]

# 一份数据生成一个文档
for val in dic_values:
    document = Document('./doc_template1.docx')

    # 替换run里的text
    for paragraph in document.paragraphs:
        for run in paragraph.runs:
            print(run.text)
            for key, value in val.items():
                if run.text.find(key) > -1:
                    run.text = run.text.replace(key, value)
                    print(run.text)   # 替换后的内容

    document.save(f'doc_template_{val["attendee"]}.docx')

通过上面的示例可以看到,替换run.text是不会丢失样式的,和我们的预期结果一致。

        不过大家会发现这次使用的占位符没有特殊符号【#】,而是用的一个完整的词语,这是因为runs会根据一些特殊字符把文本内容分割成许多不同的块,如下所示:#attendee# 被分割成了3个run,这样就无法用Replace函数了,因为每一个单独的run匹配不到定义的“键”。

    for paragraph in document.paragraphs:
        for run in paragraph.runs:
            print(run.text)

        有人可能会说,那就把“占位符的每个键”定义成一个单独的词语不就可以了,不用加特殊字符了。这样也是可以的,不过这就要求每个键都不能与文档内容里的词语重复,否则就会出现把不应该被替换的内容给替换掉。

        实际使用场景中,占位符的键不与文档内容里的词语重复,有时候很难避免,所以尽量用特殊符号把占位表装饰一下,既避免出现重合的情况,又能明显的看出哪些是占位符,哪些是正常文本内容。

         而且面对runs把文本内容分割了的情况也是有办法处理的。

4、读取并替换为实际内容(替换run.text里带特殊占位符的内容)

 

from docx import Document

# 准备演示数据,实际应用时数据可以从Excel中读取,或从数据库读取,或从其他地方获得
dic_values = [
     {'#attendee#':'张三', '#meetingdate#':'2023年11月1日', '#meetingplace#':'西安', '#meetingsubject#':'没有主题'}
    ,{'#attendee#':'李四', '#meetingdate#':'2023年11月1日', '#meetingplace#':'西安', '#meetingsubject#':'没有主题'}
    ,{'#attendee#':'王五', '#meetingdate#':'2023年11月1日', '#meetingplace#':'西安', '#meetingsubject#':'没有主题'}
    ]

# 一份数据生成一个文档
for val in dic_values:
    document = Document('./doc_template1.docx')

    for paragraph in document.paragraphs:
            runs = paragraph.runs
            for i, run in enumerate(runs):
                if run.text == '#':
                    counter = i  # 记录起始位置
                    tmp = '#'    # tmp开始存储
                    while tmp not in list(val.keys()):
                        counter += 1
                        tmp += runs[counter].text
                        runs[counter].clear()
                    runs[i].text = runs[i].text.replace(runs[i].text, val[tmp])

    document.save(f'doc_template_{val["#attendee#"]}.docx')

5、总结

  1. 替换paragraph.text里的占位符最简单容易,但是会丢失内容的样式,如果不关心样式,只关心内容,则可以使用该方式;
  2. 替换run.text里的占位符,不会丢失样式,建议使用这种方式,实际开发过程中,可以把对run.text的替换封装成一个方法,然后去调用就可以了;
  3. 不管用哪种方法,占位符的定义,尽量不要直接用词语,最好用特殊符号装饰一下,避免把不应该被替换的内容替换掉;
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 好的,你需要安装python-docx库,可以使用pip install python-docx命令进行安装。下面是示例代码: ```python import docx # 打开模板文件 doc = docx.Document('模板.docx') # 查找文本框 text_boxes = doc.inline_shapes for box in text_boxes: if box.has_text_frame: # 查找文本框的文本 text = box.text_frame.paragraphs[0].text if 'N_1' in text: # 将文本框里的内容替换为filenumber box.text_frame.paragraphs[0].text = text.replace('N_1', 'filenumber') # 保存文件 doc.save('修改后的模板.docx') ``` 你需要将模板.docx文件与程序放在同一目录下,然后将需要替换的文本N_1修改为{{filenumber}},程序会自动查找并替换。 ### 回答2: 要用Python编写一个小程序来实现将模板.docx文档的文本框里的内容从"N_1"替换为"filenumber",可以使用Python的`python-docx`库来操作Word文档。 首先,需要安装`python-docx`库。可以使用以下命令在终端或命令提示符安装: ``` pip install python-docx ``` 接下来,可以编写Python程序来实现需求: ```python from docx import Document def replace_text_in_textbox(doc, textbox_text, replacement): for textbox in doc.inline_shapes: if textbox.has_text_frame: for paragraph in textbox.text_frame.paragraphs: for run in paragraph.runs: if textbox_text in run.text: run.text = run.text.replace(textbox_text, replacement) # 打开模板.docx文件 doc = Document('模板.docx') # 调用replace_text_in_textbox函数将文本框内的内容替换 replace_text_in_textbox(doc, "N_1", "filenumber") # 保存修改后的文档 doc.save('修改后的模板.docx') ``` 以上程序的`replace_text_in_textbox`函数会接受一个`doc`参数表示要操作的文档对象,一个`textbox_text`参数表示要替换的文本框的内容,以及一个`replacement`参数表示替换后的内容。该函数会遍历文档的所有内联形状(包括文本框),找到包含要替换内容的文本框内的段落,并将其的文本进行替换。 可以将以上代码保存为一个Python脚本,运行后会生成一个名为"修改后的模板.docx"的新文档,其的文本框的内容已经完成替换,"N_1"被替换为了"filenumber"。 ### 回答3: 可以使用pythonpython-docx库来实现这个需求。首先,我们需要安装python-docx库。可以使用以下命令安装: ``` pip install python-docx ``` 下面是一个使用python-docx库修改模板文件的示例代码: ```python from docx import Document def replace_text_in_docx(template_file, search_text, replace_text): doc = Document(template_file) for paragraph in doc.paragraphs: if search_text in paragraph.text: inline = paragraph.runs for i in range(len(inline)): if search_text in inline[i].text: text = inline[i].text.replace(search_text, replace_text) inline[i].text = text doc.save("新文件.docx") template_file = "模板.docx" search_text = "N_1" replace_text = "filenumber" replace_text_in_docx(template_file, search_text, replace_text) ``` 在上述代码,我们定义了一个`replace_text_in_docx`函数,该函数接受个参数:模板文件的路径,要替换的文本,以及替换后的文本。函数会打开模板文件,逐个段落遍历,并查找含有要替换的文本的段落。如果找到了匹配的文本,则将文本替换为指定的替换文本。 最后,使用`doc.save`方法保存修改后的文档为"新文件.docx"。你可以根据需要修改保存的文件名。 使用该程序,你可以将模板.docx的所有"N_1"替换为"filenumber"。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jerry_xizn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值