使用 Python 根据自定义的 Word 模板和传入的 JSON 数据生成 Word 报告,是自动化文档生成的常见需求。最常用的方法是使用 python-docxdocxtpl 库。其中,docxtpl 是基于 python-docx 的模板引擎,支持 Jinja2 模板语法,非常适合根据模板和数据生成报告。

1. 新建项目、引入依赖

pip install docxtpl

2. 创建word模板

在这里插入图片描述

3. 程序导出word文档

from datetime import datetimefrom docxtpl import DocxTemplate
import jsondef generate_report(template_path, json_data, output_path):# 加载模板doc = DocxTemplate(template_path)# 加载 JSON 数据context = json.loads(json_data) if isinstance(json_data, str) else json_data# 渲染模板doc.render(context)# 保存为新文件doc.save(output_path)print(f"报告已生成:{output_path}")# 使用示例
if __name__ == "__main__":template_file = "./template/test-tempalte01.docx"output_file = "./output/test-output01.docx"# 模拟 JSON 数据data = {"report_title": "测试报告","report_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),"server_infos": [{"server_name": "server01", "ip": "192.168.10.5", "port": 80},{"server_name": "server02", "ip": "192.168.10.6", "port": 80},{"server_name": "server03", "ip": "192.168.10.7", "port": 80}]}generate_report(template_file, data, output_file)

在这里插入图片描述

4. 程序导出PDF

  1. 安装依赖

    pip install docx2pdf
    
  2. 修改程序

    from datetime import datetimefrom docxtpl import DocxTemplate
    from docx2pdf import convert
    import jsondef generate_report(template_path, json_data, output_path, export_pdf=False):# 加载模板doc = DocxTemplate(template_path)# 加载 JSON 数据context = json.loads(json_data) if isinstance(json_data, str) else json_data# 渲染模板doc.render(context)# 保存为Word文件doc.save(output_path)print(f"Word报告已生成:{output_path}")# 如果需要导出PDFif export_pdf:pdf_path = output_path.replace('.docx', '.pdf')convert(output_path, pdf_path)print(f"PDF报告已生成:{pdf_path}")return pdf_pathreturn output_path# 使用示例
    if __name__ == "__main__":template_file = "./template/test-tempalte01.docx"output_file = "./output/test-output01.docx"# 模拟 JSON 数据data = {"report_title": "测试报告","report_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),"server_infos": [{"server_name": "server01", "ip": "192.168.10.5", "port": 80},{"server_name": "server02", "ip": "192.168.10.6", "port": 80},{"server_name": "server03", "ip": "192.168.10.7", "port": 80}]}generate_report(template_file, data, output_file, export_pdf=True)

    此时会同时导出word和pdf文件

    注意:使用docx2pdf会依赖Microsoft Office,所以在Windows环境下可以转换成pdf文件,但是在Linux环境会有问题。需要修改为LibreOffice方案。详见下面步骤。

5. 将程序导出为工具使用(windows)

  1. 安装LibreOffice

    下载地址:https://www.libreoffice.org/download/download-libreoffice/

    安装完成后,将安装目录的program目录添加到Path环境变量。

    # 验证
    soffice --version
    
  2. 修改程序

    from datetime import datetime
    from docxtpl import DocxTemplate
    import json
    import argparse
    import sys
    import os
    import subprocessdef generate_report(template_path, json_data, output_path, export_pdf=False):# 转换路径为绝对路径并规范化template_path = os.path.abspath(template_path)output_path = os.path.abspath(output_path)print(f"执行中, 正在检查模板文件路径: {template_path}")if not os.path.exists(template_path):raise FileNotFoundError(f"执行异常, 模板文件不存在!请检查路径是否正确。\n路径: {template_path}")if not os.path.isfile(template_path):raise FileNotFoundError(f"执行异常, 路径存在,但不是一个文件(可能是目录)。\n路径: {template_path}")file_size = os.path.getsize(template_path)if file_size == 0:raise ValueError(f"执行异常, 模板文件大小为 0,可能是空文件。\n路径: {template_path}")print(f"执行中, 模板文件存在,大小: {file_size} 字节")# === 确保输出目录存在 ===output_dir = os.path.dirname(output_path)  # 根据输出文件的路径获取父目录(导出文件的目录)if output_dir and not os.path.exists(output_dir):print(f"执行中, 输出目录不存在,正在创建: {output_dir}")os.makedirs(output_dir, exist_ok=True)  # 递归创建目录# =============================# 加载模板try:doc = DocxTemplate(template_path)except Exception as e:raise RuntimeError(f"加载模板失败: {e}")# 解析 JSON 数据try:context = json.loads(json_data) if isinstance(json_data, str) else json_data# 添加当前时间(如果模板中使用了 report_time 但未提供)if 'report_time' not in context:context['report_time'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")except json.JSONDecodeError as e:raise ValueError(f"执行异常, JSON 数据解析失败: {e}")# 渲染模板try:doc.render(context)except Exception as e:raise RuntimeError(f"执行异常, 模板渲染失败,请检查上下文变量: {e}")# 保存 Word 文件doc.save(output_path)print(f"执行中, Word报告已生成:{output_path}")# 导出 PDFif export_pdf:try:pdf_path = output_path.replace('.docx', '.pdf')# convert(output_path, pdf_path)convert_to_pdf_with_libreoffice(output_path, pdf_path)print(f"执行中, PDF报告已生成:{pdf_path}")return pdf_pathexcept Exception as e:raise RuntimeError(f"执行异常, 转换PDF失败: {e}")return output_pathdef convert_to_pdf_with_libreoffice(input_docx, output_pdf):"""使用 LibreOffice 将 .docx 转为 .pdf"""# 确保目录存在pdf_dir = os.path.dirname(output_pdf)if pdf_dir and not os.path.exists(pdf_dir):os.makedirs(pdf_dir, exist_ok=True)# 调用 LibreOffice 命令try:subprocess.run(['soffice','--headless','--convert-to', 'pdf','--outdir', pdf_dir,input_docx], check=True, capture_output=True)# LibreOffice 会生成在指定目录,文件名相同,扩展名为 .pdfgenerated_pdf = os.path.join(pdf_dir, os.path.basename(input_docx).rsplit('.', 1)[0] + '.pdf')# 移动或重命名为目标路径(避免同名冲突)if generated_pdf != output_pdf:os.replace(generated_pdf, output_pdf)print(f"执行中, PDF转换成功: {output_pdf}")except subprocess.CalledProcessError as e:raise RuntimeError(f"执行异常, LibreOffice 转换失败: {e.stderr.decode()}")except Exception as e:raise RuntimeError(f"执行异常, 调用 LibreOffice 时出错: {e}")def main():parser = argparse.ArgumentParser(description="从模板和JSON数据生成Word/PDF报告")parser.add_argument('--template', '-t',required=True,help='Word模板文件路径 (.docx)')parser.add_argument('--output', '-o',required=True,help='输出文件路径,例如: ./output/report.docx')parser.add_argument('--data', '-d',required=True,help='JSON格式的数据字符串,或以@开头的文件路径,如: @data.json')parser.add_argument('--pdf',action='store_true',help='是否同时导出PDF文件')args = parser.parse_args()# 支持从文件读取 JSON 数据(以 @ 开头)if args.data.startswith('@'):data_file = args.data[1:]try:with open(data_file, 'r', encoding='utf-8') as f:json_data = f.read()except FileNotFoundError:print(f"执行异常, 数据文件未找到: {data_file}", file=sys.stderr)sys.exit(1)except Exception as e:print(f"执行异常, 读取数据文件失败: {e}", file=sys.stderr)sys.exit(1)else:json_data = args.data# 调用生成函数try:result_path = generate_report(template_path=args.template,json_data=json_data,output_path=args.output,export_pdf=args.pdf)print(f"执行完成: {result_path}")except Exception as e:print(f"执行异常, 生成报告失败: {e}", file=sys.stderr)sys.exit(1)if __name__ == "__main__":main()
    
  3. 导出为可执行程序

    # 安装依赖
    python -m pip install pyinstaller# 导出,此时会生成一个dist目录,可执行文件在此目录中
    pyinstaller main.py --onefile --console --clean# 重命名(可选)
    ren main.exe xxx.exe
    
  4. 组装数据(data.json)

    {"report_title": "测试报告","server_infos": [{"server_name": "server01", "ip": "192.168.10.5", "port": 80},{"server_name": "server02", "ip": "192.168.10.6", "port": 80},{"server_name": "server03", "ip": "192.168.10.7", "port": 80}]
    }
    
  5. 运行exe文件

    # windows 数据使用文件的方式
    main.exe --template "D:/universal_export/universal_export/template/test-template01.docx" --output "D:/universal_export/universal_export/output/test-template01.docx" --data @D:/universal_export/universal_export/data.json --pdf# windows 数据使用字符串的方式
    main.exe --template "D:/universal_export/universal_export/template/test-template01.docx" --output "D:/universal_export/universal_export/output/test-template01.docx" --data "{\"report_title\":\"测试报告\",\"server_infos\":[{\"server_name\":\"server01\",\"ip\":\"192.168.10.5\",\"port\":80},{\"server_name\":\"server02\",\"ip\":\"192.168.10.6\",\"port\":80},{\"server_name\":\"server03\",\"ip\":\"192.168.10.7\",\"port\":80}]}" --pdf
    

6. 将程序导出为工具使用(Centos)

  1. Centos安装python环境

    # 安装依赖
    yum -y groupinstall "Development tools"
    yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
    yum install -y libffi-devel zlib1g-dev
    yum install zlib* -y# 下载源码包
    cd /opt
    sudo wget https://www.python.org/ftp/python/3.12.6/Python-3.12.6.tgz
    sudo tar -xzf Python-3.12.6.tgz# 创建编译安装目录
    mkdir /usr/local/python3 # 检查openssl版本
    openssl version
    # 对于python 3.12,openssl版本不能低于1.1.1
    # 添加 EPEL 仓库
    yum install -y epel-release
    # 安装较新的 OpenSSL
    yum install -y openssl11 openssl11-devel# 安装
    export CPPFLAGS="-I/usr/include/openssl11"
    export LDFLAGS="-L/usr/lib64/openssl11"
    cd Python-3.12.6
    ./configure --prefix=/usr/local/python3 --with-openssl=/usr --with-openssl-include=/usr/include/openssl11 --with-openssl-lib=/usr/lib64/openssl11 --enable-shared
    make -j$(nproc)
    sudo make install# 配置库路径
    echo '/usr/local/python3/lib' | sudo tee /etc/ld.so.conf.d/python3.conf
    sudo ldconfig# 创建软链接
    ln -s /usr/local/python3/bin/python3 /usr/local/bin/python3
    ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip3# 验证
    python3 -V
    pip3 -V
    python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"# 修改pip源
    cd ~
    mkdir .pip
    cd .pip
    vim pip.conf#进入后添加以下内容,保存退出.
    [global]
    index-url = https://pypi.tuna.tsinghua.edu.cn/simple
    
  2. Centos安装libreoffice

    # 在线安装
    yum install epel-release -y
    yum install libreoffice-headless -y# 验证
    soffice --version
    
  3. 将程序上传至Linux服务器后编译

    # 安装 PyInstaller
    pip3 install pyinstaller# 安装程序所需要的依赖
    pip3 install docxtpl# 打包,命名为universal_export
    python3 -m PyInstaller --onefile --clean --name=universal_export main.py
    
  4. 执行导出命令

    ./universal_export -t template/test-template01.docx -o out/test.docx -d @data.json --pdf
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97391.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97391.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97391.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode算法日记 - Day 24: 颜色分类、排序数组

目录 1. 颜色分类 1.1 题目分析 1.2 解法 1.3 代码实现 2. 排序数组 2.1 题目解析 2.2 解法 2.3 代码实现 1. 颜色分类 75. 颜色分类 - 力扣(LeetCode) 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序…

学习一下动调

[NSSCTF 2nd]MyBasedie查一下用ida64打开main函数里面没有什么信息,接着追一下函数,内容在test函数里面函数会对我们输入的内容进行base64加密,这段逻辑也很简单,就是将加密后的字符串和目标字符串依次进行比较,一样就…

Java试题-选择题(22)

Java试题-选择题(22) 题目以下对JDBC事务描述错误的是 ? A) JDBC事务属于JAVA事务的一种 B) JDBC事务属于容器事务类型 C) JDBC事务可以保证操作的完整性和一致性 D) JDBC事务是由Connection发起的,并由Connection控制要通过可滚动…

蓝牙5.3核心技术架构解析:从控制器到主机的无线通信设计

蓝牙5.3核心技术架构解析:从控制器到主机的无线通信设计在无线通信领域,蓝牙技术如何通过精巧的架构设计实现设备间的高效互操作?答案在于其分层架构与标准化的接口定义。蓝牙5.3核心规范作为现代无线通信的重要标准,其系统架构设…

android View#performClick() 和 View#callOnClick() 的差异

文章目录performClick()callOnClick()关键区别对比总结在 Android 中,View.performClick() 和 View.callOnClick() 都是用于触发视图点击事件的方法,但它们的设计目的和执行逻辑存在细微差异,具体区别如下:performClick() 核心作…

PHP单独使用phinx使用数据库迁移

可以独立使用的迁移包对比后,感觉phinx更接近PHP的使用习惯。 为什么要单独用? 因为我不想数据库的迁移文件依赖于某种框架。本来是可以在框架里直接安装这个包的,但是发现这个包依赖cakephp,而cakephp的函数与thinkphp的env()函…

从零开始学习单片机18

使用STM32CubeMX创建工程选择对应芯片后创建工程,首先设置时钟源内部时钟源包括LSI(低速时钟)和HSI(高速时钟),使用内部时钟源就需要将图中的一二处勾选HCLK是芯片运行时的评率,虽然下面标的最大…

如何使用 DeepSeek 帮助自己的工作?

技术文章大纲:利用 DeepSeek 提升工作效率 了解 DeepSeek 的基本功能 DeepSeek 的核心能力:文本生成、代码辅助、数据分析支持的平台与访问方式(网页端/API/集成工具)适用场景:技术文档撰写、自动化流程设计、数据处理…

计算机毕设javayit商城 基于SSM框架的校园二手交易全流程管理系统设计与实现 Java+MySQL的校园二手商品交易与供需对接平台开发

计算机毕设 javayit 商城uwd1i9 (配套有源码 程序 mysql数据库 论文)本套源码可以先看具体功能演示视频领取,文末有联xi 可分享随着校园二手物品流通需求增长,传统校园二手交易依赖线下摆摊、社群发布的模式,存在信息分…

Java函数式编程之【流(Stream)性能优化】

Java函数式编程之【流(Stream)性能优化一、流(Stream)性能优化的预备知识(一)并行与并发的区别(二)Stream操作特性分类(三)Stream流管道的相关知识二、流&…

Cybero: 1靶场渗透

Cybero: 1 来自 <Cybero: 1 ~ VulnHub> 1&#xff0c;将两台虚拟机网络连接都改为NAT模式 2&#xff0c;攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.128&#xff0c;靶场IP192.168.23.139 3&#xff0c;对靶机进行端口服务探…

【学习笔记】非异步安全函数(禁止在信号处理中调用)

非异步安全函数&#xff08;禁止在信号处理中调用&#xff09; 一、测试 在信号处理函数&#xff08;Signal Handler&#xff09;中&#xff0c;只有异步信号安全函数&#xff08;async-signal-safe functions&#xff09; 可以安全调用。这类函数的特点是&#xff1a;不使用全…

【K8s】整体认识K8s之K8s的控制器

作用&#xff1a;控制器的作用就是持续监控k8s集群的状态&#xff0c;让它处于我们期望的状态&#xff0c;常见的控制器有replicaset、deployment、daemonset、statefulset 、job 、cronjobReplicaset控制一组pod的副本数&#xff0c;始终与预设的值相同&#xff0c;会持续监视…

R ggplot2学习Nature子刊一张图,换数据即可用!

本次使用R语言复现Nature Communications上的1张组合图,这张图兼具颜值+节约版面! Fig. 1 b原图 ❤️复现效果图-b图❤️ ✅读入测试数据! ✅关键代码, # 关键代码 library(ggplot2) library(dplyr) library(cowplot)# --- 外圈图 --- p_outer <- ggplot(data_aug, aes…

迷你电脑用到什么型号的RJ45网口

迷你电脑常用的 RJ45 网口主要有标准 RJ45 网口和 Mini RJ45 网口两种。标准 RJ45 网口是最常见的类型&#xff0c;遵循 IEEE 802.3i 标准&#xff0c;采用 8P8C&#xff08;8 Position 8 Contact&#xff0c;8 位 8 触点&#xff09;连接器&#xff0c;有 T568A 和 T568B 两种…

网络安全 | 保护智能家居和企业IoT设备的安全策略

网络安全 | 保护智能家居和企业IoT设备的安全策略 一、前言 二、智能家居和企业 IoT 设备面临的安全威胁 2.1 设备自身安全缺陷 2.2 网络通信安全隐患 2.3 数据隐私风险 2.4 恶意软件和攻击手段 三、保护智能家居和企业 IoT 设备的安全策略 3.1 设备安全设计与制造环节的考量 3…

优化器全指南:从原理到调优实战

本文将带你轻松理解深度学习中的“导航系统”——优化器。我们会避开复杂的数学公式,用大量的比喻和图示,让你彻底明白 Adam、AdamW、LAMB 是怎么回事,并学会如何调节它们的关键参数。 第一部分:核心概念:优化器是什么? 一个简单的比喻: 想象你在一座大雾弥漫的山里(…

Notepad++使用技巧1

1.打开官方参考代码经常看到下图这种行尾很多空格的代码&#xff0c;一点都不合符华为的书写规范&#xff0c;阅读起来容易让人烦躁不安。初学者建议看看华为的代码书写规范&#xff0c;你将少走很多弯路&#xff0c;终生受益。2.快速去掉行尾很多空格方法点击顶部菜单栏“宏”…

AIoT云边协同方式

随着物联网&#xff08;IoT&#xff09;与人工智能&#xff08;AI&#xff09;的深度融合&#xff0c;AIoT&#xff08;人工智能物联网&#xff09;作为一种新兴技术范式&#xff0c;正在推动智能设备与产业的快速发展。AIoT通过云边协同的方式&#xff0c;将边缘侧的IoT设备、…

MIT 6.5840 (Spring, 2024) 通关指南——Lab 1: MapReduce

MIT 6.5840 (Spring, 2024) – Lab 1: MapReduce &#x1f468;‍&#x1f4bb; Charles &#x1f517; 实验手册&#xff1a; 6.5840 Lab 1: MapReduce &#x1f4c3; MapReduce 论文原文&#xff1a; mapreduce-osdi04.pdf ✍️ 本系列前文&#xff1a; MIT 6.5840 (Spring, …