列印報表
報表列印是程式設計師的痛, 難寫又難調整. 在此本篇提供一個方式, 將要列印的資料先寫入pdf檔案進行編排, 然後再將整個pdf檔案列出
要讓Python能讀取寫入pdf, 需安裝reportlab套件, 此套件適用於Windows及Ubuntu
Windows : pip install reportlab Linux : sudo pip3 install reportlab
import
開頭需先 import一些常用的套件, 如下
import copy import time from reportlab.lib import utils from reportlab.lib.enums import TA_JUSTIFY, TA_CENTER, TA_LEFT from reportlab.lib.pagesizes import letter from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, PageBreak, Table, TableStyle from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib import colors from reportlab.graphics.shapes import Drawing from reportlab.graphics.charts.lineplots import LinePlot from reportlab.graphics.widgets.markers import makeMarker from reportlab.lib.units import inch import reportlab.rl_config reportlab.rl_config.warnOnMissingFontGlyphs = 0 from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfgen import canvas from reportlab.lib import fonts import platform from datetime import datetime
字型
Windows跟Linux的字型存放位置不一樣, 所以需先使用 platform.system()判斷作業系統, 再使用pdfmetrics.registerFont()註冊字型的位置
useros=platform.system() if useros == "Linux": pdfmetrics.registerFont(TTFont('hei', '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc')) else: pdfmetrics.registerFont(TTFont('hei', 'simsun.ttc'))
SimpleDocTemplate
接下來使用 SimpleDocTemplate產生一個文件檔doc, 參數需傳入檔案名稱及紙張格式(A4, A5…)
doc = SimpleDocTemplate("tmp.pdf", pagesize=letter, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18)
內容
doc裏要包含的內容及格式, 使用 list 容器儲存, 此例使用 story變數. 然後再使用 doc.build(story)將資料放入 doc裏並儲存成檔案
story = [] story.append(Paragraph('富立金履歷管制系統', style_title)) story.append(Spacer(1, 15)) doc.build(story)
內容可以包含Title, 段落, 表格, 圖片等資訊, 將分別說明如下
表格
表格裏要列印的資料, 先使用二維list儲存, 再將資料使用Table置入. 表格常用的格式有FONTNAME : 字型名稱
FONTSIZE : 字型大小
GRID : 外框線
BOX : 內框線
SPAN : 要合併的儲存格
VALIGN : 垂直對齊方式, 有 TOP, MIDDLE, BOTTOM三種
每一個儲存格都有其座標, 座標格式為(行, 列), 左上角為(0,0), 第一列往右依序為(1, 0), (2, 0), (3, 0). 右下角的座標除了使用行列外, 亦可使用負數表示, 最右下角座標為(-1,-1)
data=[ ['尺寸', info['dimension']], ['顏色', info['color']], ['版號', info['version']], ['半打', '{0}(KG)'.format(info['wetHalfDozen']),'一打', '{0}(KG)'.format(info['wetDozen'])], ['淨重', '{0}'.format(info['net'])], ['數量', '{0}打 {1}雙'.format(info['qtyDozen'], info['qtyPair'])] ] t = Table(data, colWidths=[70, 150, 70, 150], rowHeights=[80,80,80,80,80, 80], style=[ ('FONTNAME', (0, 0), (-1, -1), 'hei'), ('FONTSIZE', (0, 0), (-1, -1), 20), ('GRID', (0, 0), (-1, -1), 1, colors.black), ('BOX', (0, 0), (-1, -1), 2, colors.black), ('SPAN', (1, 0), (3, 0)), ('SPAN', (1, 1), (3, 1)), ('SPAN', (1, 2), (3, 2)), ('SPAN', (1, 4), (3, 4)), ('SPAN', (1, 5), (3, 5)), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ]) story.append(t)
完整代碼如下
import copy import time from reportlab.lib import utils from reportlab.lib.enums import TA_JUSTIFY, TA_CENTER, TA_LEFT from reportlab.lib.pagesizes import letter from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, PageBreak, Table, TableStyle from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib import colors from reportlab.graphics.shapes import Drawing from reportlab.graphics.charts.lineplots import LinePlot from reportlab.graphics.widgets.markers import makeMarker from reportlab.lib.units import inch import reportlab.rl_config reportlab.rl_config.warnOnMissingFontGlyphs = 0 from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfgen import canvas from reportlab.lib import fonts import platform from datetime import datetime class ResumeLabel(): def __init__(self, info): useros=platform.system() if useros == "Linux": pdfmetrics.registerFont(TTFont('hei', '/usr/share/fonts-droid-fallback/truetype/DroidSansFallback.ttf')) else: pdfmetrics.registerFont(TTFont('hei', 'simsun.ttc')) fonts.addMapping('song', 1, 0, 'hei') fonts.addMapping('song', 1, 1, 'hei') stylesheet = getSampleStyleSheet() normalStyle = copy.deepcopy(stylesheet['Normal']) normalStyle.fontName ='hei' normalStyle.fontSize = 20 doc = SimpleDocTemplate("tmp.pdf", pagesize=letter, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18) story = [] styles = getSampleStyleSheet() styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY)) style_title = ParagraphStyle('parrafos', alignment = TA_CENTER, fontSize = 24, fontName="hei") style_left = ParagraphStyle('parrafos', alignment = TA_LEFT, fontSize = 12, fontName="hei") story.append(Paragraph('Mahal履歷管制系統', style_title)) story.append(Spacer(1, 15)) img=Image("tmp.png", 2*inch, 0.5*inch) story.append(img) story.append(Paragraph(info["barcode"], style_title)) story.append(Spacer(1, 12)) story.append(Paragraph('Date : {0}'.format(datetime.now().strftime("%Y-%m-%d %H:%M:%S")), style_left)) story.append(Spacer(1, 12)) data=[ ['尺寸', info['dimension']], ['顏色', info['color']], ['版號', info['version']], ['半打', '{0}(KG)'.format(info['wetHalfDozen']),'一打', '{0}(KG)'.format(info['wetDozen'])], ['淨重', '{0}'.format(info['net'])], ['數量', '{0}打 {1}雙'.format(info['qtyDozen'], info['qtyPair'])] ] t = Table(data, colWidths=[70, 150, 70, 150], rowHeights=[80,80,80,80,80, 80], style=[ ('FONTNAME', (0, 0), (-1, -1), 'hei'), ('FONTSIZE', (0, 0), (-1, -1), 20), ('GRID', (0, 0), (-1, -1), 1, colors.black), ('BOX', (0, 0), (-1, -1), 2, colors.black), ('SPAN', (1, 0), (3, 0)), ('SPAN', (1, 1), (3, 1)), ('SPAN', (1, 2), (3, 2)), ('SPAN', (1, 4), (3, 4)), ('SPAN', (1, 5), (3, 5)), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ]) story.append(t) doc.build(story)
todo