# coding: utf-8 from decimal import Decimal from lxml import etree, objectify from reportlab.lib import colors from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib.units import inch, mm from reportlab.pdfgen import canvas from reportlab.platypus import Paragraph, Table, TableStyle from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont ######################################################################## class PDFOrder(object): """""" # ---------------------------------------------------------------------- def __init__(self, xml_file, pdf_file): """Constructor""" self.xml_file = xml_file self.pdf_file = pdf_file self.xml_obj = self.getXMLObject() # ---------------------------------------------------------------------- def coord(self, x, y, unit=1): """ # http://stackoverflow.com/questions/4726011/wrap-text-in-a-table-reportlab Вспомогательный класс для позиционирования в объектах Canvas """ x, y = x * unit, self.height - y * unit return x, y # ---------------------------------------------------------------------- def createPDF(self): """ Создаём PDF на основании XML данных """ self.canvas = canvas.Canvas(self.pdf_file, pagesize=letter) pdfmetrics.registerFont(TTFont('FreeSans', 'FreeSans.ttf')) self.canvas.setFont('FreeSans', 32) # self.canvas.setFont('Times-Roman', 20) width, self.height = letter styles = getSampleStyleSheet() xml = self.xml_obj address = str(""" Доставка:
ewdewfewfйцуцйу
%s
%s
%s
%s
""") % (xml.address1, xml.address2, xml.address3, xml.address4) p = Paragraph(address, styles["Normal"]) p.wrapOn(self.canvas, width, self.height) p.drawOn(self.canvas, *self.coord(18, 40, mm)) order_number = 'Order #%s ' % xml.order_number p = Paragraph(order_number, styles["Normal"]) p.wrapOn(self.canvas, width, self.height) p.drawOn(self.canvas, *self.coord(18, 50, mm)) data = [] data.append(["Item ID", "Name", "Price", "Quantity", "Total"]) grand_total = 0 for item in xml.order_items.iterchildren(): row = [] row.append(item.id) row.append(item.name) row.append(item.price) row.append(item.quantity) total = Decimal(str(item.price)) * Decimal(str(item.quantity)) row.append(str(total)) grand_total += total data.append(row) data.append(["", "", "", "Grand Total:", grand_total]) t = Table(data, 1.5 * inch) t.setStyle(TableStyle([ ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), ('BOX', (0,0), (-1,-1), 0.25, colors.black) ])) t.wrapOn(self.canvas, width, self.height) t.drawOn(self.canvas, *self.coord(18, 85, mm)) txt = "Thank you for your business!" p = Paragraph(txt, styles["Normal"]) p.wrapOn(self.canvas, width, self.height) p.drawOn(self.canvas, *self.coord(18, 95, mm)) # ---------------------------------------------------------------------- def getXMLObject(self): """ Открываем XML документ и возвращаем lxml XML документ """ with open(self.xml_file) as f: xml = f.read() return objectify.fromstring(xml) #---------------------------------------------------------------------- def savePDF(self): """ Сохраняем PDF """ self.canvas.save() #---------------------------------------------------------------------- if __name__ == "__main__": xml = "order.xml" pdf = "letter.pdf" doc = PDFOrder(xml, pdf) doc.createPDF() doc.savePDF()