python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python JSON数据生成PDF

使用Python实现将JSON数据生成PDF文档

作者:大丸子

在企业日常运营中,JSON 格式的数据广泛应用于 API 接口、配置文件和数据交换场景,本文将介绍如何使用 Python 从 JSON 数据自动生成格式规范的 PDF 文档,有需要的小伙伴可以了解下

在企业日常运营中,JSON 格式的数据广泛应用于 API 接口、配置文件和数据交换场景。然而,将结构化的 JSON 数据转换为适合阅读和分发的 PDF 报告,往往需要手动复制粘贴或借助复杂的模板工具,不仅效率低下,还容易出现格式错乱、数据遗漏等问题。对于需要定期生成财务报表、项目进度报告、客户信息汇总等场景,自动化生成 PDF 文档成为提升工作效率的关键需求。

本文将介绍如何使用 Python 从 JSON 数据自动生成格式规范的 PDF 文档。整个过程完全自动化,无需人工干预,适用于业务报表生成、数据归档、合同附件制作、API 数据可视化等多个应用场景。通过代码方式,你可以灵活控制文档布局、字体样式、表格结构和页面元素,确保生成的 PDF 既专业又美观。

本文使用的方法需要用到 Free Spire.PDF for Python,可通过 pip 安装:

pip install spire.pdf.free

1. 准备 JSON 数据并创建 PDF 文档

在开始生成 PDF 之前,我们需要先定义示例 JSON 数据,并初始化 PDF 文档对象。这里以一份销售数据报告为例,包含产品信息、销售记录和统计摘要。

import json
from spire.pdf import PdfDocument, PdfPageBase
from spire.pdf.graphics import *
# 示例 JSON 数据
json_data = """
{
    "report_title": "2024年第一季度销售报告",
    "company": "ABC科技有限公司",
    "date": "2024-03-31",
    "summary": {
        "total_sales": 1580000,
        "total_orders": 342,
        "average_order_value": 4619.88
    },
    "products": [
        {"name": "笔记本电脑", "category": "电子产品", "quantity": 120, "unit_price": 5999, "total": 719880},
        {"name": "无线鼠标", "category": "配件", "quantity": 450, "unit_price": 89, "total": 40050},
        {"name": "机械键盘", "category": "配件", "quantity": 280, "unit_price": 399, "total": 111720},
        {"name": "显示器", "category": "电子产品", "quantity": 95, "unit_price": 2499, "total": 237405},
        {"name": "USB集线器", "category": "配件", "quantity": 600, "unit_price": 59, "total": 35400}
    ]
}
"""
# 解析 JSON 数据
data = json.loads(json_data)
# 创建 PDF 文档
doc = PdfDocument()
page = doc.Pages.Add()

说明:

此阶段完成了数据准备和文档初始化,为后续内容绘制奠定基础。

2. 绘制文档标题和公司信息

接下来,我们在 PDF 页面顶部绘制报告标题和公司基本信息,建立文档的整体框架。

def draw_header(page, data):
    """绘制文档标题和公司信息"""
    # 设置页面边距
    margin_left = 50
    margin_top = 50
    y_position = margin_top
    
    # 绘制公司标题
    company_font = PdfTrueTypeFont("Arial", 14.0, PdfFontStyle.Bold, True)
    company_brush = PdfSolidBrush(PdfRGBColor(Color.get_DarkGray()))
    page.Canvas.DrawString(
        data["company"], 
        company_font, 
        company_brush, 
        margin_left, 
        y_position
    )
    y_position += 25
    
    # 绘制报告标题
    title_font = PdfTrueTypeFont("Arial", 24.0, PdfFontStyle.Bold, True)
    title_brush = PdfSolidBrush(PdfRGBColor(Color.get_Navy()))
    title_format = PdfStringFormat(PdfTextAlignment.Left)
    page.Canvas.DrawString(
        data["report_title"], 
        title_font, 
        title_brush, 
        margin_left, 
        y_position, 
        title_format
    )
    y_position += 35
    
    # 绘制日期
    date_font = PdfTrueTypeFont("Arial", 11.0, PdfFontStyle.Regular, True)
    date_brush = PdfSolidBrush(PdfRGBColor(Color.get_Gray()))
    page.Canvas.DrawString(
        f"报告日期:{data['date']}", 
        date_font, 
        date_brush, 
        margin_left, 
        y_position
    )
    
    return y_position + 30

# 调用函数绘制头部
current_y = draw_header(page, data)

说明:

此步骤建立了文档的视觉层次,让读者快速了解报告的基本信息。

3. 绘制统计摘要信息

在标题下方,我们展示关键的业务统计数据,以简洁的方式呈现核心指标。

def draw_summary(page, data, y_position):
    """绘制统计摘要"""
    margin_left = 50
    summary = data["summary"]
    
    # 绘制摘要标题
    section_font = PdfTrueTypeFont("Arial", 16.0, PdfFontStyle.Bold, True)
    section_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    page.Canvas.DrawString(
        "销售摘要", 
        section_font, 
        section_brush, 
        margin_left, 
        y_position
    )
    y_position += 30
    
    # 绘制摘要内容
    content_font = PdfTrueTypeFont("Arial", 11.0, PdfFontStyle.Regular, True)
    content_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    
    summary_items = [
        f"总销售额:¥{summary['total_sales']:,.2f}",
        f"订单总数:{summary['total_orders']}",
        f"平均订单价值:¥{summary['average_order_value']:,.2f}"
    ]
    
    for item in summary_items:
        page.Canvas.DrawString(
            item, 
            content_font, 
            content_brush, 
            margin_left, 
            y_position
        )
        y_position += 22
    
    return y_position + 20

# 调用函数绘制摘要
current_y = draw_summary(page, data, current_y)

说明:

此部分突出了报告的核心数据,帮助读者快速把握业务概况。

4. 创建产品明细表格

表格是展示结构化数据的最佳方式。我们将 JSON 中的产品列表转换为 PDF 表格,包含表头和数据行。

def draw_product_table(page, data, y_position):
    """绘制产品明细表格"""
    margin_left = 50
    products = data["products"]
    
    # 绘制表格标题
    table_title_font = PdfTrueTypeFont("Arial", 16.0, PdfFontStyle.Bold, True)
    table_title_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    page.Canvas.DrawString(
        "产品明细", 
        table_title_font, 
        table_title_brush, 
        margin_left, 
        y_position
    )
    y_position += 30
    
    # 定义表格列
    columns = ["产品名称", "类别", "数量", "单价", "总价"]
    column_widths = [120, 100, 80, 100, 100]
    
    # 绘制表头
    header_font = PdfTrueTypeFont("Arial", 11.0, PdfFontStyle.Bold, True)
    header_brush = PdfSolidBrush(PdfRGBColor(Color.get_White()))
    header_bg_brush = PdfSolidBrush(PdfRGBColor(Color.get_Navy()))
    
    x_position = margin_left
    for i, col in enumerate(columns):
        # 绘制表头背景
        rect = RectangleF(x_position, y_position, column_widths[i], 25)
        page.Canvas.DrawRectangle(header_bg_brush, rect)
        # 绘制表头文本
        page.Canvas.DrawString(
            col, 
            header_font, 
            header_brush, 
            x_position + 5, 
            y_position + 5
        )
        x_position += column_widths[i]
    
    y_position += 25
    
    # 绘制数据行
    row_font = PdfTrueTypeFont("Arial", 10.0, PdfFontStyle.Regular, True)
    row_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    alternate_brush = PdfSolidBrush(PdfRGBColor(Color.get_LightGray()))
    
    for idx, product in enumerate(products):
        # 交替行背景色
        if idx % 2 == 0:
            bg_brush = PdfSolidBrush(PdfRGBColor(Color.get_White()))
        else:
            bg_brush = alternate_brush
        
        x_position = margin_left
        row_height = 22
        
        # 绘制行背景
        row_rect = RectangleF(margin_left, y_position, sum(column_widths), row_height)
        page.Canvas.DrawRectangle(bg_brush, row_rect)
        
        # 绘制单元格数据
        cell_data = [
            product["name"],
            product["category"],
            str(product["quantity"]),
            f"¥{product['unit_price']:,}",
            f"¥{product['total']:,}"
        ]
        
        for i, cell_value in enumerate(cell_data):
            page.Canvas.DrawString(
                cell_value, 
                row_font, 
                row_brush, 
                x_position + 5, 
                y_position + 4
            )
            x_position += column_widths[i]
        
        y_position += row_height
    
    # 绘制表格边框
    border_pen = PdfPen(PdfRGBColor(Color.get_Black()), 0.5)
    table_width = sum(column_widths)
    table_height = 25 + len(products) * 22
    
    # 外边框
    page.Canvas.DrawRectangle(
        border_pen, 
        RectangleF(margin_left, y_position - table_height, table_width, table_height)
    )
    
    # 横线
    for i in range(len(products) + 2):
        line_y = y_position - table_height + i * 22 if i > 0 else y_position - table_height
        if i == 0:
            line_y = y_position - table_height
        elif i == 1:
            line_y = y_position - table_height + 25
        else:
            line_y = y_position - table_height + 25 + (i - 1) * 22
        
        page.Canvas.DrawLine(
            border_pen, 
            margin_left, 
            line_y, 
            margin_left + table_width, 
            line_y
        )
    
    # 竖线
    x_pos = margin_left
    for width in column_widths:
        page.Canvas.DrawLine(
            border_pen, 
            x_pos, 
            y_position - table_height, 
            x_pos, 
            y_position
        )
        x_pos += width
    page.Canvas.DrawLine(
        border_pen, 
        x_pos, 
        y_position - table_height, 
        x_pos, 
        y_position
    )
    
    return y_position + 30

# 调用函数绘制表格
current_y = draw_product_table(page, data, current_y)

说明:

此步骤将 JSON 数组转换为结构化的表格,是数据可视化的核心环节。

5. 添加页脚信息

最后,我们在页面底部添加页脚,包含页码和版权信息,使文档更加完整和专业。

def draw_footer(page, page_number, total_pages):
    """绘制页脚"""
    page_width = page.Canvas.ClientSize.Width
    margin_bottom = 30
    
    # 绘制分隔线
    line_pen = PdfPen(PdfRGBColor(Color.get_LightGray()), 0.5)
    page.Canvas.DrawLine(
        line_pen, 
        50, 
        page.Canvas.ClientSize.Height - margin_bottom - 15, 
        page_width - 50, 
        page.Canvas.ClientSize.Height - margin_bottom - 15
    )
    
    # 绘制页码
    footer_font = PdfTrueTypeFont("Arial", 9.0, PdfFontStyle.Regular, True)
    footer_brush = PdfSolidBrush(PdfRGBColor(Color.get_Gray()))
    footer_format = PdfStringFormat(PdfTextAlignment.Center)
    
    page_text = f"第 {page_number} 页 / 共 {total_pages} 页"
    page.Canvas.DrawString(
        page_text, 
        footer_font, 
        footer_brush, 
        page_width / 2, 
        page.Canvas.ClientSize.Height - margin_bottom, 
        footer_format
    )
    
    # 绘制版权信息
    copyright_text = "© 2024 ABC科技有限公司 - 内部资料,请勿外传"
    page.Canvas.DrawString(
        copyright_text, 
        footer_font, 
        footer_brush, 
        page_width / 2, 
        page.Canvas.ClientSize.Height - margin_bottom + 15, 
        footer_format
    )

# 调用函数绘制页脚(单页文档)
draw_footer(page, 1, 1)

说明:

6. 保存 PDF 文档

完成所有内容绘制后,保存 PDF 文件到指定路径。

output_file = "销售报告.pdf"
doc.SaveToFile(output_file)
doc.Close()

print(f"PDF 文档已生成:{output_file}")

说明:

关键类与方法解析

为了便于查阅和扩展,下面整理本文中使用的核心类、方法和属性。

主要类说明

类名说明
PdfDocumentPDF 文档对象,管理整个文档的生命周期
PdfPageBase页面对象,提供画布用于绘制内容
PdfTrueTypeFont字体类,设置字体名称、大小、样式
PdfSolidBrush画刷类,定义填充颜色
PdfPen画笔类,定义线条颜色和宽度
PdfStringFormat文本格式类,设置对齐方式、字符间距等
RectangleF矩形结构,用于定义绘制区域
PdfRGBColor颜色类,支持 RGB 色彩模式

常用方法说明

方法说明参数示例
doc.Pages.Add()添加新页面
page.Canvas.DrawString()在画布上绘制文本(text, font, brush, x, y, format)
page.Canvas.DrawRectangle()绘制矩形(填充或边框)(brush/pen, rectangle)
page.Canvas.DrawLine()绘制直线(pen, x1, y1, x2, y2)
doc.SaveToFile()保存文档到文件(filename)
doc.Close()关闭文档并释放资源

字体与样式设置

# 创建字体
font = PdfTrueTypeFont("Arial", 12.0, PdfFontStyle.Bold, True)
# 参数:字体名称、字号、样式(Bold/Italic/Regular/Underline)、是否嵌入

# 创建画刷
brush = PdfSolidBrush(PdfRGBColor(Color.get_Navy()))
# 支持的颜色:get_Black(), get_White(), get_Red(), get_Blue(), get_Navy() 等

# 创建画笔
pen = PdfPen(PdfRGBColor(Color.get_Black()), 0.5)
# 参数:颜色、线条宽度

# 设置文本格式
format = PdfStringFormat(PdfTextAlignment.Center, PdfVerticalAlignment.Middle)
# 对齐方式:Left, Center, Right, Justify

布局技巧

扩展应用场景

基于本文的基础实现,你可以进一步扩展以下功能:

1. 多页文档支持

当数据量较大时,需要自动分页:

# 检测内容是否超出页面高度
if current_y > page.Canvas.ClientSize.Height - 100:
    page = doc.Pages.Add()  # 添加新页面
    current_y = 50  # 重置 y 坐标

2. 从文件读取 JSON

with open('sales_data.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

3. 添加图表可视化

结合 Spire.PDF 的图形功能,可以绘制柱状图、饼图等:

# 绘制简单柱状图
for i, product in enumerate(products):
    bar_height = product['total'] / 10000  # 缩放比例
    bar_rect = RectangleF(margin_left + i * 60, chart_y, 50, bar_height)
    page.Canvas.DrawRectangle(bar_brush, bar_rect)

4. 批量生成报告

遍历多个 JSON 文件,为不同部门或时间段生成独立报告:

import glob
for json_file in glob.glob('reports/*.json'):
    with open(json_file, 'r') as f:
        data = json.load(f)
    generate_pdf(data, f"report_{json_file}.pdf")

5. 自定义模板系统

将布局逻辑封装为模板类,支持动态配置:

class PDFTemplate:
    def __init__(self, config):
        self.font_config = config['fonts']
        self.color_scheme = config['colors']
        self.layout = config['layout']
    
    def render(self, data):
        # 根据配置渲染 PDF
        pass

总结

通过本文示例,你已经掌握如何使用 Python 从 JSON 数据自动生成专业的 PDF 文档。从解析 JSON 数据结构,到绘制标题、摘要、表格和页脚,整个流程完全自动化,特别适用于业务报表、数据归档和文档分发场景。

相比手动制作 PDF,代码方式具有显著优势:

你可以在此基础上进一步探索更多高级功能,例如添加水印、加密文档、插入图像、生成目录等,为企业级文档自动化提供完整解决方案。如果你正在处理大量结构化数据或需要定期生成标准化报告,这种基于 Python 和 Spire.PDF 的方案将大幅提升你的工作效率。

到此这篇关于使用Python实现将JSON数据生成PDF文档的文章就介绍到这了,更多相关Python JSON数据生成PDF内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文