Python生成图文并茂的PDF报告

举报
Python小二 发表于 2022/06/07 00:03:56 2022/06/07
【摘要】 reportlab是Python的一个标准库,可以画图、画表格、编辑文字,最后可以输出PDF格式。它的逻辑和编辑一个word文档或者PPT很像。有两种方法: 1)建立一个空白文档,然后在上面写文字、画图等; 2)建立一个空白list,以填充表格的形式插入各种文本框、图片等,最后生成PDF文档。 因为需要产生一份给用户看的报告...

reportlab是Python的一个标准库,可以画图、画表格、编辑文字,最后可以输出PDF格式。它的逻辑和编辑一个word文档或者PPT很像。有两种方法:

1)建立一个空白文档,然后在上面写文字、画图等;

2)建立一个空白list,以填充表格的形式插入各种文本框、图片等,最后生成PDF文档。

因为需要产生一份给用户看的报告,里面需要插入图片、表格等,所以采用的是第二种方法。

安装第三方库

reportlab输入Python的第三方库,使用前需要先安装:pip install reportlab

模块导入

提前导入相关内容,并且注册字体。(注册字体前需要先准备好字体文件)


   
  1. from reportlab.pdfbase import pdfmetrics   # 注册字体
  2. from reportlab.pdfbase.ttfonts import TTFont # 字体类
  3. from reportlab.platypus import Table, SimpleDocTemplate, Paragraph, Image  # 报告内容相关类
  4. from reportlab.lib.pagesizes import letter  # 页面的标志尺寸(8.5*inch, 11*inch)
  5. from reportlab.lib.styles import getSampleStyleSheet  # 文本样式
  6. from reportlab.lib import colors  # 颜色模块
  7. from reportlab.graphics.charts.barcharts import VerticalBarChart  # 图表类
  8. from reportlab.graphics.charts.legends import Legend  # 图例类
  9. from reportlab.graphics.shapes import Drawing  # 绘图工具
  10. from reportlab.lib.units import cm  # 单位:cm
  11. # 注册字体(提前准备好字体文件, 如果同一个文件需要多种字体可以注册多个)
  12. pdfmetrics.registerFont(TTFont('SimSun''SimSun.ttf'))

封装不同内容对应的函数

创建一个Graphs类,通过不同的静态方法提供不同的报告内容,包括:标题、普通段落、图片、表格和图表。函数中的相关数据目前绝大多数都是固定值,可以根据情况自行设置成相关参数。


   
  1. class Graphs:
  2.     # 绘制标题
  3.     @staticmethod
  4.     def draw_title(title: str):
  5.         # 获取所有样式表
  6.         style = getSampleStyleSheet()
  7.         # 拿到标题样式
  8.         ct = style['Heading1']
  9.         # 单独设置样式相关属性
  10.         ct.fontName = 'SimSun'      # 字体名
  11.         ct.fontSize = 18            # 字体大小
  12.         ct.leading = 50             # 行间距
  13.         ct.textColor = colors.green     # 字体颜色
  14.         ct.alignment = 1    # 居中
  15.         ct.bold = True
  16.         # 创建标题对应的段落,并且返回
  17.         return Paragraph(title, ct)
  18.       
  19.   # 绘制小标题
  20.     @staticmethod
  21.     def draw_little_title(title: str):
  22.         # 获取所有样式表
  23.         style = getSampleStyleSheet()
  24.         # 拿到标题样式
  25.         ct = style['Normal']
  26.         # 单独设置样式相关属性
  27.         ct.fontName = 'SimSun'  # 字体名
  28.         ct.fontSize = 15  # 字体大小
  29.         ct.leading = 30  # 行间距
  30.         ct.textColor = colors.red  # 字体颜色
  31.         # 创建标题对应的段落,并且返回
  32.         return Paragraph(title, ct)
  33.     # 绘制普通段落内容
  34.     @staticmethod
  35.     def draw_text(text: str):
  36.         # 获取所有样式表
  37.         style = getSampleStyleSheet()
  38.         # 获取普通样式
  39.         ct = style['Normal']
  40.         ct.fontName = 'SimSun'
  41.         ct.fontSize = 12
  42.         ct.wordWrap = 'CJK'     # 设置自动换行
  43.         ct.alignment = 0        # 左对齐
  44.         ct.firstLineIndent = 32     # 第一行开头空格
  45.         ct.leading = 25
  46.         return Paragraph(text, ct)
  47.     # 绘制表格
  48.     @staticmethod
  49.     def draw_table(*args):
  50.         # 列宽度
  51.         col_width = 120
  52.         style = [
  53.             ('FONTNAME', (00), (-1-1), 'SimSun'),  # 字体
  54.             ('FONTSIZE', (00), (-10), 12),  # 第一行的字体大小
  55.             ('FONTSIZE', (01), (-1-1), 10),  # 第二行到最后一行的字体大小
  56.             ('BACKGROUND', (00), (-10), '#d5dae6'),  # 设置第一行背景颜色
  57.             ('ALIGN', (00), (-1-1), 'CENTER'),  # 第一行水平居中
  58.             ('ALIGN', (01), (-1-1), 'LEFT'),  # 第二行到最后一行左右左对齐
  59.             ('VALIGN', (00), (-1-1), 'MIDDLE'),  # 所有表格上下居中对齐
  60.             ('TEXTCOLOR', (00), (-1-1), colors.darkslategray),  # 设置表格内文字颜色
  61.             ('GRID', (00), (-1-1), 0.5, colors.grey),  # 设置表格框线为grey色,线宽为0.5
  62.             # ('SPAN', (01), (02)),  # 合并第一列二三行
  63.             # ('SPAN', (03), (04)),  # 合并第一列三四行
  64.             # ('SPAN', (05), (06)),  # 合并第一列五六行
  65.             # ('SPAN', (07), (08)),  # 合并第一列五六行
  66.         ]
  67.         table = Table(args, colWidths=col_width, style=style)
  68.         return table
  69.     # 创建图表
  70.     @staticmethod
  71.     def draw_bar(bar_data: list, ax: list, items: list):
  72.         drawing = Drawing(500250)
  73.         bc = VerticalBarChart()
  74.         bc.x = 45       # 整个图表的x坐标
  75.         bc.y = 45      # 整个图表的y坐标
  76.         bc.height = 200     # 图表的高度
  77.         bc.width = 350      # 图表的宽度
  78.         bc.data = bar_data
  79.         bc.strokeColor = colors.black       # 顶部和右边轴线的颜色
  80.         bc.valueAxis.valueMin = 5000           # 设置y坐标的最小值
  81.         bc.valueAxis.valueMax = 26000         # 设置y坐标的最大值
  82.         bc.valueAxis.valueStep = 2000         # 设置y坐标的步长
  83.         bc.categoryAxis.labels.dx = 2
  84.         bc.categoryAxis.labels.dy = -8
  85.         bc.categoryAxis.labels.angle = 20
  86.         bc.categoryAxis.categoryNames = ax
  87.         # 图示
  88.         leg = Legend()
  89.         leg.fontName = 'SimSun'
  90.         leg.alignment = 'right'
  91.         leg.boxAnchor = 'ne'
  92.         leg.x = 475         # 图例的x坐标
  93.         leg.y = 240
  94.         leg.dxTextSpace = 10
  95.         leg.columnMaximum = 3
  96.         leg.colorNamePairs = items
  97.         drawing.add(leg)
  98.         drawing.add(bc)
  99.         return drawing
  100.     # 绘制图片
  101.     @staticmethod
  102.     def draw_img(path):
  103.         img = Image(path)       # 读取指定路径下的图片
  104.         img.drawWidth = 5*cm        # 设置图片的宽度
  105.         img.drawHeight = 8*cm       # 设置图片的高度
  106.         return img

生成报告


   
  1. if __name__ == '__main__':
  2.     # 创建内容对应的空列表
  3.     content = list()
  4.     # 添加标题
  5.     content.append(Graphs.draw_title('数据分析就业薪资'))
  6.     # 添加图片
  7.     content.append(Graphs.draw_img('抗疫必胜.png'))
  8.     # 添加段落文字
  9.     content.append(Graphs.draw_text('众所周知,大数据分析师岗位是香饽饽,近几年数据分析热席卷了整个互联网行业,与数据分析的相关的岗位招聘、培训数不胜数。很多人前赴后继,想要参与到这波红利当中。那么数据分析师就业前景到底怎么样呢?'))
  10.     # 添加小标题
  11.     content.append(Graphs.draw_title(''))
  12.     content.append(Graphs.draw_little_title('不同级别的平均薪资'))
  13.     # 添加表格
  14.     data = [
  15.         ('职位名称''平均薪资''较上年增长率'),
  16.         ('数据分析师''18.5K''25%'),
  17.         ('高级数据分析师''25.5K''14%'),
  18.         ('资深数据分析师''29.3K''10%')
  19.     ]
  20.     content.append(Graphs.draw_table(*data))
  21.     # 生成图表
  22.     content.append(Graphs.draw_title(''))
  23.     content.append(Graphs.draw_little_title('热门城市的就业情况'))
  24.     b_data = [(254001290020100203002030017400), (158009700129829283139007623)]
  25.     ax_data = ['BeiJing''ChengDu''ShenZhen''ShangHai''HangZhou''NanJing']
  26.     leg_items = [(colors.red, '平均薪资'), (colors.green, '招聘量')]
  27.     content.append(Graphs.draw_bar(b_data, ax_data, leg_items))
  28.     # 生成pdf文件
  29.     doc = SimpleDocTemplate('report.pdf', pagesize=letter)
  30.     doc.build(content)

生成报告的结果如下:

50a96227477564fba4d7db1ad2a60162.png

推荐阅读  点击标题可跳转


   
  1. 点分享
  2. 点点赞
  3. 点在看

文章来源: ityard.blog.csdn.net,作者:Python小二,版权归原作者所有,如需转载,请联系作者。

原文链接:ityard.blog.csdn.net/article/details/125139427

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。