学点python,自动化生成word报告

  


自动化处理Excel文件Pandas可是当之无愧的利器,那么有没有能自动化处理Word的神器呢?答案是有,本文将介绍如何使用python-docx库来处理Word文档,但是个人感觉它不能算上处理Word的神器,反而是一种不得已的选择,这可能也跟Word文档的数据结构化程度比Excel要复杂得多的缘故。


如果完全使用python-docx来生成完整的Word文档,要实现一些复杂样式会相当复杂,今天我就通过一个具体的示例来讲解一种折中的方案,那就是通过事先编写好的模板文件,仅通过更新模板文件中的定义好的占位符来生成Word文档。这样的方式可以最大限度地利用模板文件的样式,只需要学习几个python-docx简单的API就可以做到自动化生成漂亮报告,对于需要经常处理Word文档的工作者而言,可以让你从繁琐的键盘敲击中解放出来。使用python-docx前需要先进行安装。

pip install python-docx


为了方便演示,创建一个如下图所示的简单模板示例,我们的目标是编写python程序自动替换模板中的由{}包裹的内容,并生成样式和模板一致的Word报告。标题中的{report_date}将替换为报告的日期;正文段落的{num_xxx}表示将替换为数字,并设置为标红加粗的样式;{image_demo}表示这里将插入图片;最后表格部分仅保留表头,示例将第一列表头的内容作为识别要更新表格的标识,这里为NO.。


以上只是本次约定的规则,实际应用中你可以创建专业的模板并自行定义占位符的规则。


接着简单介绍python-docx的基本概念,让我们对它有个基本的理解,后面就直接通过具体的示例代码展示如何使用它们,这里完全不会用到其复杂的内容。

1. Document对象,对应的就是Word文档,打开或新建文档都使用Document方法。

2. 我们知道Word文档是由标题、段落、节、表格等元素组成,python-docx也都有对应的概念,它们是可迭代对象,在程序中可以遍历文档对象的段落、表格进行相应的处理操作。

3. Run对象,比如示例模板中的数字可以单独标红加粗,设置不同的样式,它们就是一个Run对象,简单理解,就是一个段落中的小分块,每个分块可以单独设置样式。

4. save方法将更新的Document保存为Word文档。


下面就直接给出代码,大部分代码都进行了注释,示例代码将模板文件命名为template.docx,另外还需要事先准备一个名为demo.png的图片放到和代码同一目录下。

import re
import time
from docx import Document
from docx.shared import Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
def format_number_red_bold(paragraph):
    """
    将段落中的数字标红加粗
    整体的思路是把段落重新拆分为文本和数字,然后重新创建新的Run对象,针对数字的样式进行修改
    """
    # 正则表达式匹配数字
    pattern = re.compile(r'\d+')
    # 记录拆分的段落文本和数字Run对象
    new_runs = []
    # 当前处理的文本起始位置
    start = 0


    # 找到所有数字的位置
    for match in pattern.finditer(paragraph.text):
        number_start, number_end = match.span()
        # 如果数字前面有文本,添加一个新的Run对象保存数字前的文本
        if number_start > start:
            text = paragraph.text[start:number_start]
            new_runs.append((text, "text"))
        # 创建包含数字的Run对象,并设置样式
        text = paragraph.text[number_start:number_end]
        new_runs.append((text, "digit"))
        # 更新当前处理的文本起始位置
        start = number_end
    # 段落末尾的文本
    new_runs.append((paragraph.text[start:], "text"))
    # 清空段落
    paragraph.text = ""
    # 重新组装段落并将数字的样式改为标红加粗
    for text, style in new_runs:
        run = paragraph.add_run(text)
        if style == "digit":
            run.font.color.rgb = RGBColor(255, 0, 0)  # 红色
            run.font.bold = True  # 加粗
def generate_report_from_template(template_path, output_path, report_data):
    """
    根据提供的数据更新Word模板并生成报告文件
    :param template_path: 模板文件
    :param output_path: 输出报告文件
    :param report_data: 包含要更新的数据字典,
    """
    # 打开模板文档
    doc = Document(template_path)
    # 遍历模板文档中的段落
    for para in doc.paragraphs:
        # 遍历检查段落中是否有需要替换的占位符
        for placeholder, new_text in report_data.items():
            # 排除图片占位符
            if not placeholder.startswith('image_'):
                # 如果当前段落文本包含占位符,则替换为占位符对应的文本
                if f'{{{placeholder}}}' in para.text:
                    para.text = para.text.replace(f'{{{placeholder}}}', new_text)


    # 段落被占位符替换后样式会丢失,遍历段落设置数字的样式为标红加粗
    for para in doc.paragraphs:
        # 判断是否是需要对数字标红加粗的段落
        if para.text.startswith("这是一段包含数字的段落示例"):
            # 重新将需要标红加粗的数字进行样式修改
            format_number_red_bold(para)


    # 更新报告表格数据
    for table in doc.tables:
        # 获取表格第一行第一列标题,作为判定表格的依据
        th0 = table.rows[0].cells[0].text
        # 遍历报告数据中的数据
        for thead, tdata in report_data.items():
            # 如果第一列标题和报告数据中的key相同,则表明该表格需要更新
            if th0 == thead:
                # 记录新增表格的行
                new_added_rows = []
                for _ in tdata:
                    new_added_rows.append(table.add_row())
                # 遍历新增的行
                for index, new_row in enumerate(new_added_rows):
                    # 遍历每一行的单元格
                    for cell_idx, cell in enumerate(new_row.cells):
                        # 取表格对应的数据项设置为单元格的文本
                        cell.text = tdata[index][cell_idx]
                        # 设置单元格样式为居中
                        for p in cell.paragraphs:
                            p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
    # 更新报告图片
    for para in doc.paragraphs:
        # 遍历数据字典
        for placeholder, image_path in report_data.items():
            # 判断是否是图片占位符
            if placeholder.startswith("image_"):
                if f'{{{placeholder}}}' in para.text:
                    # 占位符所在的段落清除并添加图片
                    para.clear()
                    run = para.add_run()
                    # Inches(5)用于调整图片的大小比例
                    run.add_picture(image_path, width=Inches(5))
                    # 设置图片居中
                    para.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER  


    # 保存更新后的文档
    doc.save(output_path)
if __name__ == "__main__":
    # 模板文件路径
    template_path = "./template.docx"
    # 指定生成word报告路径
    output_path = "report.docx"
    # 模拟报告数据
    report_data = {
        "report_date": time.strftime("%Y/%m/%d"),
        "num_001": f"{123}",
        "num_002": f"{456}",
        "num_003": f"{789}",
        "image_demo": "demo.png",
        "NO.": [
            ("001", "key01", "val01"),
            ("002", "key02", "val02"),
            ("003", "key03", "val03"),
        ]
    }
    # 根据模板生成word报告
    generate_report_from_template(template_path, output_path, report_data)

运行代码将会在相同目录下生成名为report.docx的Word文档,打开内容将如下图所示。


参考文献:

[1].https://python-docx.readthedocs.io/en/latest/index.html#api-documentation

相关文章

Python 操作 Word

用 docx 模块读取 Worddocx 安装cmd 中输入pip install python-docx 即可安装 docx 模块docx 常用函数创建空白文档from docx import Do...

Python+Word办公自动化:10分钟掌握高效文档处理,告别996加班!

引言在职场中,Word文档处理是高频却耗时的任务——批量生成报告、重复填写表格、手动调整格式……而Python的python-docx库,能让你用代码轻松实现文档自动化,效率提升10倍!本文将手把手教...

提升效率100倍,Python+Word实现周报自动化的完整流程

在现代企业环境中,周报、月报等定期报告的编写往往占用了大量专业人员的宝贵时间。这些报告通常需要从各种数据源中提取数据,进行分析整理,再按照统一的格式生成文档。如果能够将这一过程自动化,不仅可以大幅提高...

Python操作Word文档神器:python-docx库从入门到精通

Python操作Word文档神器:python-docx库从入门到精通 动动小手,点击关注,感谢您的阅读,您的关注是我最大的动力!!!!在办公自动化场景中,处理 Word 文档是常见需求。python...