def content_latitude( c, content_title=CONTENT_TITLE_CONTENT, content_description=CONTENT_DESCRIPTION_CONTENT, content_echart = 'lines.jpg', content_page=CONTENT_PAGE_PAGE, content_page_subtitle = CONTENT_FOOTER_MODEL_CONTENT, content_page_watermarking = CONTENT_FOOTER_WATERMARKING_CONTENT, ): ''' 生成pdf内容--横向文本 纬度方向 :param c reportlab canvas 对象 object :param content_title 文本标题 :param content_echart 插入图表的图片路径 :param content_page 页脚 -- 页码 :param content_page_subtitle 页脚 -- 副标题 一般与封面的中文名称保持一致 :param content_page_watermarking 页脚 -- 水印 一般与封面的公司水印保持一致 ''' # ************** 设置背景 ************** # 设置图片的背景 c.drawImage(CONTENT_BG,0,0,width=PDF_PAGESIZE[0],height=PDF_PAGESIZE[1],mask=None) # ************** 设置标题 ******************** # 设置标题字体 c.setFont(CONTENT_TITLE_FONT,CONTENT_TITLE_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_TITLE_COLOR[0], CONTENT_TITLE_COLOR[1], CONTENT_TITLE_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_TITLE_OPACITY) # 标题 c.drawString(CONTENT_TITLE_POSITION[0],CONTENT_TITLE_POSITION[1],content_title) # ************** 插入图表 ******************** c.drawImage( content_echart, CONTENT_CHARTS_POSITION_LATITUDE[0], CONTENT_CHARTS_POSITION_LATITUDE[1], width=CONTENT_CHARTS_SIZE_LATITUDE[0], height=CONTENT_CHARTS_SIZE_LATITUDE[1], mask=None) # ************** 图表说明背景 ******************** # 填充颜色 c.setFillColorRGB(CONTENT_DESCRIPTION_BG_COLOR[0],CONTENT_DESCRIPTION_BG_COLOR[1],CONTENT_DESCRIPTION_BG_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_DESCRIPTION_BG_OPACITY) # 画矩形框 c.rect( CONTENT_DESCRIPTION_BG_POSITION_LATITUDE[0], CONTENT_DESCRIPTION_BG_POSITION_LATITUDE[1], width = CONTENT_DESCRIPTION_BG_SIZE_LATITUDE[0], height=CONTENT_DESCRIPTION_BG_SIZE_LATITUDE[1], stroke=0, fill=1 ) # ************** 图表说明描述 ******************* # 获取默认样式的字典对象 styleSheet = getSampleStyleSheet() # 获取文本的样式 style = styleSheet['BodyText'] # 设置字体 style.fontName = CONTENT_DESCRIPTION_FONT # 字体 # 设置字体大小 style.fontSize = CONTENT_DESCRIPTION_FONTSIZE # 字体大小 # 设置行间距 style.leading = CONTENT_DESCRIPTION_ROWSPACING_LATITUDE # 设置字体颜色 style.textColor = CONTENT_DESCRIPTION_COLOR # 官方文档提示 中文要有该参数 style.wordWrap = 'CJK' # 文本格式化 p =Preformatted(content_description,style,maxLineLength=CONTENT_DESCRIPTION_MAXLENGTH_LATITUDE, newLineChars='') # 指定文本区域大小 p.wrapOn(c,CONTENT_DESCRIPTION_SIZE_LATITUDE[0], CONTENT_DESCRIPTION_SIZE_LATITUDE[1]) # 绘画在画布上 p.drawOn(c, CONTENT_DESCRIPTION_POSITION_LATITUDE[0], CONTENT_DESCRIPTION_POSITION_LATITUDE[1]) # ************** 页脚---页码 ******************* # 设置标题字体 c.setFont(CONTENT_PAGE_FONT,CONTENT_PAGE_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_PAGE_COLOR[0], CONTENT_PAGE_COLOR[1], CONTENT_PAGE_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_PAGE_OPACITY) # 标题 c.drawString(CONTENT_PAGE_POSITION[0],CONTENT_PAGE_POSITION[1],str(content_page).zfill(2)) # ************** 页脚---模块 ******************* # 设置标题字体 c.setFont(CONTENT_FOOTER_MODEL_FONT,CONTENT_FOOTER_MODEL_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_FOOTER_MODEL_COLOR[0], CONTENT_FOOTER_MODEL_COLOR[1], CONTENT_FOOTER_MODEL_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_FOOTER_MODEL_OPACITY) # 标题 c.drawString(CONTENT_FOOTER_MODEL_POSITION[0],CONTENT_FOOTER_MODEL_POSITION[1],content_page_subtitle) # ************** 页脚---水印 ******************* # 设置标题字体 c.setFont(CONTENT_FOOTER_WATERMARKING_FONT,CONTENT_FOOTER_WATERMARKING_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_FOOTER_WATERMARKING_COLOR[0], CONTENT_FOOTER_WATERMARKING_COLOR[1], CONTENT_FOOTER_WATERMARKING_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_FOOTER_WATERMARKING_OPACITY) # 标题 前一个的位置+前一个的长度(字体个数*单字的像素点)+二者的间隔 c.drawString( (CONTENT_FOOTER_MODEL_POSITION[0] + len(content_page_subtitle)*CONTENT_FOOTER_WATERMARKING_FONTSIZE+CONTENT_FOOTER_WATERMARKING_INTERVAL), CONTENT_FOOTER_WATERMARKING_POSITION[1], content_page_watermarking ) return c
def content_longitude( c, content_title=CONTENT_TITLE_CONTENT, content_description=CONTENT_DESCRIPTION_CONTENT, content_echart = 'map.jpg', content_page=CONTENT_PAGE_PAGE, content_page_subtitle = CONTENT_FOOTER_MODEL_CONTENT, content_page_watermarking = CONTENT_FOOTER_WATERMARKING_CONTENT, ): ''' 生成pdf内容--纵向文本 经度方向 :param c reportlab canvas 对象 object :param content_title 文本标题 :param content_description 文本描述 :param content_echart 插入图表的图片路径 :param content_page 页脚 -- 页码 :param content_page_subtitle 页脚 -- 副标题 一般与封面的中文名称保持一致 :param content_page_watermarking 页脚 -- 水印 一般与封面的公司水印保持一致 ''' # c = canvas.Canvas("hello.pdf",pagesize=PDF_PAGESIZE) # ************** 设置背景 ************** # 设置图片的背景 c.drawImage(CONTENT_BG,0,0,width=PDF_PAGESIZE[0],height=PDF_PAGESIZE[1],mask=None) # ************** 设置标题 ******************** # 设置标题字体 c.setFont(CONTENT_TITLE_FONT,CONTENT_TITLE_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_TITLE_COLOR[0], CONTENT_TITLE_COLOR[1], CONTENT_TITLE_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_TITLE_OPACITY) # 标题 c.drawString(CONTENT_TITLE_POSITION[0],CONTENT_TITLE_POSITION[1],content_title) # ************** 插入图表 ******************** c.drawImage( content_echart, CONTENT_CHARTS_POSITION_LONGITUDE[0], CONTENT_CHARTS_POSITION_LONGITUDE[1], width=CONTENT_CHARTS_SIZE_LONGITUDE[0], height=CONTENT_CHARTS_SIZE_LONGITUDE[1], mask=None ) # ************** 图表说明背景 ******************** # 填充颜色 c.setFillColorRGB(CONTENT_DESCRIPTION_BG_COLOR[0],CONTENT_DESCRIPTION_BG_COLOR[1],CONTENT_DESCRIPTION_BG_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_DESCRIPTION_BG_OPACITY) # 画矩形框 c.rect( CONTENT_DESCRIPTION_BG_POSITION_LONGITUDE[0], CONTENT_DESCRIPTION_BG_POSITION_LONGITUDE[1], width = CONTENT_DESCRIPTION_BG_SIZE_LONGITUDE[0], height=CONTENT_DESCRIPTION_BG_SIZE_LONGITUDE[1], stroke=0, fill=1 ) # ************** 图表说明描述 ******************* # 获取默认样式的字典对象 styleSheet = getSampleStyleSheet() # 获取文本的样式 style = styleSheet['BodyText'] # 设置字体 style.fontName = CONTENT_DESCRIPTION_FONT # 字体 # 设置字体大小 style.fontSize = CONTENT_DESCRIPTION_FONTSIZE # 字体大小 # 设置行间距 style.leading = CONTENT_DESCRIPTION_ROWSPACING_LONGITUDE # 设置字体颜色 style.textColor = CONTENT_DESCRIPTION_COLOR # 官方文档提示 中文要有该参数 style.wordWrap = 'CJK' # 文本格式化 p =Preformatted(content_description,style,maxLineLength=CONTENT_DESCRIPTION_MAXLENGTH_LONGITUDE, newLineChars='') # 左下角为(0,0) 原点 所以纵向文本写入画布时会有问题 为了右上角对齐 # 纵坐标会根据文本的行数 而发生变动 变动的的纵坐标可以根据计算得出 # 文本域距下的像素 + 文本域空余的像素(文本域指定大小 - 根据文本行数计算而得的像素) = 写入文本的坐标位置 # 行数间隔的像素 = 每行字的像素 + 行与行之间的空格的像素 t_px = len(p.lines) * CONTENT_DESCRIPTION_ROWSPACING_LONGITUDE t_px = CONTENT_DESCRIPTION_POSITION_LONGITUDE[1] + 960 - t_px if t_px <= 960 else CONTENT_DESCRIPTION_POSITION_LONGITUDE[1] # 指定文本区域大小 p.wrapOn(c,CONTENT_DESCRIPTION_SIZE_LONGITUDE[0], CONTENT_DESCRIPTION_SIZE_LONGITUDE[1]) # 绘画在画布上 p.drawOn(c, CONTENT_DESCRIPTION_POSITION_LONGITUDE[0], t_px) # ************** 页脚---页码 ******************* # 设置标题字体 c.setFont(CONTENT_PAGE_FONT,CONTENT_PAGE_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_PAGE_COLOR[0], CONTENT_PAGE_COLOR[1], CONTENT_PAGE_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_PAGE_OPACITY) # 标题 c.drawString(CONTENT_PAGE_POSITION[0],CONTENT_PAGE_POSITION[1],str(content_page).zfill(2)) # ************** 页脚---模块 ******************* # 设置标题字体 c.setFont(CONTENT_FOOTER_MODEL_FONT,CONTENT_FOOTER_MODEL_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_FOOTER_MODEL_COLOR[0], CONTENT_FOOTER_MODEL_COLOR[1], CONTENT_FOOTER_MODEL_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_FOOTER_MODEL_OPACITY) # 标题 c.drawString(CONTENT_FOOTER_MODEL_POSITION[0],CONTENT_FOOTER_MODEL_POSITION[1],content_page_subtitle) # ************** 页脚---水印 ******************* # 设置标题字体 c.setFont(CONTENT_FOOTER_WATERMARKING_FONT,CONTENT_FOOTER_WATERMARKING_FONTSIZE) # 填充颜色 c.setFillColorRGB(CONTENT_FOOTER_WATERMARKING_COLOR[0], CONTENT_FOOTER_WATERMARKING_COLOR[1], CONTENT_FOOTER_WATERMARKING_COLOR[2]) # 设置透明度 c.setFillAlpha(CONTENT_FOOTER_WATERMARKING_OPACITY) # 标题 前一个的位置+前一个的长度(字体个数*单字的像素点)+二者的间隔 c.drawString( (CONTENT_FOOTER_MODEL_POSITION[0] + len(content_page_subtitle)*CONTENT_FOOTER_WATERMARKING_FONTSIZE+CONTENT_FOOTER_WATERMARKING_INTERVAL), CONTENT_FOOTER_WATERMARKING_POSITION[1], content_page_watermarking ) return c
class ParaBox(figures.Figure): """Illustrates paragraph examples, with style attributes on the left""" descrStyle = ParagraphStyle('description', fontName='Courier', fontSize=8, leading=9.6) def __init__(self, text, style, caption): figures.Figure.__init__(self, 0, 0, caption) self.text = text self.style = style self.para = Paragraph(text, style) styleText = self.getStyleText(style) self.pre = Preformatted(styleText, self.descrStyle) def wrap(self, availWidth, availHeight): """Left 30% is for attributes, right 50% for sample, 10% gutter each side.""" self.x0 = availWidth * 0.05 #left of box self.x1 = availWidth * 0.1 #left of descriptive text self.x2 = availWidth * 0.5 #left of para itself self.x3 = availWidth * 0.9 #right of para itself self.x4 = availWidth * 0.95 #right of box self.width = self.x4 - self.x0 self.dx = 0.5 * (availWidth - self.width) paw, self.pah = self.para.wrap(self.x3 - self.x2, availHeight) self.pah = self.pah + self.style.spaceBefore + self.style.spaceAfter prw, self.prh = self.pre.wrap(self.x2 - self.x1, availHeight) self.figureHeight = max(self.prh, self.pah) * 10.0/9.0 return figures.Figure.wrap(self, availWidth, availHeight) def getStyleText(self, style): """Converts style to preformatted block of text""" lines = [] for (key, value) in style.__dict__.items(): lines.append('%s = %s' % (key, value)) lines.sort() return string.join(lines, '\n') def drawFigure(self): #now we fill in the bounding box and before/after boxes self.canv.saveState() self.canv.setFillGray(0.95) self.canv.setDash(1,3) self.canv.rect(self.x2 - self.x0, self.figureHeight * 0.95 - self.pah, self.x3-self.x2, self.para.height, fill=1,stroke=1) self.canv.setFillGray(0.90) self.canv.rect(self.x2 - self.x0, #spaceBefore self.figureHeight * 0.95 - self.pah + self.para.height, self.x3-self.x2, self.style.spaceBefore, fill=1,stroke=1) self.canv.rect(self.x2 - self.x0, #spaceBefore self.figureHeight * 0.95 - self.pah - self.style.spaceAfter, self.x3-self.x2, self.style.spaceAfter, fill=1,stroke=1) self.canv.restoreState() #self.canv.setFillColor(colors.yellow) self.para.drawOn(self.canv, self.x2 - self.x0, self.figureHeight * 0.95 - self.pah) self.pre.drawOn(self.canv, self.x1 - self.x0, self.figureHeight * 0.95 - self.prh) def getStyleText(self, style): """Converts style to preformatted block of text""" lines = [] for (key, value) in style.__dict__.items(): if key not in ('name','parent'): lines.append('%s = %s' % (key, value)) return string.join(lines, '\n')
def onPage(canvas, doc, da=None, a=None): width, height = canvas._doctemplate.pagesize canvas.saveState() fattura = doc.fatture[doc.fattura_corrente] if da is None: da = fattura.emessa_da if a is None: a = fattura.emessa_a fatturazione = FATTURE_PER_TIPO[fattura.tipo] stondata_style = ParagraphStyle("IntestazioneStondata", fontName='Helvetica', fontSize=8, leading=10, borderRadius=5, borderWidth=1, borderColor=colors.silver, borderPadding=5) a_style = ParagraphStyle("Titolo della fattura", fontName='Helvetica', fontSize=8, leading=10) tipo = fattura.tipo # set PDF properties *************** canvas.setFont('Helvetica', 8) canvas.setAuthor(settings.LICENSE_OWNER) canvas.setCreator('TaM v.%s' % settings.TAM_VERSION) canvas._doc.info.producer = ('TaM invoices') canvas.setSubject(u"%s" % fattura.nome_fattura()) if tipo == '3': nome = 'Ricevuta servizio TAXI' else: nome = 'Fattura' # Fatture consorzio e conducente si chiamano semplicemente FATTURA descrittoreFattura = u"%s %s" % (nome, fattura.descrittore()) canvas.setTitle(descrittoreFattura) # Header *************** y = height - doc.topMargin x = doc.leftMargin if test: canvas.setLineWidth(1) p = canvas.beginPath() p.moveTo(0, y) p.lineTo(width, y) canvas.drawPath(p) if fatturazione.mittente == "consorzio": logo_height = 2.5 * cm y -= logo_height canvas.drawImage(logoImage_path, x=x, y=y, width=7 * cm, height=logo_height) descrittore = Paragraph( '<font size="14"><b>%s</b></font> del %s' % (descrittoreFattura, localize(fattura.data)), a_style) descrittore.wrapOn(canvas, width / 2, y) descrittore.drawOn(canvas, x=x, y=y - descrittore.height) y -= descrittore.height + 10 if fatturazione.mittente == "conducente": # nelle fatture conducente metto il mittente a sinistra fattura_da = Paragraph(da.strip().replace('\n', '<br/>'), a_style) fattura_da.wrapOn(canvas, 6.5 * cm, 10 * cm) fattura_da.drawOn(canvas, x, y - fattura_da.height) y -= fattura_da.height y -= 0.2 * cm # spacer tra mittente e destinatario if fattura.note: note = Preformatted(fattura.note, a_style) note.wrapOn(canvas, width / 2, 10 * cm) y = y - note.height - 8 note.drawOn(canvas, 1 * cm, y=y) note_fisse = fattura.note_fisse() if note_fisse: # le vecchie ricevute hanno l'indicazione di servizio emodializzato y = y - 10 testata_fissa = Paragraph("<font size='6'>%s</font>" % note_fisse, a_style) testata_fissa.wrapOn(canvas, width / 2, 2 * cm) y = y - testata_fissa.height testata_fissa.drawOn(canvas, x, y) left_y = y - 8 # spacer finale if test: p = canvas.beginPath() p.moveTo(0, y) p.lineTo(width / 2, y) canvas.drawPath(p) # faccio la seconda colonna (destra) dell'header y = height - doc.topMargin x = width - 8 * cm if not fatturazione.mittente == "conducente": # nelle fatture conducente ho messo già il conducente a sinistra fattura_da = Paragraph(da.strip().replace('\n', '<br/>'), a_style) fattura_da.wrapOn(canvas, 6.5 * cm, 10 * cm) fattura_da.drawOn(canvas, x, y - fattura_da.height) y -= fattura_da.height y -= 0.1 * cm # spacer tra mittente e destinatario fattura_a = Paragraph(a.replace('\n', '<br/>'), stondata_style) fattura_a.wrapOn(canvas, 6.5 * cm, 10 * cm) fattura_a.drawOn(canvas, x, y - fattura_a.height - fattura_a.style.borderPadding) y -= fattura_a.height + fattura_a.style.borderPadding * 2 # spazio finale right_y = y lower_y = min(left_y, right_y) y = lower_y if test: p = canvas.beginPath() p.moveTo(width / 2, y) p.lineTo(width, y) canvas.drawPath(p) note_finali_lines = [] for footer_row in fattura.footer(): note_finali_lines.append(footer_row) note_finali = Paragraph("<br/>".join(note_finali_lines), normalStyle) note_finali.wrap(width - doc.rightMargin - doc.leftMargin, 5 * cm) note_finali.drawOn(canvas, doc.leftMargin, doc.bottomMargin) # linea sotto l'intestazione canvas.setLineWidth(1) p = canvas.beginPath() p.moveTo(doc.leftMargin, y) p.lineTo(width - doc.rightMargin, y) canvas.drawPath(p) doc.pageTemplate.frames = [ Frame(doc.leftMargin, doc.bottomMargin + note_finali.height, width - (doc.leftMargin + doc.rightMargin), y - doc.bottomMargin - note_finali.height, showBoundary=test), # x,y, width, height ] canvas.setLineWidth(0.3) p = canvas.beginPath() p.moveTo(doc.leftMargin, doc.bottomMargin) p.lineTo(width - doc.rightMargin, doc.bottomMargin) canvas.drawPath(p) canvas.restoreState()
class ParaBox(figures.Figure): """Illustrates paragraph examples, with style attributes on the left""" descrStyle = ParagraphStyle('description', fontName='Courier', fontSize=8, leading=9.6) def __init__(self, text, style, caption): figures.Figure.__init__(self, 0, 0, caption) self.text = text self.style = style self.para = Paragraph(text, style) styleText = self.getStyleText(style) self.pre = Preformatted(styleText, self.descrStyle) def wrap(self, availWidth, availHeight): """Left 30% is for attributes, right 50% for sample, 10% gutter each side.""" self.x0 = availWidth * 0.05 #left of box self.x1 = availWidth * 0.1 #left of descriptive text self.x2 = availWidth * 0.5 #left of para itself self.x3 = availWidth * 0.9 #right of para itself self.x4 = availWidth * 0.95 #right of box self.width = self.x4 - self.x0 self.dx = 0.5 * (availWidth - self.width) paw, self.pah = self.para.wrap(self.x3 - self.x2, availHeight) self.pah = self.pah + self.style.spaceBefore + self.style.spaceAfter prw, self.prh = self.pre.wrap(self.x2 - self.x1, availHeight) self.figureHeight = max(self.prh, self.pah) * 10.0 / 9.0 return figures.Figure.wrap(self, availWidth, availHeight) def getStyleText(self, style): """Converts style to preformatted block of text""" lines = [] for (key, value) in style.__dict__.items(): lines.append('%s = %s' % (key, value)) lines.sort() return string.join(lines, '\n') def drawFigure(self): #now we fill in the bounding box and before/after boxes self.canv.saveState() self.canv.setFillGray(0.95) self.canv.setDash(1, 3) self.canv.rect(self.x2 - self.x0, self.figureHeight * 0.95 - self.pah, self.x3 - self.x2, self.para.height, fill=1, stroke=1) self.canv.setFillGray(0.90) self.canv.rect( self.x2 - self.x0, #spaceBefore self.figureHeight * 0.95 - self.pah + self.para.height, self.x3 - self.x2, self.style.spaceBefore, fill=1, stroke=1) self.canv.rect( self.x2 - self.x0, #spaceBefore self.figureHeight * 0.95 - self.pah - self.style.spaceAfter, self.x3 - self.x2, self.style.spaceAfter, fill=1, stroke=1) self.canv.restoreState() #self.canv.setFillColor(colors.yellow) self.para.drawOn(self.canv, self.x2 - self.x0, self.figureHeight * 0.95 - self.pah) self.pre.drawOn(self.canv, self.x1 - self.x0, self.figureHeight * 0.95 - self.prh) def getStyleText(self, style): """Converts style to preformatted block of text""" lines = [] for (key, value) in style.__dict__.items(): if key not in ('name', 'parent'): lines.append('%s = %s' % (key, value)) return string.join(lines, '\n')
def onPage(canvas, doc, da=None, a=None): width, height = canvas._doctemplate.pagesize canvas.saveState() fattura = doc.fatture[doc.fattura_corrente] if da is None: da = fattura.emessa_da if a is None: a = fattura.emessa_a fatturazione = FATTURE_PER_TIPO[fattura.tipo] stondata_style = ParagraphStyle("IntestazioneStondata", fontName='Helvetica', fontSize=8, leading=10, borderRadius=5, borderWidth=1, borderColor=colors.silver, borderPadding=5) a_style = ParagraphStyle("Titolo della fattura", fontName='Helvetica', fontSize=8, leading=10) tipo = fattura.tipo # set PDF properties *************** canvas.setFont('Helvetica', 8) canvas.setAuthor(settings.LICENSE_OWNER) canvas.setCreator('TaM v.%s' % settings.TAM_VERSION) canvas._doc.info.producer = ('TaM invoices') canvas.setSubject(u"%s" % fattura.nome_fattura()) nome = fattura.custom_name descrittoreFattura = u"%s %s" % (nome, fattura.descrittore()) canvas.setTitle(descrittoreFattura) # Header *************** y = height - doc.topMargin x = doc.leftMargin if test: canvas.setLineWidth(1) p = canvas.beginPath() p.moveTo(0, y) p.lineTo(width, y) canvas.drawPath(p) if fatturazione.mittente == "consorzio": logo_height = 2.5 * cm y -= logo_height canvas.drawImage(logoImage_path, x=x, y=y, width=7 * cm, height=logo_height) descrittore = Paragraph( '<font size="14"><b>%s</b></font> del %s' % (descrittoreFattura, localize(fattura.data)), a_style) descrittore.wrapOn(canvas, width / 2, y) descrittore.drawOn(canvas, x=x, y=y - descrittore.height) y -= descrittore.height + 10 if fatturazione.mittente == "conducente": # nelle fatture conducente metto il mittente a sinistra fattura_da = Paragraph(da.strip().replace('\n', '<br/>'), a_style) fattura_da.wrapOn(canvas, 6.5 * cm, 10 * cm) fattura_da.drawOn(canvas, x, y - fattura_da.height) y -= fattura_da.height y -= 0.2 * cm # spacer tra mittente e destinatario if fattura.note: note = Preformatted(fattura.note, a_style) note.wrapOn(canvas, width / 2, 10 * cm) y = y - note.height - 8 note.drawOn(canvas, 1 * cm, y=y) note_fisse = fattura.note_fisse() if note_fisse: # le vecchie ricevute hanno l'indicazione di servizio emodializzato y = y - 10 testata_fissa = Paragraph("<font size='6'>%s</font>" % note_fisse, a_style) testata_fissa.wrapOn(canvas, width / 2, 2 * cm) y = y - testata_fissa.height testata_fissa.drawOn(canvas, x, y) left_y = y - 8 # spacer finale if test: p = canvas.beginPath() p.moveTo(0, y) p.lineTo(width / 2, y) canvas.drawPath(p) # faccio la seconda colonna (destra) dell'header y = height - doc.topMargin x = width - 8 * cm if not fatturazione.mittente == "conducente": # nelle fatture conducente ho messo già il conducente a sinistra fattura_da = Paragraph(da.strip().replace('\n', '<br/>'), a_style) fattura_da.wrapOn(canvas, 6.5 * cm, 10 * cm) fattura_da.drawOn(canvas, x, y - fattura_da.height) y -= fattura_da.height y -= 0.1 * cm # spacer tra mittente e destinatario fattura_a = Paragraph(a.replace('\n', '<br/>'), stondata_style) fattura_a.wrapOn(canvas, 6.5 * cm, 10 * cm) fattura_a.drawOn(canvas, x, y - fattura_a.height - fattura_a.style.borderPadding) y -= fattura_a.height + fattura_a.style.borderPadding * 2 # spazio finale right_y = y lower_y = min(left_y, right_y) y = lower_y if test: p = canvas.beginPath() p.moveTo(width / 2, y) p.lineTo(width, y) canvas.drawPath(p) note_finali_lines = [] for footer_row in fattura.footer(): note_finali_lines.append(footer_row) note_finali = Paragraph("<br/>".join(note_finali_lines), normalStyle) note_finali.wrap(width - doc.rightMargin - doc.leftMargin, 5 * cm) note_finali.drawOn(canvas, doc.leftMargin, doc.bottomMargin) # linea sotto l'intestazione canvas.setLineWidth(1) p = canvas.beginPath() p.moveTo(doc.leftMargin, y) p.lineTo(width - doc.rightMargin, y) canvas.drawPath(p) doc.pageTemplate.frames = [ Frame(doc.leftMargin, doc.bottomMargin + note_finali.height, width - (doc.leftMargin + doc.rightMargin), y - doc.bottomMargin - note_finali.height, showBoundary=test), # x,y, width, height ] canvas.setLineWidth(0.3) p = canvas.beginPath() p.moveTo(doc.leftMargin, doc.bottomMargin) p.lineTo(width - doc.rightMargin, doc.bottomMargin) canvas.drawPath(p) canvas.restoreState()
def pdf(path, start_time, end_time): # 读取文件 以及背景图 生成的gantt图以及生成的table gantt_width, gantt_height = Image.open(GANTT_BG).size table_width, table_height = Image.open(TABLE_BG).size # 设置pdf画布的大小 默认宽是1920 超过1920的 即俩个图最大的宽度 + 外边框(左右图边距均为160) bigger_width = max([gantt_width, table_width]) bigger_width = bigger_width if bigger_width > DEFAULT_WIDTH else DEFAULT_WIDTH gantt_height = ceil((bigger_width / gantt_width) * gantt_height) table_height = ceil((bigger_width / table_width) * table_height) page_width = bigger_width + 4 * PAGE_MARGIN title_image = Image.open(TITLE_BG) title_width, title_height = title_image.size title_width = page_width resize_precent = title_width / 1920 title_height = ceil(resize_precent * title_height) # print(title_height) page_height = title_height + (80 + gantt_height + 80 + 200) + (80 + table_height + 80 + 10 + 200) c = canvas.Canvas(path, pagesize=(page_width, page_height)) c.setFillColorRGB(PAGE_BG_COLOR[0], PAGE_BG_COLOR[1], PAGE_BG_COLOR[2]) # 给画布添加背景色 c.rect(0, 0, width=page_width, height=page_height, stroke=0, fill=1) # 从左下角的原点坐标开始画起 # 设置table区域 背景色为白色 c.setFillColorRGB(1, 1, 1) c.rect(80, 80, width=bigger_width + 2 * 80, height=table_height + 80 + 10 + 200, stroke=0, fill=1) # 画出table的图片 c.drawImage(TABLE_BG, 160, 160, width=bigger_width, height=table_height, mask=None) # 设置分割符号 c.setFillColorRGB(PAGE_BG_COLOR[0], PAGE_BG_COLOR[1], PAGE_BG_COLOR[2]) c.rect(150, 160 + table_height, width=bigger_width + 20, height=10, stroke=0, fill=1) # 设置table 标题 # 设置字体以及字体大小 c.setFont('hei', 80) c.drawString(150, 160 + table_height + 10 + 60, '项目周报详情') c.setFont('hei', 30) c.drawString(bigger_width + 20 + 80 + 75 - 505, table_height + 80 + 10 + 200 + 80 - 130, f'周报日期:{start_time} ~ {end_time}') # 设置gantt图 # 设置gantt区域 背景色为白色 c.setFillColorRGB(1, 1, 1) c.rect(80, 80 + table_height + 80 + 10 + 200 + 80, width=bigger_width + 2 * 80, height=gantt_height + 80 + 200, stroke=0, fill=1) # 画出gantt图的图片 c.drawImage(GANTT_BG, 160, 80 + table_height + 80 + 10 + 200 + 80 + 80, width=bigger_width, height=gantt_height, mask=None) # 设置分割符号 c.setFillColorRGB(PAGE_BG_COLOR[0], PAGE_BG_COLOR[1], PAGE_BG_COLOR[2]) c.rect(150, 80 + table_height + 80 + 10 + 200 + 80 + 80 + gantt_height, width=bigger_width + 20, height=10, stroke=0, fill=1) # gantt图图片 c.setFont('hei', 80) c.drawString( 150, 80 + table_height + 80 + 10 + 200 + 80 + gantt_height + 80 + 80, '项目进度图') # 设置title c.drawImage(TITLE_BG, 0, 80 + table_height + 80 + 10 + 200 + 80 + gantt_height + 80 + 200, width=title_width, height=title_height) # 绘制时间 # 获取默认样式的字典对象 styleSheet = getSampleStyleSheet() # 获取文本的样式 style = styleSheet['BodyText'] # 设置字体 style.fontName = 'hei' # 字体 # 设置字体大小 style.fontSize = ceil(resize_precent * 60) # 字体大小 # 设置行间距 style.leading = ceil(resize_precent * 70) # 设置字体颜色 style.textColor = PAGE_BG_COLOR # 官方文档提示 中文要有该参数 style.wordWrap = 'CJK' # 文本格式化 text = f''' {start_time} / {end_time} ''' p = Preformatted(text, style, newLineChars='') # 指定文本区域大小 p.wrapOn(c, 321, 224) # 绘画在画布上 time_position_x = ceil(1400 / 1920 * page_width) time_position_y = ceil(129 / 482 * title_height) + ( 80 + gantt_height + 80 + 200) + (80 + table_height + 80 + 10 + 200) p.drawOn(c, time_position_x, time_position_y) c.showPage() c.save()