reportlab模塊是用python語言生成pdf文件的模塊python
安裝:pip install reportlabcanvas
模塊默認不支持中文,若是使用中文須要註冊app
下載本身須要的.ttf字體,例如STSONG.ttfecharts
from reportlab.pdfbase import pdfmetrics字體
from reportlab.pdfbase.ttfonts import TTFontui
pdfmetrics.registerFont(TTFont('song', STSONG.ttf))spa
from reportlab.lib.styles import getSampleStyleSheet from reportlab.platypus import Paragraph,SimpleDocTemplate from reportlab.lib import colors Style=getSampleStyleSheet() bt = Style['Normal'] #字體的樣式 # bt.fontName='song' #使用的字體 bt.fontSize=14 #字號 bt.wordWrap = 'CJK' #該屬性支持自動換行,'CJK'是中文模式換行,用於英文中會截斷單詞形成閱讀困難,可改成'Normal' bt.firstLineIndent = 32 #該屬性支持第一行開頭空格 bt.leading = 20 #該屬性是設置行距 ct=Style['Normal'] # ct.fontName='song' ct.fontSize=12 ct.alignment=1 #居中 ct.textColor = colors.red t = Paragraph('hello',bt) pdf=SimpleDocTemplate('ppff.pdf') pdf.multiBuild([t])
一份pdf文件能夠定義多種字體樣式,如bt和ct。字體有多種屬性,這裏只列舉一些經常使用的屬性,rest
其中,code
wordWrap自動換行屬性的參數'CJK'是按照中文方式換行(能夠在字符之間換行),英文方式爲'Normal'(在空格出換行)component
alignment:0 左對齊
1 居中
2 右對齊
from reportlab.platypus import Table
t = Table(data)
from reportlab.platypus import Paragraph, SimpleDocTemplate, Table,TableStyle from reportlab.lib.units import inch from reportlab.lib import colors def table_model(data): width = 7.2 # 總寬度 colWidths = (width / len(data[0])) * inch # 每列的寬度 dis_list = [] for x in data: # dis_list.append(map(lambda i: Paragraph('%s' % i, cn), x)) dis_list.append(x) style = [ # ('FONTNAME', (0, 0), (-1, -1), 'song'), # 字體 ('FONTSIZE', (0, 0), (-1, 0), 15), # 字體大小 ('BACKGROUND', (0, 0), (-1, 0), HexColor('#d5dae6')), # 設置第一行背景顏色 ('BACKGROUND', (0, 1), (-1, 1), HexColor('#d5dae6')), # 設置第二行背景顏色 # 合併 ('SPAN',(第一個方格的左上角座標),(第二個方格的左上角座標)),合併後的值爲靠上一行的值,按照長方形合併 ('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), # 設置表格左邊線顏色爲灰色,線寬爲0.1 ('TEXTCOLOR', (0, 0), (-1, 0), colors.royalblue), # 設置表格內文字顏色 ('TEXTCOLOR', (0, -1), (-1, -1), colors.red), # 設置表格內文字顏色 ('GRID', (0, 0), (-1, -1), 0.5, colors.grey), # 設置表格框線爲grey色,線寬爲0.5 ] component_table = Table(dis_list, colWidths=colWidths,style=style) return component_table Style=getSampleStyleSheet() n = Style['Normal'] data = [[0,1,2,3,4,5,6,7], [00,11,22,33,44,55,66,77], [000,111,222,333,444,555,666,777], [0000,1111, 2222, 3333, 4444, 5555, 6666, 7777],] z = table_model(data) pdf = MyDocTemplate('ppff.pdf') pdf.multiBuild([Paragraph('Title',n),z])
from reportlab.graphics.shapes import Drawing
d = Drawing()
參數有:
d.width:邊框寬度
d.heigth:邊框高度
d.background:邊框顏色
等等。
邊框中可以使用add()添加文字,圖形等內容
例:
在邊框中添加文字
from reportlab.graphics.shapes import Drawing, Rect
from reportlab.graphics.charts.textlabels import Label
def autoLegender( title=''): width = 448 height = 230 d = Drawing(width,height) lab = Label() lab.x = 220 #x和y是文字的位置座標 lab.y = 210 lab.setText(title) # lab.fontName = 'song' #增長對中文字體的支持 lab.fontSize = 20 d.add(lab) d.background = Rect(0,0,width,height,strokeWidth=1,strokeColor="#868686",fillColor=None) #邊框顏色 return d l = autoLegender('hello') pdf=SimpleDocTemplate('ppff.pdf') pdf.multiBuild([l])
# **這種方法能夠給邊框中的圖例添加顏色說明**
def autoLegender(chart, categories=[], use_colors=[], title=''): width = 448 height = 230 d = Drawing(width,height) lab = Label() lab.x = 220 #x和y是title文字的位置座標 lab.y = 210 lab.setText(title) # lab.fontName = 'song' #增長對中文字體的支持 lab.fontSize = 20 d.add(lab) d.background = Rect(0,0,width,height,strokeWidth=1,strokeColor="#868686",fillColor=None) #邊框顏色 d.add(chart) #顏色圖例說明等 leg = Legend() leg.x = 500 # 說明的x軸座標 leg.y = 0 # 說明的y軸座標 leg.boxAnchor = 'se' # leg.strokeWidth = 4 leg.strokeColor = None leg.subCols[1].align = 'right' leg.columnMaximum = 10 # 圖例說明一列最多顯示的個數
# leg.fontName = 'song' leg.alignment = 'right' leg.colorNamePairs = zip(use_colors, tuple(categories)) #增長顏色說明 d.add(leg) return d
餅圖須要添加在邊框中
from reportlab.lib import colors from reportlab.platypus import SimpleDocTemplate from reportlab.graphics.shapes import Drawing, Rect from reportlab.graphics.charts.textlabels import Label from reportlab.graphics.charts.piecharts import Pie def autoLegender( chart,title=''): width = 448 height = 230 d = Drawing(width,height) lab = Label() lab.x = 220 #x和y是文字的位置座標 lab.y = 210 lab.setText(title) # lab.fontName = 'song' #增長對中文字體的支持 lab.fontSize = 20 d.add(lab) d.background = Rect(0,0,width,height,strokeWidth=1,strokeColor="#868686",fillColor=None) #邊框顏色 d.add(chart) return d def draw_pie(data=[], labels=[], use_colors=[], width=360,): '''更多屬性請查詢reportlab.graphics.charts.piecharts.WedgeProperties''' pie = Pie() pie.x = 60 # x,y餅圖在框中的座標 pie.y = 20 pie.slices.label_boxStrokeColor = colors.white #標籤邊框的顏色 pie.data = data # 餅圖上的數據 pie.labels = labels # 數據的標籤 pie.simpleLabels = 0 # 0 標籤在標註線的右側;1 在線上邊 pie.sameRadii = 1 # 0 餅圖是橢圓;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 = 'song' #設置中文 for i, col in enumerate(use_colors): pie.slices[i].fillColor = col return pie
data = [10,9,8,7,6,5,4,3,2,1]
labs = ['0000000','1111111','2222222','3333333','4444444',
'5555555','6666666','7777777','8888888','9999999']
color = [HexColor("#696969"),HexColor("#A9A9A9"),HexColor("#D8BFD8"),
HexColor("#DCDCDC"),HexColor('#E6E6FA'),HexColor("#B0C4DE"),
HexColor("#778899"),HexColor('#B0C4DE'),HexColor("#6495ED"),
HexColor("#483D8B")
]
z = autoLegender(draw_pie(data,labs,color),labs,color)
pdf=SimpleDocTemplate('ppff.pdf')
pdf.multiBuild([z])
柱狀圖須要添加在邊框中
from reportlab.graphics.charts.barcharts import VerticalBarChart from reportlab.lib.colors import HexColor def draw_bar_chart(min, max, x_list, data=[()], x_label_angle=0, bar_color=HexColor("#7BB8E7"), height=125, width=280): ''' :param min: 設置y軸的最小值 :param max: 設置y軸的最大值 :param x_list: x軸上的標籤 :param data: y軸對應標籤的值 :param x_label_angle: x軸上標籤的傾斜角度 :param bar_color: 柱的顏色 能夠是含有多種顏色的列表 :param height: 柱狀圖的高度 :param width: 柱狀圖的寬度 :return: ''' bc = VerticalBarChart() bc.x = 50 # x和y是柱狀圖在框中的座標 bc.y = 50 bc.height = height # 柱狀圖的高度 bc.width = width # 柱狀圖的寬度 bc.data = data for j in xrange(len(x_list)): setattr(bc.bars[j], 'fillColor', bar_color) # bar_color若含有多種顏色在這裏分配bar_color[j] # 調整step minv = min * 0.5 maxv = max * 1.5 maxAxis = int(height/10) # 向上取整 minStep = int((maxv-minv+maxAxis-1)/maxAxis) bc.valueAxis.valueMin = min * 0.5 #設置y軸的最小值 bc.valueAxis.valueMax = max * 1.5 #設置y軸的最大值 bc.valueAxis.valueStep = (max-min)/4 #設置y軸的最小度量單位 if bc.valueAxis.valueStep < minStep: bc.valueAxis.valueStep = minStep if bc.valueAxis.valueStep == 0: bc.valueAxis.valueStep = 1 bc.categoryAxis.labels.boxAnchor = 'ne' # x軸下方標籤座標的開口方向 bc.categoryAxis.labels.dx = -5 # x和y是x軸下方的標籤距離x軸遠近的座標 bc.categoryAxis.labels.dy = -5 bc.categoryAxis.labels.angle = x_label_angle # x軸上描述文字的傾斜角度 # bc.categoryAxis.labels.fontName = 'song' 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 return bc z = autoLegender(draw_bar_chart(100, 300, ['a', 'b', 'c'], [(100, 200, 120)])) pdf=SimpleDocTemplate('ppff.pdf') pdf.multiBuild([z])
6.累加柱狀圖
def draw_2bar_chart(min, max, x_list, data=[()],array=[()], x_label_angle=0,bar_color=[],height=125, width=280): ''' :param min: 設置y軸的最小值 :param max: 設置y軸的最大值 :param x_list: x軸上的標籤 :param data: y軸對應標籤的值 :param x_label_angle: x軸上標籤的傾斜角度 :param bar_color: 柱的顏色 能夠是含有多種顏色的列表 :param height: 柱狀圖的高度 :param width: 柱狀圖的寬度 :return: ''' bc = VerticalBarChart() bc.x = 50 # x和y是柱狀圖在框中的座標 bc.y = 50 bc.height = height # 柱狀圖的高度 bc.width = width # 柱狀圖的寬度 bc.data = data # 圖形柱上標註文字 bc.barLabels.nudge = -5 # 文字在圖形柱的上下位置 bc.barLabelArray = array # 要添加的文字 bc.barLabelFormat = 'values' for j in xrange(len(data)): setattr(bc.bars[j], 'fillColor', bar_color[j]) # bar_color若含有多種顏色在這裏分配bar_color[j] # 調整step # minv = min * 0.5 minv = 0 maxv = max * 1.5 maxAxis = int(height/10) # 向上取整 minStep = int((maxv-minv+maxAxis-1)/maxAxis) bc.valueAxis.valueMin =0 #設置y軸的最小值 bc.valueAxis.valueMax = max * 1.5 #設置y軸的最大值 bc.valueAxis.valueStep = (max-min)/4 #設置y軸的最小度量單位 if bc.valueAxis.valueStep < minStep: bc.valueAxis.valueStep = minStep if bc.valueAxis.valueStep == 0: bc.valueAxis.valueStep = 1 bc.categoryAxis.labels.boxAnchor = 'ne' # x軸下方標籤座標的開口方向 bc.categoryAxis.labels.dx = -5 # x和y是x軸下方的標籤距離x軸遠近的座標 bc.categoryAxis.labels.dy = -5 bc.categoryAxis.labels.angle = x_label_angle # x軸上描述文字的傾斜角度 # bc.categoryAxis.labels.fontName = 'song' bc.categoryAxis.style = 'stacked' 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 return bc # 制柱狀圖 Style=getSampleStyleSheet() n = Style['Normal'] my_color = [HexColor('#E13C3C'),HexColor('#BE0000')] z = autoLegender(draw_2bar_chart(100, 300, ['a', 'b', 'c'], [(100, 200, 120),(150, 50, 130)], bar_color=my_color, array=[['100','200','120'],['150','50','130']] ), categories=['first','last'], use_colors=my_color ) pdf = MyDocTemplate('ppff.pdf') pdf.multiBuild([Paragraph('Title',n),z])
添加頁眉須要咱們自定義模版
from reportlab.platypus.doctemplate import BaseDocTemplate, Frame from reportlab.lib.units import cm from reportlab.platypus import PageTemplate from reportlab.lib.styles import getSampleStyleSheet import os def myMainPageFrame(canvas, doc): # 全局應用 "The page frame used for all PDF documents." canvas.saveState() canvas.setFont('Times-Roman', 12) pageNumber = canvas.getPageNumber() if pageNumber > 0: pic_yemei = os.path.join(os.path.dirname(__file__),'yemei01.jpg') # 頁眉圖片 pic_line_file = os.path.join(os.path.dirname(__file__),'line.jpg') # 頁眉線 canvas.drawImage(pic_yemei, 75, 795, width=100,height=25) canvas.drawImage(pic_line_file, 75, 780, width=450, height=15) canvas.drawString(10*cm, cm, str(pageNumber)) canvas.restoreState() class MyDocTemplate(BaseDocTemplate): # 自定義模版類 "The document template used for all PDF documents." _invalidInitArgs = ('pageTemplates',) def __init__(self, filename, **kw): frame1 = Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1') self.allowSplitting = 0 BaseDocTemplate.__init__(self, filename, **kw) template = PageTemplate('normal', [frame1], myMainPageFrame) self.addPageTemplates(template) # 綁定全局應用 Style=getSampleStyleSheet() n = Style['Normal'] z = autoLegender(draw_bar_chart(100, 300, ['a', 'b', 'c'], [(100, 200, 120)])) pdf = MyDocTemplate('ppff.pdf') pdf.multiBuild([Paragraph('Title',n),z])