最近项目需要生成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)
生成就类似这样:
问题:
生成的pdf在Ubuntu下可以正常打开查看,但是复制到windows下就是中文字体就是黑格格,我不知道是不是windows下没有字体的原因