添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
主题帖

Ubuntu下通过reportLab库生成pdf报表

米修儿
LV.4
2022-03-18 18:12

最近项目需要生成pdf,通过查找资料发现通过reportLab库来实现挺方便,最终成功解决问题,顺便记录依一下,以备查询和学习。

成pdf的方式(python)有reportlab、pdfkit、xhtml2pdf、 django -easy-pdf。纵观几种都用优缺点,但是相对来说reportlab资料更多,各方面更方便些.

优点: 基本上报表、巡检报告等涉及的都能实现

缺点: 字体需要引入字体文件,但是可以通过下载字体文件解决

下面就说具体生产过程:

模块默认不支持中文,若是使用中文须要注册 app

1.注册中文字体,下载的很多Ubuntu下不能用

1.查看reportlab已注册的字体
from reportlab.pdfbase import pdfmetrics
pdfmetrics.getRegisteredFontNames()
#>>>['Helvetica', 'STSong-Light', 'Symbol', 'ZapfDingbats', 'msyh']
pdfmetrics.dumpFontData()
Registered Encodings:
    SymbolEncoding
    WinAnsiEncoding
    ZapfDingbatsEncoding
Registered Typefaces:
    Helvetica
    Symbol
    ZapfDingbats
Registered Fonts:
    Helvetica (Helvetica/WinAnsiEncoding)
    STSong-Light (STSong-Light/UniGB-UCS2-H)
    Symbol (Symbol/SymbolEncoding)
    ZapfDingbats (ZapfDingbats/ZapfDingbatsEncoding)
    msyh (b'MicrosoftYaHei'/UTF-8)   

基本实现代码:

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, PageBreak, Table, TableStyle
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import mm
from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
from reportlab.pdfbase.ttfonts import TTFont 
pdfmetrics.registerFont(TTFont('msyh', 'msyh.ttf')) 
# 生成PDF文件
class PDFGenerator(QObject):
    def __init__(self):
        super().__init__()
        self.title_style = ParagraphStyle(name="TitleStyle", fontName="ping", fontSize=48, alignment=TA_LEFT, )
        self.sub_title_style = ParagraphStyle(name="SubTitleStyle", fontName="ping", fontSize=32,
                                              textColor=colors.HexColor(0x666666), alignment=TA_LEFT, )
        self.content_style = ParagraphStyle(name="ContentStyle", fontName="ping", fontSize=18, leading=25,
                                            spaceAfter=20,
                                            underlineWidth=1, alignment=TA_LEFT, )
        self.table_title_style = ParagraphStyle(name="TableTitleStyle", fontName="ping", fontSize=20, leading=25,
                                                spaceAfter=10, alignment=TA_LEFT, )
        self.content_style = ParagraphStyle(name="SubTableTitleStyle", fontName="ping", fontSize=16, leading=25,
                                            spaceAfter=10, alignment=TA_LEFT, )
        self.common_style = TableStyle([('FONTNAME', (0, 0), (-1, -1), 'ping'),
                                        ('FONT SIZE', (0, 0), (-1, -1), 12),
                                        ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
                                        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                                        ('BOTTOM PADDING', (0, 0), (-1, -1), 6),
                                        ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
    def create_pdf(self, file_name, home_data, image_list, verdict_data):
        story = {Spacer(1, 20 * mm), Spacer(1, 10 * mm), Paragraph("测试报告", self.title_style), Spacer(1, 20 * mm),
                 Paragraph("Test Report of XXX", self.sub_title_style), Spacer(1, 85 * mm),
                 Paragraph("检测部件:" + home_data[0], self.content_style),
                 Paragraph("检测单位:" + home_data[1], self.content_style),
                 Paragraph("检 测 人:" + home_data[2], self.content_style),
                 Paragraph("报告日期:" + "home_data[2]", self.content_style), Spacer(1, 55 * mm), PageBreak()}
        # 表格允许单元格内容自动换行格式设置
        stylesheet = getSampleStyleSheet()
        body_style = stylesheet["BodyText"]
        body_style.wordWrap = 'CJK'
        body_style.fontName = 'ping'
        body_style.fontSize = 12
        # 检测图片
        story.append(Paragraph("检测图片", self.table_title_style))
        story.append(Spacer(1, 3 * mm))
        # task_table = Table(task_data, colWidths=[25 * mm, 141 * mm], rowHeights=12 * mm, style=self.common_style)
        # story.append(task_table)
        for file in image_list:
            t = Image(file, width=400, height=300)
            story.append(t)
            story.append(Spacer(1, 20 * mm))
        doc = SimpleDocTemplate(file_name,
                                leftMargin=20 * mm, rightMargin=20 * mm, topMargin=20 * mm, bottomMargin=20 * mm)
        doc.build(story)
        story.append(Spacer(1, 10 * mm))
        # 基础参数
        story.append(Paragraph("基础参数", self.sub_table_style))
        basic_table = Table(basic_data, colWidths=[25*mm, 61*mm, 25*mm, 55*mm], rowHeights=12 * mm, style=self.basic_style)
        story.append(basic_table)
        story.append(Spacer(1, 15 * mm))
        doc.build(story)

注意:这里涉及到两种字体:

1.CID字体(CID字库技术是美国Adobe公司发表的最新字库格式)

2.TTF字体(TTF(TrueTypeFont)是Apple公司和Microsoft公司共同推出的字体文件格式)

生成大概样式:

  需要说明的:

  1.项目后台使用的是python3.8.10;

  2.如果需要使用到特定的字体,需要将字体下载下来放到reportlab模块安装位置的font文件夹下,如:/usr/loacl/lib/python3.8.10/site-packages/reportlab/fonts/;

  3.支持表格中的中文依文字长度自动换行

这个是别人的例子,我用到的很少,就首页、然后添加图片

图片的调用接口比较简单,在调用该接口时,支持默认的jpeg格式。接口如下:

Image(filename, width=None, height=None)

filename:指定文件名width:指定图片的宽度height:指定图片的高度

如果宽度和高度有一个没有被指定,则参考原来的图片像素。

from reportlab.platypus import SimpleDocTemplate, Image
from reportlab.lib.styles import getSampleStyleSheet
doc = SimpleDocTemplate("Hello.pdf")
styles = getSampleStyleSheet()
style = styles['Normal']
story =[]
t = Image("C:\\Users\\Administrator\\Desktop\\timg.jpg?x-oss-process=image/watermark,g_center,image_YXJ0aWNsZS9wdWJsaWMvd2F0ZXJtYXJrLnBuZz94LW9zcy1wcm9jZXNzPWltYWdlL3Jlc2l6ZSxQXzQwCg,t_20")
story.append(t)
doc.build(story)

生成就类似这样: