python 基于 docx 文件模板生成 docx 或 PDF 文件

需求背景

提供一个Word 文档模板,使用python程序替换里边的占位符,替换内容包括文本和图片,然后输出docx 或者PDF文件。

功能演示

输入示例

输出示例

实现程序

python 复制代码
import os
import shutil
import subprocess
import time

from docx import Document
from docx.shared import Pt


class DocFiller:
    def __init__(self, doc_file_path, libreoffice_path=None):
        self.doc = Document(doc_file_path)
        self.libreoffice_path = libreoffice_path

    def _process_paragraphs(self, paragraphs, placeholders):
        # 遍历处理每个段落
        for paragraph in paragraphs:
            # 遍历处理每个段落中的每个run
            for run in paragraph.runs:
                self._process_run(run, placeholders)

    @staticmethod
    def _process_run(run, placeholders):
        for placeholder, replacement in placeholders.items():
            # 文本替换
            if isinstance(replacement, str):
                run.text = run.text.replace(placeholder, replacement)
            # 图片替换
            elif isinstance(replacement, tuple) and len(replacement) == 3:
                image_path, width, height = replacement
                if placeholder in run.text:
                    # 保留占位符前后文本,只替换占位符部分
                    texts = run.text.split(placeholder, 1)
                    run.clear()
                    run.add_text(texts[0])
                    run.add_picture(image_path, width=Pt(width), height=Pt(height))
                    run.add_text(texts[1])

    def _process_tables(self, doc_tables, placeholders):
        for table in doc_tables:
            for row in table.rows:
                for cell in row.cells:
                    self._process_paragraphs(cell.paragraphs, placeholders)

    def fill(self, placeholders):
        self._process_paragraphs(self.doc.paragraphs, placeholders)
        self._process_tables(self.doc.tables, placeholders)

    def convert_to_pdf(self, docx_path, pdf_path):
        output_dir = os.path.dirname(pdf_path)
        temp_pdf_path = os.path.join(output_dir, os.path.basename(docx_path).rsplit('.', 1)[0] + '.pdf')

        try:
            subprocess.run([
                self.libreoffice_path, '--headless', '--convert-to', 'pdf:writer_pdf_Export',
                '--outdir', output_dir, docx_path], check=True)
            shutil.move(temp_pdf_path, pdf_path)
            print(f"conversion successful: {pdf_path}")
        except subprocess.CalledProcessError as e:
            print(f"convert the document error: {e}")

    def to_docx(self, outputfile):
        self.doc.save(path_or_stream=outputfile)
        print('to docx complete')

    def to_pdf(self, outputfile):
        temp_file = f'{int(time.time() * 1e6)}.docx'
        self.to_docx(temp_file)
        try:
            self.convert_to_pdf(temp_file, outputfile)
        finally:
            os.remove(temp_file)

        print('to pdf complete')


if __name__ == '__main__':
    liberoffice = 'D:/LibreOffice/program/soffice.exe'
    d = DocFiller('template.docx', liberoffice)
    data = {
        '{{meeting_time}}': '2024年12月12日 下午3点半',
        '{{meeting_address}}': '中央会议室',
        '{{host}}': '小白',
        '{{photo}}': ('./0.png', 80, 80),
        '{{image1}}': ('./1.jpg', 8, 8),
        '{{image2}}': ('./2.jpg', 300, 200)
    }
    d.fill(data)
    # 生成docx文件
    # d.to_docx('data/output.docx')
    # 生成pdf文件
    d.to_pdf('data/output.pdf')

说明

  1. 本程序依赖python-docx 库和liberoffice ,可以实现docx文件模板内容替换。
  2. 如果替换后只需生成Word 文档,则无需安装liberoffice ,也不用指定liberoffice可执行文件路径。
  3. 如果需要生成PDF 文件,则需要安装liberoffice ,并将程序中的liberoffice可执行文件路径修改为自己的路径。
相关推荐
木头左7 分钟前
跨周期共振效应在ETF网格参数适配中的应用技巧
开发语言·python·算法
爱蹦跶的精灵9 分钟前
降级版本Pillow解决freetypefont has no attribute getsize问题
python·pillow
一人の梅雨41 分钟前
亚马逊 MWS 关键字 API 实战:关键字搜索商品列表接口深度解析与优化方案
python·spring
唐叔在学习2 小时前
pip安装太慢?一键切换国内镜像源,速度飞起!
后端·python
Gz、3 小时前
Spring Boot 常用注解详解
spring boot·后端·python
起风了___3 小时前
Python 自动化下载夸克网盘分享文件:基于 Playwright 的完整实现(含登录态持久化与提取码处理)
后端·python
我是华为OD~HR~栗栗呀3 小时前
测试转C++开发面经(华为OD)
java·c++·后端·python·华为od·华为·面试
mldong4 小时前
保姆级教程!手把手教你搭建FastAPI + Vue3前后端分离项目
vue.js·python·全栈
Q_Q5110082854 小时前
python+uniapp基于微信小程序美食点餐系统
spring boot·python·微信小程序·django·flask·uni-app·node.js
小关会打代码4 小时前
关于Pycharm中在运行出现语法错误:Non-UTF-8 code starting with
ide·python·pycharm