ReportLab 导出 PDF(图文表格)
ReportLab 导出 PDF(文档创建)
ReportLab 导出 PDF(页面布局)
ReportLab 导出 PDF(图文表格)
文章目录
- 1. Paragraph(段落)
- 2. Table(表格)
- 3. VerticalBarChart(柱形图表)
- 3.1. 多组多条数据
- 3.2. 多组单条数据
- 3.3. 柱状图累加
- 4. 饼状图
- 5. Image(图像)
- 6. 常用颜色
- 7. 字体与编码
1. Paragraph(段落)
https://blog.csdn.net/weixin_49278803/article/details/132907427
2. Table(表格)
https://www.cnblogs.com/jilingxf/p/15857940.html
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFontfrom reportlab.graphics.charts.barcharts import VerticalBarChart # 图表类
from reportlab.graphics.charts.legends import Legend # 图例类
from reportlab.graphics.shapes import Drawing # 绘图工具
from reportlab.platypus import Table, Paragraph, TableStyle
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheetdef draw_table1(datas: list):col_widths, row_heights = [80, 100, 100, 100, 100], [60, 50, 50, 50, 50, 50]# 表格行列的表达形式为(x, y):左上方第一个单元格为(0, 0), 右下角单元格为(-1, -1)table_style = TableStyle([("FONT", (0, 0), (0, -1), "simsun", 15), # 第一列:配置字体("FONT", (0, 0), (-1, 0), "simsun", 15), # 第一行:("FONT", (1, 1), (-1, -1), "simsun", 12),("ALIGN", (0, 0), (-1, -1), "CENTER"), # 水平居中("VALIGN", (0, 0), (-1, -1), "MIDDLE"), # 垂直居中("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black), # 单元格分割线("BOX", (0, 0), (-1, -1), 0.25, colors.black), # 边框("BACKGROUND", (0, 0), (-1, -1), colors.lightgrey), # 背景色(默认为白色)("TEXTCOLOR", (0, 0), (-1, 0), colors.red), # 第一行: 区域字体颜色("LINEBELOW", (0,-1), (-1,-1), 0, colors.white), # 移除最后一行的下框线,延申LINEABOVE(上框线)、LINEBEFORE(左框线)、LINEAFTER(右框线)# ("GRID", (0, 0), (-1, -1), 0.5, colors.black), # 表格框线为灰色,线宽为0.5# ("SPAN", (0, 3), (-1, 3)), # 合并单元格])return Table(datas, colWidths=col_widths, rowHeights=row_heights, style=table_style)def draw_table2(datas: list):col_widths, row_heights = [80, 100, 100, 100, 100], [30, 25, 25, 25, 25, 25]# 表格行列的表达形式为(x, y):左上方第一个单元格为(0, 0), 右下角单元格为(-1, -1)table_style = TableStyle([("FONT", (0, 0), (0, -1), "simsun", 20), # 第一列:配置字体("FONT", (0, 0), (-1, 0), "simsun", 15), # 第一行:("FONT", (1, 1), (-1, -1), "simsun", 15),("ALIGN", (0, 0), (-1, -1), "CENTER"), # 水平居中("VALIGN", (0, 0), (-1, -1), "MIDDLE"), # 垂直居中("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black), # 单元格分割线("BOX", (0, 0), (-1, -1), 0.25, colors.black), # 边框# ("BACKGROUND", (0, 0), (-1, -1), colors.lightgrey), # 背景色(默认为白色)("TEXTCOLOR", (0, 0), (-1, 0), colors.red), # 第一行: 区域字体颜色# ("LINEBELOW", (0,-1), (-1,-1), 0, colors.white), # 移除最后一行的下框线,延申LINEABOVE(上框线)、LINEBEFORE(左框线)、LINEAFTER(右框线)# ("GRID", (0, 0), (-1, -1), 0.5, colors.black), # 表格框线为灰色,线宽为0.5("SPAN", (0, 3), (-1, 3)), # 合并单元格])return Table(datas, colWidths=col_widths, rowHeights=row_heights, style=table_style)def main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))doc = SimpleDocTemplate(filename, pagesize=A4)Story = []datas = [["姓名", "语文", "数学", "英语", "体育"],["张三", 91, 97, 79, "良好"],["李四", 99, 87, 73, "优秀"],["王五", 86, 89, 83, "良好"],["赵六", 95, 88, 86, "良好"],# 当需要将数据在一个单元格分两列的话,可以用下面的语法["孙七", 79, 95, 98, "良"+"\n"+"好"],]# 编辑表格标题及样式tabletitle = """<para alignment=center fontName="simsun" fontSize=20 spaceAfter=30>表1: 学生成绩表</para>"""# 可以配置上下左右页边距,topMargin=1*cm,bottomMargin=1*cm,leftMargin=1*cm,rightMargin=1*cmStory.append(Paragraph(tabletitle, getSampleStyleSheet()["Normal"]))Story.append(draw_table1(datas))tabletitle = """<para alignment=center fontName="simsun" fontSize=20 spaceBefore=30 spaceAfter=30>表1: 学生成绩表</para>"""Story.append(Paragraph(tabletitle))Story.append(draw_table2(datas))doc.build(Story)if __name__ == '__main__': main(filename='example.pdf')
3. VerticalBarChart(柱形图表)
参考:
https://blog.csdn.net/weixin_49278803/article/details/132907427
https://www.cnblogs.com/hujq1029/p/7767980.html
https://zhuanlan.zhihu.com/p/528669672
3.1. 多组多条数据
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFontfrom reportlab.graphics.charts.barcharts import VerticalBarChart # 图表类
from reportlab.graphics.charts.legends import Legend # 图例类
from reportlab.graphics.shapes import Drawing # 绘图工具# 多组多列
def draw_group_bars1(datas: list, categorys: list, legends: list):drawing = Drawing(500, 250)bc = VerticalBarChart()bc.x = 45 # 整个图表的x坐标bc.y = 45 # 整个图表的y坐标bc.height = 200 # 图表的高度bc.width = 350 # 图表的宽度bc.data = datasbc.strokeColor = colors.black # 顶部和右边轴线的颜色bc.valueAxis.valueMin = 5000 # 设置y坐标的最小值bc.valueAxis.valueMax = 26000 # 设置y坐标的最大值bc.valueAxis.valueStep = 2000 # 设置y坐标的步长bc.groupSpacing = 10 # 每组柱状图之间的间隔# bc.barSpacing = 1 # 每个柱状图之间的间隔bc.categoryAxis.labels.dx = 2 # x和y是x轴下方的标签距离x轴远近的坐标bc.categoryAxis.labels.dy = -8# bc.categoryAxis.labels.angle = 20 # x轴上描述文字的倾斜角度bc.categoryAxis.categoryNames = categorysbc.bars[0].fillColor = colors.redbc.bars[1].fillColor = colors.orangebc.bars[2].fillColor = colors.yellowbc.bars[3].fillColor = colors.green# 图示leg = Legend()leg.fontName = 'simsun'leg.alignment = 'right' # 文字在色块的左或者右leg.boxAnchor = 'ne'leg.x = 475 # 图例的x坐标leg.y = 240leg.dxTextSpace = 10 # 色块与文字之间的间距leg.columnMaximum = len(legends)leg.colorNamePairs = legendsdrawing.add(leg)drawing.add(bc)return drawing# 多组多列
def draw_group_bars2(datas: list, categorys: list, legends: list):drawing = Drawing(500, 250)bc = VerticalBarChart()bc.x = 45 # 整个图表的x坐标bc.y = 45 # 整个图表的y坐标bc.height = 200 # 图表的高度bc.width = 350 # 图表的宽度bc.data = datasbc.strokeColor = colors.black # 顶部和右边轴线的颜色bc.valueAxis.valueMin = 5000 # 设置y坐标的最小值bc.valueAxis.valueMax = 26000 # 设置y坐标的最大值bc.valueAxis.valueStep = 2000 # 设置y坐标的步长bc.groupSpacing = 10 # 每组柱状图之间的间隔# bc.barSpacing = 1 # 每个柱状图之间的间隔bc.categoryAxis.labels.dx = 2 # x和y是x轴下方的标签距离x轴远近的坐标bc.categoryAxis.labels.dy = -8bc.categoryAxis.labels.angle = 20 # x轴上描述文字的倾斜角度bc.categoryAxis.categoryNames = categorysbc.bars[0].fillColor = colors.redbc.bars[1].fillColor = colors.orangebc.bars[2].fillColor = colors.yellowbc.bars[3].fillColor = colors.green# 图示leg = Legend()leg.fontName = 'simsun'leg.alignment = 'left' # 文字在色块的左或者右leg.boxAnchor = 'ne'leg.x = 475 # 图例的x坐标leg.y = 240leg.dxTextSpace = 20 # 色块与文字之间的间距leg.columnMaximum = len(legends)leg.colorNamePairs = legendsdrawing.add(leg)drawing.add(bc)return drawingdef main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))doc = SimpleDocTemplate(filename, pagesize=A4)Story = []datas = [(25400, 12900, 20100, 20300, 20300, 17400), (15800, 9700, 12982, 20100, 13900, 7623),(20100, 13900, 9700, 12982, 7623, 15800),(12900, 13900, 20300, 9283, 25400, 9700)]categorys = ['BeiJing', 'ChengDu', 'ShenZhen', 'ShangHai', 'HangZhou', 'NanJing']legends = [(colors.red, '标准1'), (colors.orange, '标准2'), (colors.yellow, '标准3'), (colors.green, '标准4')]Story.append(draw_group_bars1(datas, categorys, legends))Story.append(draw_group_bars2(datas, categorys, legends))doc.build(Story)if __name__ == '__main__': main(filename='example.pdf')
3.2. 多组单条数据
参考:https://dev59.com/uF7Va4cB1Zd3GeqPKod0
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFontfrom reportlab.graphics.charts.barcharts import VerticalBarChart # 图表类
from reportlab.graphics.charts.legends import Legend # 图例类
from reportlab.graphics.shapes import Drawing # 绘图工具
from reportlab.graphics.shapes import String
from reportlab.graphics.charts.textlabels import Label# 多组单条
def draw_group_bar1(datas: list, categorys: list, legends: list):drawing = Drawing(500, 280)# drawing.add(String(45, 260, "多组单条柱状图", fontSize=14, fontName='simsun', fillColor=colors.black))# 配置图表标题title = Label()title.setText("多组单条柱状图")# title.fontSize, title.fontName, title.dx, title.dy = 14, "simsun", 45, 260title.fontSize, title.fontName, title.x, title.y = 14, "simsun", 45, 260drawing.add(title)bc = VerticalBarChart()bc.x = 45 # 整个图表的x坐标bc.y = 45 # 整个图表的y坐标bc.height = 200 # 图表的高度bc.width = 350 # 图表的宽度bc.data = datasbc.strokeColor = colors.black # 顶部和右边轴线的颜色bc.valueAxis.valueMin = 5000 # 设置y坐标的最小值bc.valueAxis.valueMax = 26000 # 设置y坐标的最大值bc.valueAxis.valueStep = 2000 # 设置y坐标的步长bc.groupSpacing = 10 # 每组柱状图之间的间隔# bc.barSpacing = 1 # 每个柱状图之间的间隔bc.categoryAxis.labels.dx = 2bc.categoryAxis.labels.dy = -8# bc.categoryAxis.labels.angle = 20bc.categoryAxis.categoryNames = categorys# 图形柱上标注文字# bc.barLabels.nudge = -10 # 文字在图形柱的上下位置bc.barLabels.nudge = 10 # 文字在图形柱的上下位置# bc.barLabelArray = labels # 要添加的文字# bc.barLabelFormat = 'values' # 以字符串类型,还有函数类型,不会用# bc.barLabelFormat = "%0.0f"bc.barLabelFormat = "%d"bc.bars[0].fillColor = colors.redbc.bars[1].fillColor = colors.orangebc.bars[2].fillColor = colors.yellowbc.bars[3].fillColor = colors.green# 图示leg = Legend()leg.fontName = 'simsun'leg.alignment = 'right' # 文字在色块的左或者右leg.boxAnchor = 'ne'leg.x = 475 # 图例的x坐标leg.y = 240leg.dxTextSpace = 10 # 色块与文字之间的间距leg.columnMaximum = len(legends)leg.colorNamePairs = legendsdrawing.add(leg)drawing.add(bc)return drawingdef draw_group_bar2(datas: list, labels: list, categorys: list, legends: list):drawing = Drawing(500, 280)drawing.add(String(45, 260, "多组单条柱状图", fontSize=14, fontName='simsun', fillColor=colors.black))bc = VerticalBarChart()bc.x = 45 # 整个图表的x坐标bc.y = 45 # 整个图表的y坐标bc.height = 200 # 图表的高度bc.width = 350 # 图表的宽度bc.data = datasbc.strokeColor = colors.black # 顶部和右边轴线的颜色bc.valueAxis.valueMin = 5000 # 设置y坐标的最小值bc.valueAxis.valueMax = 26000 # 设置y坐标的最大值bc.valueAxis.valueStep = 2000 # 设置y坐标的步长bc.groupSpacing = 10 # 每组柱状图之间的间隔# bc.barSpacing = 1 # 每个柱状图之间的间隔bc.categoryAxis.labels.dx = 2bc.categoryAxis.labels.dy = -8bc.categoryAxis.labels.angle = 20bc.categoryAxis.categoryNames = categorys# 图形柱上标注文字# bc.barLabels.nudge = -10 # 文字在图形柱的上下位置bc.barLabels.nudge = 10 # 文字在图形柱的上下位置bc.barLabelArray = labels # 要添加的文字bc.barLabelFormat = 'values' # 以字符串类型,还有函数类型,不会用# bc.barLabelFormat = "%0.0f"# 每组0-3条的颜色bc.bars[0].fillColor = colors.redbc.bars[1].fillColor = colors.orangebc.bars[2].fillColor = colors.yellowbc.bars[3].fillColor = colors.green# 每组第0条 也就是数组中 第一个元组的颜色bc.bars[(0,0)].fillColor = colors.yellowgreenbc.bars[(0,1)].fillColor = colors.bluebc.bars[(0,2)].fillColor = colors.purplebc.bars[(0,3)].fillColor = colors.perubc.bars[(0,4)].fillColor = colors.pinkbc.bars[(0,5)].fillColor = colors.coral# 第1组(也就是第二组) 第1条(第二条)bc.bars[(1,1)].fillColor = colors.gray# 图示leg = Legend()leg.fontName = 'simsun'leg.alignment = 'left' # 文字在色块的左或者右leg.boxAnchor = 'ne'leg.x = 475 # 图例的x坐标leg.y = 240leg.dxTextSpace = 10 # 色块与文字之间的间距leg.columnMaximum = len(legends)leg.colorNamePairs = legends# drawing.add(leg)drawing.add(bc)return drawingdef main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))doc = SimpleDocTemplate(filename, pagesize=A4)Story = []datas = [(25400, 12900, 20100, 20300, 20300, 17400)]categorys = ['BeiJing', 'ChengDu', 'ShenZhen', 'ShangHai', 'HangZhou', 'NanJing']legends = [(colors.red, '标准1'), (colors.orange, '标准2'), (colors.yellow, '标准3'), (colors.green, '标准4')]Story.append(draw_group_bar1(datas, categorys, legends))datas = [(25400, 12900, 20100, 20300, 20300, 17400),(15800, 9700, 12982, 20100, 13900, 7623),]labels = [("25400", "12900", "20100", "20300", "20300", "17400"),("15800", "9700", "12982", "20100", "13900", "7623"),]categorys = ['BeiJing', 'ChengDu', 'ShenZhen', 'ShangHai', 'HangZhou', 'NanJing']legends = [(colors.red, '标准1'), (colors.orange, '标准2'), (colors.yellow, '标准3'), (colors.green, '标准4')]Story.append(draw_group_bar2(datas, labels, categorys, legends))doc.build(Story)if __name__ == '__main__': main(filename='example.pdf')
3.3. 柱状图累加
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFontfrom reportlab.graphics.charts.barcharts import VerticalBarChart # 图表类
from reportlab.graphics.charts.legends import Legend # 图例类
from reportlab.graphics.shapes import Drawing # 绘图工具
from reportlab.graphics.shapes import String
from reportlab.graphics.charts.textlabels import Labeldef func(datas: list):minv, maxv, tmpv = 0, 0, 0# print(len(datas), datas)for idxj,val in enumerate(datas[0]):tmpv = 0for idxi in range(len(datas)):tmpv += datas[idxi][idxj]# print("#########333", tmpv)if tmpv < minv:minv = tmpvif tmpv > maxv:maxv = tmpvreturn minv, maxv# 柱状图累加
def draw_group_bar1(datas: list, categorys: list, legends: list):drawing = Drawing(500, 280)# drawing.add(String(45, 260, "柱状图累加", fontSize=14, fontName='simsun', fillColor=colors.black))# 配置图表标题title = Label()title.setText("柱状图累加")# title.fontSize, title.fontName, title.dx, title.dy = 14, "simsun", 45, 260title.fontSize, title.fontName, title.x, title.y = 14, "simsun", 45, 260drawing.add(title)width = 350height = 200### 调整stepminv, maxv = func(datas)maxAxis = int(height/20)# step = int((maxv-minv+maxAxis-1)/maxAxis) # 向上取整step = int((maxv-minv)/maxAxis) # 向上取整bc = VerticalBarChart()bc.x = 45 # 整个图表的x坐标bc.y = 45 # 整个图表的y坐标bc.height = height # 图表的高度bc.width = width # 图表的宽度bc.data = datasbc.strokeColor = colors.black # 顶部和右边轴线的颜色bc.valueAxis.valueMin = minv # 设置y坐标的最小值bc.valueAxis.valueMax = maxv*1.2 # 设置y坐标的最大值bc.valueAxis.valueStep = step # 设置y坐标的步长bc.groupSpacing = 10 # 每组柱状图之间的间隔# bc.barSpacing = 1 # 每条柱状图之间的间隔bc.categoryAxis.labels.dx = 2bc.categoryAxis.labels.dy = -8bc.categoryAxis.labels.angle = 20bc.categoryAxis.categoryNames = categorys# 图形柱上标注文字# bc.barLabels.nudge = -10 # 文字在图形柱的上下位置bc.barLabels.nudge = 10 # 文字在图形柱的上下位置bc.barLabelFormat = "%0.0f"# 柱状图累加bc.categoryAxis.style = 'stacked'# 图形柱上标注文字# bc.barLabels.nudge = -10 # 文字在图形柱的上下位置bc.barLabels.nudge = 10 # 文字在图形柱的上下位置# bc.barLabelArray = labels # 要添加的文字# bc.barLabelFormat = 'values' # 以字符串类型,还有函数类型,不会用# bc.barLabelFormat = "%0.0f"bc.barLabelFormat = "%d"## 0-3条柱形图的颜色# bc.bars[0].fillColor = colors.red# bc.bars[1].fillColor = colors.orange# bc.bars[2].fillColor = colors.yellow# bc.bars[3].fillColor = colors.greencolorsb = [colors.yellowgreen, colors.blue, colors.purple, colors.peru, colors.pink, colors.coral] colorsg = [colors.red, colors.orange, colors.yellow, colors.green] for idxi in range(len(datas)):setattr(bc.bars[idxi], 'fillColor', colorsg[idxi]) # bar_color若含有多种颜色在这里分配bar_color[j]# 图示leg = Legend()leg.fontName = 'simsun'leg.alignment = 'right' # 文字在色块的左或者右leg.boxAnchor = 'ne'leg.x = 475 # 图例的x坐标leg.y = 240leg.dxTextSpace = 10 # 色块与文字之间的间距leg.columnMaximum = len(legends)leg.colorNamePairs = legendsdrawing.add(leg)drawing.add(bc)return drawingdef draw_group_bar2(datas: list, categorys: list, legends: list):drawing = Drawing(500, 280)drawing.add(String(45, 260, "多组单条柱状图", fontSize=14, fontName='simsun', fillColor=colors.black))width = 350height = 200# 调整stepminv, maxv = func(datas)maxAxis = int(height/20)# step = int((maxv-minv+maxAxis-1)/maxAxis) # 向上取整step = int((maxv-minv)/maxAxis) # 向上取整bc = VerticalBarChart()bc.x = 45 # 整个图表的x坐标bc.y = 45 # 整个图表的y坐标bc.height = height # 图表的高度bc.width = width # 图表的宽度bc.data = datasbc.strokeColor = colors.black # 顶部和右边轴线的颜色bc.valueAxis.valueMin = minv # 设置y坐标的最小值bc.valueAxis.valueMax = maxv*1.2 # 设置y坐标的最大值bc.valueAxis.valueStep = step # 设置y坐标的步长bc.groupSpacing = 10 # 每组柱状图之间的间隔# bc.barSpacing = 1 # 每条柱状图之间的间隔bc.categoryAxis.labels.dx = 2bc.categoryAxis.labels.dy = -8bc.categoryAxis.labels.angle = 20bc.categoryAxis.categoryNames = categorys# 图形柱上标注文字# bc.barLabels.nudge = -10 # 文字在图形柱的上下位置bc.barLabels.nudge = 10 # 文字在图形柱的上下位置bc.barLabelFormat = "%0.0f"# 柱状图累加bc.categoryAxis.style = 'stacked'colorsb = [colors.yellowgreen, colors.blue, colors.purple, colors.peru, colors.pink, colors.coral] colorsg = [colors.red, colors.orange, colors.yellow, colors.green] for idxi in range(len(datas)):for idxj in range(len(datas[0])):if idxi == 0:setattr(bc.bars[(idxi, idxj)], 'fillColor', colorsb[idxj])else:setattr(bc.bars[(idxi, idxj)], 'fillColor', colorsg[idxi])# 图示leg = Legend()leg.fontName = 'simsun'leg.alignment = 'left' # 文字在色块的左或者右leg.boxAnchor = 'ne'leg.x = 475 # 图例的x坐标leg.y = 240leg.dxTextSpace = 10 # 色块与文字之间的间距leg.columnMaximum = len(legends)leg.colorNamePairs = legends# drawing.add(leg)drawing.add(bc)return drawingdef main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))doc = SimpleDocTemplate(filename, pagesize=A4)Story = []datas = [(25400, 12900, 20100, 20300, 20300, 17400),(15800, 9700, 12982, 20100, 13900, 7623),]categorys = ['BeiJing', 'ChengDu', 'ShenZhen', 'ShangHai', 'HangZhou', 'NanJing']legends = [(colors.red, '标准1'), (colors.orange, '标准2'), (colors.yellow, '标准3'), (colors.green, '标准4')]Story.append(draw_group_bar1(datas, categorys, legends))Story.append(draw_group_bar2(datas, categorys, legends))doc.build(Story)if __name__ == '__main__': main(filename='example.pdf')
4. 饼状图
5. Image(图像)
6. 常用颜色
7. 字体与编码
https://blog.csdn.net/qq_40596572/article/details/102896520
字体
https://blog.csdn.net/qtlyx/article/details/99653081