4.7. 使用reportlab模块

模块默认不支持中文,如果使用中文需要注册,他并不算是真正的开源库。 我们虽然不能用它读取PDF,但是可以画图、画表格、编辑文字,最后可以输出PDF格式。

安装

pip3 install reportlab

在 Debian 12 中,可以通过软件仓储库进行安装:

sudo apt install python3-reportlab

4.7.1. 生成文字

前面我们生成水印时已经使用过了。

>>> from reportlab.lib.styles import getSampleStyleSheet
>>> from reportlab.platypus import Paragraph,SimpleDocTemplate
>>> from reportlab.lib import  colors
>>>
>>> Style=getSampleStyleSheet()

字体的样式,大小

>>> bt = Style['Normal']
>>> bt.fontSize=14

设置分词

>>> bt.wordWrap = 'CJK'

设置行距和缩进

>>> bt.firstLineIndent = 32
>>> bt.leading = 20

这是位置和颜色

>>> bt.alignment=1
>>> bt.textColor = colors.red
>>>
>>> t = Paragraph('hello',bt)
>>> pdf=SimpleDocTemplate('./xx_ppff.pdf')
>>> pdf.multiBuild([t])
1

4.7.2. 生成表格

与生成文字相似,不过要多几个方法

>>> from reportlab.lib.colors import HexColor
>>> from reportlab.platypus import  Table,TableStyle
>>> from reportlab.lib.units import inch
>>>
>>> Style=getSampleStyleSheet()
>>> n = Style['Normal']
>>> data = [[0,1,2,3,4,5,6,7],[0,1,2,3,4,5,6,7],[0,1,2,3,4,5,6,7],[0,1,2,3,4,5,6,7],]

设置表格总宽度,每一列的宽度。

>>> width = 7.2
>>> colWidths = (width / len(data[0])) * inch
>>>
>>> dis_list = []
>>> for x in data:
>>>     dis_list.append(x)

配置样式,没有的就使用默认的。

>>> style = [
>>>     ('FONTSIZE', (0, 0), (-1, 0), 15),
>>>     ('BACKGROUND', (0, 0), (-1, 0), HexColor('#d5dae6')),
>>>     ('BACKGROUND', (0, 1), (-1, 1), HexColor('#d5dae6')),
>>>     ('SPAN',(0,0),(0,1)),
>>>     ('SPAN',(1,0),(2,0)),
>>>     ('SPAN',(3,0),(4,0)),
>>>     ('SPAN',(5,0),(7,0)),
>>>     ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
>>>     ('VALIGN', (-1, 0), (-2, 0), 'MIDDLE'),
>>>     ('LINEBEFORE', (0, 0), (0, -1), 0.1, colors.grey),
>>>     ('TEXTCOLOR', (0, 0), (-1, 0), colors.royalblue),
>>>     ('TEXTCOLOR', (0, -1), (-1, -1), colors.red),
>>>     ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
>>> ]
>>>
>>> component_table = Table(dis_list, colWidths=colWidths,style=style)
>>> pdf = SimpleDocTemplate('./pdf_file/addtable.pdf')

4.7.3. 添加图

与在 Excel 软件内画图相似,也可以用其他的库添加。

画饼状图

图形一般都需要标签进行说明,在这里我们使用中文进行显示,必须要进行注册才能使用。如果没有注册,结果如下图:

_images/report1.png
>>> from reportlab.graphics.shapes import Drawing, Rect
>>> from reportlab.graphics.charts.textlabels import Label
>>> from reportlab.graphics.charts.piecharts import Pie
>>> from reportlab.pdfbase import pdfmetrics
>>> from reportlab.pdfbase.ttfonts import TTFont
>>>
>>> pdfmetrics.registerFont(TTFont('zh','/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc'))
>>> data = [10,9,8,7,6,5,4,3,2,1]
>>> labels = ['第一个','中文','C','D','E',
>>>         'F','G','H','I','J']
>>> use_colors = [HexColor("#696969"),HexColor("#A9A9A9"),HexColor("#D8BFD8"),
>>>          HexColor("#DCDCDC"),HexColor('#E6E6FA'),HexColor("#B0C4DE"),
>>>          HexColor("#778899"),HexColor('#B0C4DE'),HexColor("#6495ED"),
>>>          HexColor("#483D8B")
>>>          ]

设置图的宽度,以及图的位置,在外围添加剂一个边框。

>>> width=360
>>> pie = Pie()
>>> pie.x = 60
>>> pie.y = 20
>>> pie.slices.label_boxStrokeColor = colors.white
>>> # pie.data = data
>>> pie.labels = labels
>>> pie.simpleLabels = 0
>>> pie.sameRadii = 1

设置图形的边界颜色,空白区域的宽度,标签与内侧、外边框的距离,相当于内边距与外边距。

>>> pie.slices.strokeColor = colors.red
>>> pie.strokeWidth=1
>>> pie.strokeColor= colors.white
>>> pie.slices.label_pointer_piePad = 10
>>> pie.slices.label_pointer_edgePad = 25
>>> pie.width = width
>>> pie.direction = 'clockwise'
>>> pie.pointerLabelMode  = 'LeftRight'

程序开始时我们注册了中文,在这里设置中文显示。

>>> for i in range(len(labels)):
>>>     pie.slices[i].fontName = 'zh'
>>> for i, col in enumerate(use_colors):
>>>      pie.slices[i].fillColor  = col

标签的相关设置。

>>> width = 448
>>> height = 230
>>> d = Drawing(width,height)
>>> lab = Label()
>>> lab.x = 220
>>> lab.y = 210
>>> lab.setText('使用中文')
>>> lab.fontName = 'zh'
>>> lab.fontSize = 50

所有的都放到一个对象下面

>>> d.add(lab)
>>> d.background = Rect(0,0,width,height,strokeWidth=1,strokeColor="#868686",fillColor=None)
>>> d.add(pie)
>>>
>>> pdf=SimpleDocTemplate('./xx_addpie.pdf')
>>> pdf.multiBuild([d])
1

让我们再次查看结果。

_images/report2.png

画柱状图

与画饼状图相似。

>>> min=100
>>> max=300
>>> x_list=['a', 'b', 'c']
>>> data=[(100, 200, 120)]
>>> x_label_angle=0
>>> bar_color=HexColor("#7BB8E7")
>>> height=125
>>> width=280
  • min: 设置y轴的最小值

  • max: 设置y轴的最大值

  • x_list: x轴上的标签

  • data: y轴对应标签的值

  • x_label_angle: x轴上标签的倾斜角度

  • bar_color: 柱的颜色 可以是含有多种颜色的列表

  • height: 柱状图的高度

  • width: 柱状图的宽度

  • x和y是柱状图在框中的坐标

  • height 柱状图的高度

  • width 柱状图的宽度

  • bar_color 若含有多种颜色在这里分配

>>> from reportlab.graphics.charts.barcharts import VerticalBarChart
>>> bc = VerticalBarChart()
>>> bc.x = 50
>>> bc.y = 50
>>> bc.height = height
>>> bc.width = width
>>> bc.data = data
>>> for j in range(len(x_list)):
>>>     setattr(bc.bars[j], 'fillColor', bar_color)
>>> minv = min * 0.5
>>> maxv = max * 1.5
>>> maxAxis = int(height/10)
>>> minStep = int((maxv-minv+maxAxis-1)/maxAxis)
  • minStep 调整步长向上取整

  • valueMin 设置y轴的最小值

  • valueMax 设置y轴的最大值

  • valueStep 设置y轴的最小度量单位

  • boxAnchor x轴下方标签坐标的开口方向

  • dx,dy x和y是x轴下方的标签距离x轴远近的坐标

  • angle x轴上描述文字的倾斜角度

>>> bc.valueAxis.valueMin = min * 0.5
>>> bc.valueAxis.valueMax = max * 1.5
>>> bc.valueAxis.valueStep = (max-min)/4
>>> if bc.valueAxis.valueStep < minStep:
>>>     bc.valueAxis.valueStep = minStep
>>> if bc.valueAxis.valueStep == 0:
>>>     bc.valueAxis.valueStep = 1
>>> bc.categoryAxis.labels.boxAnchor = 'ne'
>>> bc.categoryAxis.labels.dx = -5
>>> bc.categoryAxis.labels.dy = -5
>>> bc.categoryAxis.labels.angle = x_label_angle
>>> bc.categoryAxis.labels.fontName = 'zh'
>>> x_real_list = []
>>> if len(x_list) > 10:
>>>     for i in range(len(x_list)):
>>>         tmp = '' if i%5 != 0 else x_list[i]
>>>         x_real_list.append(tmp)
>>> else:
>>>     x_real_list = x_list
>>> bc.categoryAxis.categoryNames = x_real_list
>>> width = 448
>>> height = 230
>>> d = Drawing(width,height)
>>> lab = Label()
>>> lab.x = 220
>>> lab.y = 210
>>> lab.setText(' ')
>>> lab.fontName = 'zh'
>>> lab.fontSize = 20
>>> d.add(lab)
>>> d.background = Rect(0,0,width,height,strokeWidth=1,strokeColor="#868686",fillColor=None)
>>> d.add(bc)
>>> pdf=SimpleDocTemplate('./xx_addbar.pdf')
>>> pdf.multiBuild([d])
1

生成的结果如图所示:

_images/report3.png