发布于2026-07-11 阅读(0)
扫一扫,手机访问
在企业日常运营中,JSON格式的数据几乎无处不在——API接口、配置文件、数据交换,几乎都离不开它。但问题来了:如何把这些结构化的JSON数据,变成一份拿得出手的PDF报告?很多人第一反应是手动复制粘贴,或者搬出复杂的模板工具。结果呢?效率低不说,格式还容易跑偏,数据也容易漏掉。尤其是那些需要定期生成的财务报表、项目进度报告、客户信息汇总,自动化生成PDF成了刚需。

这篇文章就来讲讲,怎么用Python把JSON数据自动转成格式规整的PDF文档。整个过程全自动化,不需要人工插手,适用于业务报表生成、数据归档、合同附件制作、API数据可视化等场景。通过代码,你可以灵活控制文档布局、字体样式、表格结构和页面元素,保证生成的PDF既专业又美观。
实现这个功能,需要用到Free Spire.PDF for Python这个库。安装很简单,一行命令搞定:
pip install spire.pdf.free
在生成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,
"a verage_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()
说明:
json.loads() 把JSON字符串转成Python字典,方便后面提取数据。PdfDocument() 创建PDF文档对象,Pages.Add() 添加新页面作为内容载体。这一步完成数据准备和文档初始化,为后续内容绘制打好基础。
接下来,在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_Na vy()))
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)
说明:
PdfTrueTypeFont 用来设置字体类型、大小和样式(比如粗体、斜体)。PdfSolidBrush 定义文本颜色,支持RGB色彩空间。DrawString 方法在指定坐标位置绘制文本,可以配合 PdfStringFormat 设置对齐方式。y_position 变量,实现内容的垂直布局,避免重叠。这一步建立了文档的视觉层次,让读者一眼就能了解报告的基本信息。
标题下面,展示关键的业务统计数据,用简洁的方式呈现核心指标。
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['a verage_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)
说明:
:, 添加千位分隔符,.2f 保留两位小数。这部分突出了报告的核心数据,帮助读者快速把握业务概况。
表格是展示结构化数据的最佳方式。我们把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_Na vy()))
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)
说明:
RectangleF 用来绘制矩形区域,作为单元格背景和边框。DrawLine 方法绘制表格的横线和竖线,形成完整的网格结构。这一步把JSON数组转成结构化的表格,是数据可视化的核心环节。
最后,在页面底部加上页脚,包含页码和版权信息,让文档更完整、更专业。
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)
说明:
所有内容绘制完成后,保存PDF文件到指定路径。
output_file = "销售报告.pdf"
doc.Sa veToFile(output_file)
doc.Close()
print(f"PDF 文档已生成:{output_file}")
说明:
Sa veToFile 方法把内存中的PDF文档保存到文件系统。Close 方法释放文档资源,确保文件完整性。为了方便查阅和扩展,下面整理了本文使用的核心类、方法和属性。
| 类名 | 说明 |
|---|---|
PdfDocument | PDF 文档对象,管理整个文档的生命周期 |
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.Sa veToFile() | 保存文档到文件 | (filename) |
doc.Close() | 关闭文档并释放资源 | 无 |
# 创建字体
font = PdfTrueTypeFont("Arial", 12.0, PdfFontStyle.Bold, True)
# 参数:字体名称、字号、样式(Bold/Italic/Regular/Underline)、是否嵌入
# 创建画刷
brush = PdfSolidBrush(PdfRGBColor(Color.get_Na vy()))
# 支持的颜色:get_Black(), get_White(), get_Red(), get_Blue(), get_Na vy() 等
# 创建画笔
pen = PdfPen(PdfRGBColor(Color.get_Black()), 0.5)
# 参数:颜色、线条宽度
# 设置文本格式
format = PdfStringFormat(PdfTextAlignment.Center, PdfVerticalAlignment.Middle)
# 对齐方式:Left, Center, Right, Justify
margin_left、margin_top 等变量统一管理边距基于本文的基础实现,还可以进一步扩展功能:
当数据量较大时,需要自动分页:
# 检测内容是否超出页面高度
if current_y > page.Canvas.ClientSize.Height - 100:
page = doc.Pages.Add() # 添加新页面
current_y = 50 # 重置 y 坐标
with open('sales_data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
结合 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)
遍历多个 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")
将布局逻辑封装为模板类,支持动态配置:
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的方案,能大大提升工作效率。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8