def testIt(self): "This makes one long multi-page paragraph." # Build story. story = [] styleSheet = getSampleStyleSheet() h1 = styleSheet['Heading1'] h1.pageBreakBefore = 1 h1.keepWithNext = 1 h2 = styleSheet['Heading2'] h2.frameBreakBefore = 1 h2.keepWithNext = 1 h3 = styleSheet['Heading3'] h3.backColor = colors.cyan h3.keepWithNext = 1 bt = styleSheet['BodyText'] story.append(Paragraph(""" This tests ability to alternate left and right templates. We start on a plain one. The next page should display a left-side template, with a big inner margin and staple-like holes on the right.""",style=bt)) story.append(NextPageTemplate(['left','right'])) story.append(Paragraph(""" One can specify a list of templates instead of a single one in order to sequence through them.""",style=bt)) def doSome(): for i in range(10): story.append(Paragraph('Heading 1 always starts a new page (%d)' % len(story), h1)) for j in range(3): story.append(Paragraph('Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) story.append(Paragraph('Heading 2 always starts a new frame (%d)' % len(story), h2)) story.append(Paragraph('Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) for j in range(3): story.append(Paragraph(randomText(theme=PYTHON, sentences=2)+' (%d)' % len(story), bt)) story.append(Paragraph('I should never be at the bottom of a frame (%d)' % len(story), h3)) story.append(Paragraph(randomText(theme=PYTHON, sentences=1)+' (%d)' % len(story), bt)) doSome() story.append(NextPageTemplate('plain')) story.append(Paragraph('Back to plain old page template',h1)) story.append(Paragraph('Back to plain old formatting', bt)) story.append(Paragraph("""use a template name of * to indicate where the iteration should restart""",style=bt)) story.append(NextPageTemplate(['left','*','right'])) doSome() #doc = MyDocTemplate(outputfile('test_platypus_leftright.pdf')) doc = MyDocTemplate(outputfile('test_platypus_leftright.pdf')) doc.multiBuild(story)
def AddStoryElement(self, element): if element.tag == "para": styleName = element.get("style", "default") style = self.paragraphStyles[styleName] element.attrib.clear() text = cElementTree.tostring(element) rotated = self._ConvertNumber(element, "rotate", 0) cls = RotatedParagraph if rotated else Paragraph para = cls(text, style) self.story.append(para) elif element.tag == "nextPage": self.story.append(PageBreak()) elif element.tag == "nextFrame": self.story.append(FrameBreak()) elif element.tag == "spacer": length = self._ConvertNumber(element, "length", 0) self.story.append(Spacer(length, length)) elif element.tag == "setNextTemplate": name = element.attrib["name"] self.story.append(NextPageTemplate(name)) elif element.tag == "blockTable": styleName = element.get("style", "default") style = self.tableStyles[styleName] if self.tableCommands: style = TableStyle(self.tableCommands, style) repeatRows = self._ConvertNumber(element, "repeatRows", 0) hAlign = element.get("hAlign", "CENTER") vAlign = element.get("vAlign", "MIDDLE") columnWidths = self._ConvertNumberList(element, "colWidths", []) pageRows = self._ConvertNumber(element, "pageRows") if not pageRows: self.story.append( LongTable(self.tableRows, columnWidths, self.tableRowHeights, style=style, hAlign=hAlign, vAlign=vAlign, repeatRows=repeatRows)) else: headerRows = self.tableRows[:repeatRows] headerRowHeights = self.tableRowHeights[:repeatRows] rows = self.tableRows[repeatRows:] rowHeights = self.tableRowHeights[repeatRows:] while rows: table = LongTable(headerRows + rows[:pageRows], columnWidths, headerRowHeights + rowHeights[:pageRows], style=style, hAlign=hAlign, vAlign=vAlign) self.story.append(table) rows = rows[pageRows:] rowHeights = rowHeights[pageRows:]
def renderElements(elements, filesuffix=None, tmpdir=None): """ takes a list of reportlab flowables and renders them to a test.pdf file""" margin = 2 * cm if filesuffix: fn = 'test_' + filesuffix + '.pdf' else: fn = 'test.pdf' fn = os.path.join(tmpdir, fn) doc = BaseDocTemplate(fn, topMargin=margin, leftMargin=margin, rightMargin=margin, bottomMargin=margin) pt = WikiPage("Title") doc.addPageTemplates(pt) elements.insert(0, NextPageTemplate('Title')) doc.build(elements)
def story(self): """Return report as a list ready to be passed to MyDocTemplate multiBuild method.""" tree = RenderTree(self) story = [ Paragraph("<seqreset id='h1'/>", PARAGRAPH_STYLES['Normal']), NextPageTemplate('ContentPage'), PageBreak(), Paragraph('<b>Table of Contents</b>', PARAGRAPH_STYLES['centered']), TableOfContents(levelStyles=PARAGRAPH_STYLES['TOCHeadings']), PageBreak() ] for row in list(tree)[1:]: elements = list(row.node.elements.values()) flowables = list(chain(*elements)) story += flowables return story
def testAutoPageTemplate(self): from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin from reportlab.lib.units import inch class onPage: def __init__(self,label): self.label = label def __call__(self,canv,doc): canv.drawString(72,72,'This is pageTemplate(%s)' % (self.label,)) class MyDocTemplate(BaseDocTemplate): _invalidInitArgs = ('pageTemplates',) def __init__(self, filename, **kw): self.allowSplitting = 0 BaseDocTemplate.__init__(self, filename, **kw) self.addPageTemplates( [ PageTemplate('normal', [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], onPage = onPage('normal'), ), PageTemplate('auto', [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], onPage = onPage('auto'), autoNextPageTemplate = 'autoFollow', ), PageTemplate('autoFollow', [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], onPage = onPage('autoFollow'), ), ]) styleSheet = getSampleStyleSheet() normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal']) story =[] a = story.append a(Paragraph('should be on page template normal', normal)) a(NextPageTemplate('auto')) a(PageBreak()) a(Paragraph('should be on page template auto', normal)) a(PageBreak()) a(DocAssert('doc.pageTemplate.id=="autoFollow"','expected doc.pageTemplate.id=="autoFollow"')) a(Paragraph('should be on page template autoFollow 1', normal)) a(PageBreak()) a(Paragraph('should be on page template autoFollow 2', normal)) doc = MyDocTemplate(outputfile('test_platypus_paragraphs_AutoNextPageTemplate.pdf')) doc.build(story)
def wrap(self, aW, aH): frame = self._frame from reportlab.platypus.doctemplate import NextPageTemplate, CurrentFrameFlowable, LayoutError G = [NextPageTemplate(self.nextTemplate)] if aH < self.gap + self.required - _FUZZ: #we are going straight to the nextTemplate with no attempt to modify the frames G.append(PageBreak()) else: #we are going to modify the incoming templates templates = self._doctemplateAttr('pageTemplates') if templates is None: raise LayoutError('%s called in non-doctemplate environment' % self.identity()) T = [t for t in templates if t.id == self.nextTemplate] if not T: raise LayoutError('%s.nextTemplate=%s not found' % (self.identity(), self.nextTemplate)) T = T[0] F = [f for f in T.frames if f.id in self.nextFrames] N = [f.id for f in F] N = [f for f in self.nextFrames if f not in N] if N: raise LayoutError( '%s frames=%r not found in pageTemplate(%s)\n%r has frames %r' % (self.identity(), N, T.id, T, [f.id for f in T.frames])) T = self._doctemplateAttr('pageTemplate') def unwrap(canv, doc, T=T, onPage=T.onPage, oldFrames=T.frames): T.frames = oldFrames T.onPage = onPage onPage(canv, doc) T.onPage = unwrap h = aH - self.gap for i, f in enumerate(F): f = copy(f) f.height = h f._reset() F[i] = f T.frames = F G.append(CurrentFrameFlowable(F[0].id)) frame.add_generated_content(*G) return 0, 0
def make_invoice(fp, purchase, org, pgnum, tickets, **kw): """ make pdf invoice. Should be called with the same parameters as the render_template with the html template. """ doc = BaseDocTemplate(fp, pagesize=A4) styles = getSampleStyleSheet() args = dict(date=purchase.date[0], rcptaddr=[purchase.buyerName[0]], senderaddr=[org.name[0]], orgnum=org.orgnum[0], fskatt=org.fskatt[0], kind=purchase.kind[0], ocr=purchase.ocr[0], conditions='30 dagar netto', latefee=u'Efter förfallodatum debiteras ' u'dröjsmålsränta enligt räntelagen.', total=purchase.total[0], pgnum=pgnum, styles=styles) qrcode = { 'uqr': 1, 'tp': 1, 'nme': org.name[0], 'cid': org.orgnum[0], 'idt': time.strftime('%Y%m%d', time.localtime(purchase.date[0])), 'iref': purchase.ocr[0], 'due': str(purchase.total[0]), 'pt': 'PG', 'acc': pgnum[:-1] + '-' + pgnum[-1:] } if purchase.buyerAddress: args['rcptaddr'] += purchase.buyerAddress[0].split('\n') if org.address: args['senderaddr'] += org.address[0].split('\n') if org.phone: args['phone'] = org.phone[0] if org.email: args['email'] = org.email[0] if org.url: args['url'] = org.url[0] if org.seat: args['seat'] = org.seat[0] if org.vatnum: args['vatnum'] = org.vatnum[0] if purchase.buyerReference: args['buyerref'] = purchase.buyerReference[0] if purchase.buyerAnnotation: args['annotation'] = purchase.buyerAnnotation[0].split('\n') for (code, pct, value) in purchase.vat: qrcode[{'10': 'vh', '11': 'vm', '12': 'vl'}[code]] = str(value) try: args['expiryDate'] = purchase.expiryDate[0] qrcode['ddt'] = time.strftime('%Y%m%d', time.localtime(purchase.expiryDate[0])) except (AttributeError, IndexError): qrcode['ddt'] = time.strftime('%Y%m%d') args['qrcode'] = json.dumps(qrcode) tmpl = InvoiceTemplate(name='invoice', **args) tmpl2 = Invoice2Template(name='invoice2', **args) doc.addPageTemplates([tmpl, tmpl2]) elements = [NextPageTemplate('invoice'), NextPageTemplate('invoice2')] indentedsmallstyle = ParagraphStyle('Small', fontName='Helvetica', fontSize=8, leading=9, leftIndent=5 * mm) boldstyle = ParagraphStyle('Bold', fontName='Helvetica-Bold', fontSize=10, leading=12) boldrightstyle = ParagraphStyle('Bold', fontName='Helvetica-Bold', fontSize=10, leading=12, alignment=TA_RIGHT) mycellstyle = CellStyle('mycellstyle') mycellstyle.topPadding = mycellstyle.bottomPadding = 0 tabledata = [ Table( [[ Paragraph(_('Item'), boldstyle), Paragraph(_('Price'), boldrightstyle), Paragraph(_('Quantity'), boldrightstyle), Paragraph(_('Total'), boldrightstyle) ]], colWidths=[115 * mm, 20 * mm, 20 * mm, 25 * mm], style=TableStyle([ ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), #('BOX', (0,0), (-1, -1), 0.25, colors.black), ])) ] for item in purchase.items: celldata = [ Table( [[ item.name[0], formatters.money(item.price[0], True), item.quantity[0], formatters.money(item.total[0], True) ]], colWidths=[115 * mm, 20 * mm, 20 * mm, 25 * mm], style=TableStyle([ ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), #('BOX', (0,0), (-1, -1), 0.25, colors.black), #('ALIGN', (0,0), (-1, 0), 'LEFT') ]), ) ] if item.options: for opt, val in item.optionsWithValue: celldata.append( Paragraph('%s: <i>%s</i>' % (opt, val), indentedsmallstyle)) tabledata.append(celldata) # Sum and VAT tabledata.append([ Table( [[ '', Paragraph(_('Total'), boldrightstyle), Paragraph(formatters.money(purchase.total[0], True), boldrightstyle) ]], colWidths=[115 * mm, 40 * mm, 25 * mm], style=TableStyle([ ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), #('BOX', (0,0), (-1, -1), 0.25, colors.black), #('ALIGN', (0,0), (-1, 0), 'LEFT') ]), ) ]) #vats = [(25, decimal.Decimal('11.37')), (12, decimal.Decimal('6.78'))] for code, percentage, amount in purchase.vat: tabledata.append([ Table( [[ '', Paragraph( _('Including %s%% VAT') % py3txt(formatters.vatpercentage(percentage)), boldrightstyle), Paragraph(formatters.money(amount, True), boldrightstyle) ]], colWidths=[115 * mm, 40 * mm, 25 * mm], style=TableStyle([ ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), #('BOX', (0,0), (-1, -1), 0.25, colors.black), #('ALIGN', (0,0), (-1, 0), 'LEFT') ]), ) ]) t = Table( [[t] for t in tabledata], colWidths=[180 * mm], repeatRows=1, style=TableStyle([ ('LEFTPADDING', (0, 0), (0, -1), 0), ('RIGHTPADDING', (0, -1), (-1, -1), 0), #('BOX', (0,0), (-1, -1), 0.25, colors.black) ])) elements.append(t) extraText = purchase.extraText if extraText: textElements = [] text_style = ParagraphStyle('Text', fontName='Helvetica', fontSize=8, leading=9) for text in extraText: textElements.append(Paragraph(text, text_style)) elements.append(KeepTogether(textElements)) doc.multiBuild(elements)
def test0(self): "IndentTestCase test0" if rl_invariant: random.seed(1479316371) # Build story. story = [] doc = MyDocTemplate(outputfile('test_platypus_indents.pdf')) storyAdd = story.append styleSheet = getSampleStyleSheet() h1 = styleSheet['Heading1'] h1.spaceBefore = 18 bt = styleSheet['BodyText'] bt.spaceBefore = 6 storyAdd(Paragraph('Test of context-relative indentation', h1)) storyAdd(Spacer(18, 18)) storyAdd(Indenter(0, 0)) storyAdd( Paragraph( "This should be indented 0 points at each edge. " + ("spam " * 25), bt)) storyAdd(Indenter(0, 0)) storyAdd(Indenter(36, 0)) storyAdd( Paragraph( "This should be indented 36 points at the left. " + ("spam " * 25), bt)) storyAdd(Indenter(-36, 0)) storyAdd(Indenter(0, 36)) storyAdd( Paragraph( "This should be indented 36 points at the right. " + ("spam " * 25), bt)) storyAdd(Indenter(0, -36)) storyAdd(Indenter(36, 36)) storyAdd( Paragraph( "This should be indented 36 points at each edge. " + ("spam " * 25), bt)) storyAdd(Indenter(36, 36)) storyAdd( Paragraph( "This should be indented a FURTHER 36 points at each edge. " + ("spam " * 25), bt)) storyAdd(Indenter(-72, -72)) storyAdd( Paragraph( "This should be back to normal at each edge. " + ("spam " * 25), bt)) storyAdd(Indenter(36, 36)) storyAdd( Paragraph(("""This should be indented 36 points at the left and right. It should run over more than one page and the indent should continue on the next page. """ + (random.randint(0, 10) * 'x') + ' ') * 20, bt)) storyAdd(Indenter(-36, -36)) storyAdd(NextPageTemplate('updown')) storyAdd(FrameBreak()) storyAdd(Paragraph('Another test of context-relative indentation', h1)) storyAdd(NextPageTemplate( 'normal')) # so NEXT page is different template... storyAdd( Paragraph( """This time we see if the indent level is continued across frames...this page has 2 frames, let's see if it carries top to bottom. Then onto a totally different template.""", bt)) storyAdd(Indenter(0, 0)) storyAdd( Paragraph( "This should be indented 0 points at each edge. " + ("spam " * 25), bt)) storyAdd(Indenter(0, 0)) storyAdd(Indenter(36, 72)) storyAdd( Paragraph(("""This should be indented 36 points at the left and 72 at the right. It should run over more than one frame and one page, and the indent should continue on the next page. """ + (random.randint(0, 10) * 'x') + ' ') * 35, bt)) storyAdd(Indenter(-36, -72)) storyAdd( Paragraph( "This should be back to normal at each edge. " + ("spam " * 25), bt)) storyAdd(PageBreak()) storyAdd(PageBreak()) storyAdd( Paragraph( "Below we should colour the background lightgreen and have a red border", bt)) storyAdd( FrameBG(start=True, color=lightgreen, strokeColor=toColor('red'), strokeWidth=1)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(Spacer(6, 6)) storyAdd(FrameBG(start=False)) storyAdd( Paragraph("Below we should colour the background lightgreen", bt)) storyAdd( FrameBG(start=True, color=lightgreen, strokeColor=toColor('red'), strokeWidth=None)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(Spacer(6, 6)) storyAdd(FrameBG(start=False)) storyAdd( Paragraph( "Below we split to two new frames with dark green borders", bt)) storyAdd(FrameSplitter('templateX', ['XF4', 'XF5'], adjustHeight=False)) storyAdd( FrameBG(start=True, color=lightgreen, strokeColor=toColor('red'), strokeWidth=1)) for i in range(15): storyAdd( Paragraph( "We should have a light green background here %d" % i, bt)) storyAdd(Spacer(6, 6)) storyAdd(FrameBG(start=False)) storyAdd(NextPageTemplate('normal')) storyAdd(PageBreak()) storyAdd( Paragraph("Below we should colour the background lightgreen", bt)) storyAdd(FrameBG(start="frame", color=lightgreen)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(PageBreak()) storyAdd(Paragraph("Here we should have no background.", bt)) storyAdd(PageBreak()) storyAdd(FrameBG(start="frame", color=lightblue)) storyAdd( Paragraph( "We should have a light blue background here and the whole frame should be filled in.", bt)) storyAdd(PageBreak()) storyAdd(Paragraph("Here we should have no background again.", bt)) storyAdd( Paragraph("Below we should colour the background lightgreen", bt)) storyAdd(FrameBG(start="frame-permanent", color=lightgreen)) storyAdd(Paragraph("We should have a light green background here", bt)) storyAdd(PageBreak()) storyAdd( Paragraph("Here we should still have a lightgreen background.", bt)) storyAdd(PageBreak()) storyAdd(FrameBG(start="frame", color=lightblue, left=36, right=36)) storyAdd( Paragraph("We should have a lighgreen/lightblue background.", bt)) storyAdd(PageBreak()) storyAdd( Paragraph("Here we should have only light green background.", bt)) doc.multiBuild(story)
def includePdfFlowables(fileName, pages=None, dx=0, dy=0, sx=1, sy=1, degrees=0, orientation=None, isdata=False, #True if this is a preprocessed data file leadingBreak=True, #True/False or 'notattop' template=None, outlineText=None, outlineLevel=0, outlineClosed=0, pdfBoxType = None, autoCrop = False, pageSize=None, callback=None, user_data=None, ): ''' includePdfFlowables creates a list of story flowables that represents an included PDF. Arguments meaning fileName string name of a .pdf or .data file or an object with a read method pages If None all pages will be used, else this argument can be a string like '1,2,4-6,12-10,15' or an explicit list of integers eg [1,2,7]. dx,dy, translation together all these make up a transformation sx,sy, scaling matrix degrees, rotation orientation None or integer degrees eg 0 90 270 or 'portrait'/'landscape' isdata True if fileName argument refers to a .data file (as produced by pageCatcher) leadingBreak True/False or 'notattop' specifies whether a leading page break should be used; 'notattop' means a page break will not be used if the story is at the top of a frame. template If specified the index or name of a template to be used. outlineText Any outline text to be used (default None) outlineLevel The level of any outline text. outlineClosed True/False if the outline should be closed or open. pdfBoxType which box to use or None or [x0,y0, x1,y1] autoCrop True/False crop/don't crop with CropBox (default is False) boxname use for cropping [x0,y0, x1,y1] crop area pageSize default None ie leave page size alone 'set' adjust page size to incoming box 'fit' scale incoming box to fit page size 'orthfit' orthogonally scale incoming box to fit 'center' or 'centre' center the incoming box in the existing page size [x0,y0, x1,y1] use this as the page size callback draw time callback with signature callback(canvas,key,obj,pdf_data,user_data) canvas the canvas being drawn on key may be 'raw-pre'|'transformed-pre'|'transformed-post'|'raw-post' obj the flowable calling the callback pdf_data ('fileName',pageNumber) user_data user data passed down to the flowable from IncludePdfFlowable. user_data information to be passed to the callback ''' try: orientation=int(orientation) orientation = orientation % 360 except: if orientation=='portrait': orientation = 0 elif orientation=='landscape': orientation = 90 elif orientation!='auto' and orientation!=None: raise ValueError('Bad value %r for orientation attribute' % orientation) iptrans = IPTrans(sx,sy,dx,dy,degrees) if iptrans.trivial(): iptrans = None pages = expandPageNumbers(pages) # this one is unusual in that it returns a list of objects to # go into the story. output = [] output_append = output.append if template: output_append(NextPageTemplate(template)) try: if isdata: pickledStuff = pickle.loads(open_and_read(fileName)) formNames = pickledStuff[None] else: #read in the PDF file right now and get the pickled object # and names pdfContent = open_and_read(fileName) prefix = fileName2Prefix(fileName if isStr(fileName) else pdfContent) (formNames, pickledStuff) = storeFormsInMemory( pdfContent, prefix=prefix, all=1,#if pages else 0 #here is where things go wrong #pagenumbers = pages, BBoxes=0, extractText=0, fformname=None) except: annotateException('\nerror storing %r in memory\n' % fileName) #if explicit pages requested, slim it down. if pages: #and isdata: newNames = [] for pgNo in pages: newNames.append(formNames[pgNo-1]) formNames = newNames #make object 1 for story loader = LoadPdfFlowable(pickledStuff,isdata) output_append(loader) #now do first page. This is special as it might #have an outline formName = formNames[0] if leadingBreak: output_append((leadingBreak=='notattop' and NotAtTopPageBreak or PageBreak)()) if outlineText: output_append(OutlineEntry(outlineLevel, outlineText, outlineClosed)) if pageSize=='fit': class PageSizeHandler(object): '''simple class to allow communications between first and last ShowPdfFlowables''' _oldPageSize = [None] def __init__(self,first): self.first = first def oldPageSize(self,v): self._oldPageSize[0] = v oldPageSize = property(lambda self: self._oldPageSize[0],oldPageSize) pageSizeHandler = PageSizeHandler(True) else: pageSizeHandler = None output_append(ShowPdfFlowable(formName,orientation=orientation,iptrans=iptrans, callback=callback, pdf_data=(fileName,pages[0] if pages else 1), user_data=user_data, pdfBoxType=pdfBoxType, autoCrop=autoCrop, pageSize=pageSize, pageSizeHandler=pageSizeHandler, )) #now make a shower for each laterpage, and a page break for i,formName in enumerate(formNames[1:]): i += 1 output_append(PageBreak()) output_append(ShowPdfFlowable(formName,orientation=orientation,iptrans=iptrans, callback=callback, pdf_data=(fileName,pages[i] if pages else i), user_data=user_data, pdfBoxType=pdfBoxType, autoCrop=autoCrop, pageSize=pageSize, pageSizeHandler=None, )) if pageSize=='fit': output[-1]._pageSizeHandler = PageSizeHandler(False) return output
def add_toc(): Report.append(NextPageTemplate('later_pages')) Report.append(PageBreak()) Report.append(toc) Report.append(PageBreak())
def createPriceList(response, wine, mode='wholesale'): def addTableTitle(title, style): data = [[title]] story.append(Spacer(1, 0.5 * cm)) story.append( Table(data, colWidths=fullW, style=tstyles[style], rowHeights=rowH)) addFontFile() story = [] # TITLE PAGE story.append(NextPageTemplate(['toc'])) story.append(PageBreak()) # TABLE OF CONTENTS toc = TableOfContents() toc.levelStyles = [body, bodyin] story.append(Spacer(1, 2.5 * cm)) story.append(Paragraph('<b>CONTENTS</b>', body)) story.append(Spacer(1, 0.5 * cm)) story.append(toc) story.append(NextPageTemplate(['normal'])) story.append(PageBreak()) # GET ALL WINE OBJECTS if mode == 'retail': wines = wine.objects.filter(retail=True, price_group__isnull=False).order_by( 'price_group__my_order', 'appellation__my_order', 'producer__name') else: wines = wine.objects.filter(wholesale=True, price_group__isnull=False).order_by( 'price_group__my_order', 'appellation__my_order', 'producer__name') ## PRICE GROUP START price_groups = groupby(wines, lambda wine: wine.price_group) for pg, w in price_groups: story.append(Paragraph(pg.name.upper(), h1)) # Set header row -> Wine, Vintage, Bottle, Case data = [['', 'Vintage', 'Bottle', 'Case']] story.append(Spacer(1, 1 * cm)) story.append( Table(data, colWidths=colW, style=tstyles['theader'], rowHeights=rowH)) ## PRICE GROUP END # APPELLATION GROUP START appellation_groups = groupby(w, lambda wine: wine.appellation) for a, w in appellation_groups: if a.retail_list or a.wholesale_list: data = [[a.name.upper()]] story.append(Spacer(1, 0.5 * cm)) t = wineTable(data, colWidths=fullW, style=tstyles['tappellation'], rowHeights=rowH) t.name = a.name.upper() story.append(t) # APPELLATION GROUP END # PRODUCER GROUP START producer_groups = groupby(w, lambda wine: wine.producer) for p, wines in producer_groups: addTableTitle(p.name.upper(), 'tproducer') #w = sorted(w, key=lambda wine: wine.vintage) #w = sorted(w, key=lambda wine: wine.size.size) #w = sorted(w, key=lambda wine: wine.wine) data = [] row = 0 wine_colours = [] for w in wines: datarow = [] if w.size.name == 'Bottle': wine_name = w.wine else: wine_name = "%s - %s" % (w.wine, w.size) colour = { None: PCMYKColor(0, 0, 0, 100), '': PCMYKColor(0, 0, 0, 100), 'Ro': PCMYKColor(0, 76, 23, 9), 'W': PCMYKColor(84, 0, 100, 42), 'R': PCMYKColor(0, 89, 100, 9) } wine_colour = w.colour #Set wine colour wine_colours.append( ('TEXTCOLOR', (0, row), (0, row), colour[wine_colour])) datarow.append("%s" % (wine_name)) #set default colour datarow.append(w.vintage) try: whole_price = w.wholesale_price except ValueError: whole_price = 0.0 datarow.append("%s%.2f" % (u"\u00A3", whole_price)) datarow.append("%s%.2f" % (u"\u00A3", w.wholesale_case_price)) data.append(datarow) row += 1 t = Table(data, colWidths=colW, style=tstyles['tnormal'], rowHeights=rowH) t.setStyle(TableStyle(wine_colours)) story.append(t) # PRODUCER GROUP END story.append(PageBreak()) doc = MyDocTemplate(response) doc.multiBuild(story)
def render_to_reportlab(context): """ In context dictionary we could have a 'fattura' or a list of fatture in 'fatture'. Everything will be appended to a pdf returned as Django response. To reset page counter between different invoices, we'll use 2 "Normale" templates, one for even and one for odds, so every times the template changes we'll reset the NumberedCanvas """ if "fattura" in context and "fatture" in context: raise Exception( "Please create PDF choosing between a fattura or multiple fatture") if "fattura" in context: fatture = [context.get('fattura')] else: fatture = context.get('fatture') response = http.HttpResponse(content_type='application/pdf') NormalTemplates = ['Normale0', 'Normale1'] fatture_rimanenti = len(fatture) story = [] pageTemplates = [ PageTemplate(id='Normale0', onPage=onPageNormal), PageTemplate(id='Normale1', onPage=onPageNormal), PageTemplate(id='ConducenteConsorzio', onPage=onPageConducenteConsorzio), PageTemplate(id='ConsorzioConducente', onPage=onPageConsorzioConducente), ] # scelgo il template della prima pagina come primo della lista if fatture[0].is_ricevuta_sdoppiata(): lastTemplateID = 'ConducenteConsorzio' pageTemplates = pageTemplates[2:] + pageTemplates[:2] else: lastTemplateID = 'Normale0' width, height = portrait(A4) doc = BaseDocTemplate( response, pagesize=(width, height), leftMargin=1 * cm, rightMargin=1 * cm, bottomMargin=1.5 * cm, topMargin=1 * cm, showBoundary=test, pageTemplates=pageTemplates, ) doc.fatture = fatture doc.lastTemplateID = lastTemplateID doc.fattura_corrente = 0 for fattura in fatture: ricevutaMultipla = fattura.is_ricevuta_sdoppiata() story_fattura = [] fatturazione = FATTURE_PER_TIPO[fattura.tipo] righeFattura = [ ('Descrizione', 'Q.tà', 'Prezzo', 'IVA %', 'Importo'), ] righe = fattura.righe.all() raggruppa_barbatrucco = False if fatturazione.codice == "5": totale = sum([r.val_totale() for r in righe]) conducente = righe[0].conducente if righe else None if "Imposta di bollo" not in [r.descrizione for r in righe]: if not (totale < settings.MIN_PRICE_FOR_TAXSTAMP and (conducente is None or conducente.emette_ricevute)): raggruppa_barbatrucco = True if raggruppa_barbatrucco: # print "5 esente iva con barbatrucco" netto = totale / Decimal(1.1) class RigaTotaleIvata(object ): # una riga che fa corrispondere il totale descrizione = "Servizi per consorzio." note = None qta = 1 prezzo = netto iva = 10 def val_imponibile(self): return self.prezzo def val_iva(self): return totale - netto def val_totale(self): return totale riga = RigaTotaleIvata() # la fattura ha totale pari al totale di tutte le righe # l'iva è fissa al 10% e il netto è calcolato di conseguenza imponibile = netto iva = totale - netto righe = [riga] else: imponibile = fattura.val_imponibile() iva = fattura.val_iva() for riga in righe: descrizione = riga.descrizione if riga.note: descrizione += " (%s)" % riga.note righeFattura.append( (Paragraph(descrizione, normalStyle), Paragraph("%s" % riga.qta, normalStyle), moneyfmt(riga.prezzo), riga.iva, moneyfmt(riga.val_totale()))) righeTotali = [] righeTotali.append(('Imponibile', moneyfmt(imponibile))) righeTotali.append(('IVA', moneyfmt(iva))) righeTotali.append(('TOTALE', moneyfmt(fattura.val_totale()))) righeStyle = TableStyle([ ('VALIGN', (0, 0), (-1, -1), 'TOP'), ('ALIGN', (0, 0), (-1, -1), 'RIGHT'), # globalmente allineato a destra... ('ALIGN', (0, 0), (1, -1), 'LEFT'), # tranne la prima colonna (con la descrizione) ('GRID', (0, 1), (-1, -1), 0.1, colors.grey), ('FACE', (0, 0), (-1, -1), 'Helvetica'), ('FACE', (0, 0), (-1, 0), 'Helvetica-Bold'), # header ('SIZE', (0, 0), (-1, -1), 8), # ('SPAN', (0, -1), (3, -1)), # anziché mettere lo span qui aggiungo in coda una tabella diversa ]) totaliStyle = TableStyle([ ('ALIGN', (0, 0), (-1, -1), 'RIGHT'), ('GRID', (-1, 0), (-1, -1), 0.1, colors.grey), ('FACE', (0, 0), (-1, -1), 'Helvetica'), # header ('FACE', (0, -1), (-1, -1), 'Helvetica-Bold'), # Totale ('SIZE', (0, 0), (-1, -1), 8), ]) colWidths = ((width - doc.leftMargin - doc.rightMargin) - (1.6 * 4) * cm, ) + (1.6 * cm, ) * 4 story_fattura = [ Table(righeFattura, style=righeStyle, repeatRows=1, colWidths=colWidths) ] story_fattura.append( KeepTogether( Table(righeTotali, style=totaliStyle, colWidths=(width - doc.leftMargin - doc.rightMargin - 1.6 * cm, 1.6 * cm)))) if ricevutaMultipla: # le ricevute si raddoppiano con 2 template diversi # raddoppio lo story di questa fattura cambiando template story_fattura = story_fattura + [ NextPageTemplate("ConsorzioConducente"), PageBreak() ] + story_fattura fatture_rimanenti -= 1 if fatture_rimanenti: story_fattura += [ NextPageTemplate(NormalTemplates[-1]), PageBreak() ] NormalTemplates.reverse() # reverse current, next normal template story = story + story_fattura doc.build(story, canvasmaker=NumberedCanvas) return response
def getSpecialTemplate(self, temp_name="Later"): """ get the next page action flowable template that starts with temp_name """ return NextPageTemplate( self.getTemplate(temp_id=temp_name, last=True, as_name=True))
def test1(self): "This makes one long multi-page paragraph." # Build story. story = [] styleSheet = getSampleStyleSheet() h3 = styleSheet['Heading3'] bt = styleSheet['BodyText'] text = '''If you imagine that the box of X's tothe left is an image, what I want to be able to do is flow a series of paragraphs around the image so that once the bottom of the image is reached, then text will flow back to the left margin. I know that it would be possible to something like this using tables, but I can't see how to have a generic solution. There are two examples of this in the demonstration section of the reportlab site. If you look at the "minimal" euro python conference brochure, at the end of the timetable section (page 8), there are adverts for "AdSu" and "O'Reilly". I can see how the AdSu one might be done generically, but the O'Reilly, unsure... I guess I'm hoping that I've missed something, and that it's actually easy to do using platypus.We can do greek letters <greek>mDngG</greek>. This should be a u with a dieresis on top <unichar code=0xfc/>="<unichar code="0xfc"/>" and this &#xfc;="ü" and this \\xc3\\xbc="\xc3\xbc". On the other hand this should be a pound sign &pound;="£" and this an alpha &alpha;="α". You can have links in the page <link href="http://www.reportlab.com" color="blue">ReportLab</link> & <a href="http://www.reportlab.org" color="green">ReportLab.org</a>. Use scheme "pdf:" to indicate an external PDF link, "http:", "https:" to indicate an external link eg something to open in your browser. If an internal link begins with something that looks like a scheme, precede with "document:". <strike>This text should have a strike through it.</strike> ''' from reportlab.platypus.flowables import ImageAndFlowables, Image from reportlab.lib.testutils import testsFolder gif = os.path.join(testsFolder,'pythonpowered.gif') heading = Paragraph('This is a heading',h3) story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text,bt)])) phrase = 'This should be a paragraph spanning at least three pages. ' description = ''.join([('%d: '%i)+phrase for i in xrange(250)]) story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(description, bt)],imageSide='left')) story.append(NextPageTemplate('special')) story.append(PageBreak()) VERA = ('Vera','VeraBd','VeraIt','VeraBI') for v in VERA: registerFont(TTFont(v,v+'.ttf')) registerFontFamily(*(VERA[:1]+VERA)) story.append(ImageAndFlowables( Image(gif,width=280,height=120), Paragraph('''<font name="Vera">The <b>concept</b> of an <i>integrated</i> one <b><i>box</i></b> solution for <i><b>advanced</b></i> voice and data applications began with the introduction of the IMACS. The IMACS 200 carries on that tradition with an integrated solution optimized for smaller port size applications that the IMACS could not economically address. An array of the most popular interfaces and features from the IMACS has been bundled into a small 2U chassis providing the ultimate in ease of installation.</font>''', style=ParagraphStyle( name="base", fontName="Helvetica", leading=12, leftIndent=0, firstLineIndent=0, spaceBefore = 9.5, fontSize=9.5, ) ), imageSide='left', ) ) story.append(ImageAndFlowables( Image(gif,width=240,height=120), Paragraph('''The concept of an integrated one box solution for advanced voice and data applications began with the introduction of the IMACS. The IMACS 200 carries on that tradition with an integrated solution optimized for smaller port size applications that the IMACS could not economically address. An array of the most popular interfaces and features from the IMACS has been bundled into a small 2U chassis providing the ultimate in ease of installation.''', style=ParagraphStyle( name="base", fontName="Helvetica", leading=12, leftIndent=0, firstLineIndent=0, spaceBefore = 9.5, fontSize=9.5, ) ), imageSide='left', ) ) story.append(PageBreak()) story.append(Paragraph('Image larger than the frame',h3)) story.append(ImageAndFlowables( Image(gif,width=6*110,height=6*44), Paragraph('''The concept of an integrated one box solution for advanced voice and data applications began with the introduction of the IMACS. The IMACS 200 carries on that tradition with an integrated solution optimized for smaller port size applications that the IMACS could not economically address. An array of the most popular interfaces and features from the IMACS has been bundled into a small 2U chassis providing the ultimate in ease of installation.''', style=ParagraphStyle( name="base", fontName="Helvetica", leading=12, leftIndent=0, firstLineIndent=0, spaceBefore = 9.5, fontSize=9.5, ) ), imageSide='left', ) ) doc = MyDocTemplate(outputfile('test_platypus_imageandflowables.pdf'),showBoundary=1) doc.multiBuild(story)
# ------------------------------------- # BEGIN TO ADD CONTENT # when to add content at document, is # similar to write a story step by step # and you should use a list of flowables # that help to write it. # ------------------------------------- # list of flowables that represent the content of document content = [] # add the first flowable called Paragraph, that allow write text content.append( Paragraph("This is a Paragraph ", ParagraphStyle( 'MyStyle1', fontSize=10, ))) content.append(NextPageTemplate('page_design_two')) content.append(PageBreak()) content.append( Paragraph("This is a Paragraph on the page 2 ", ParagraphStyle( 'MyStyle1', fontSize=10, ))) # when finish of write content, so you can send build it document.build(content, filename="Training_pdf" #canvasmaker=canvas.Canvas )
def start(self, c): # deprecation("pdf:nextpage") c.addPara() if self.attr.name: c.addStory(NextPageTemplate(self.attr.name)) c.addStory(PageBreak())
def start(self, c): c.addStory(NextPageTemplate(self.attr["name"]))
def start(self, c): c.addPara() if self.attr.name: c.addStory(NextPageTemplate(self.attr.name)) c.addStory(PageBreak())
def handle_flowable(self, flowables): """ overriding base method!!! try to handle one flowable from the front of list flowables. added a dirty workaround to scale images if their boundingBox exceeds the borders of the frame. """ #allow document a chance to look at, modify or ignore #the object(s) about to be processed self.filterFlowables(flowables) self.handle_breakBefore(flowables) self.handle_keepWithNext(flowables) f = flowables[0] del flowables[0] if f is None: return if isinstance(f, PageBreak): npt = f.nextTemplate if npt and not self._samePT(npt): npt = NextPageTemplate(npt) npt.apply(self) self.afterFlowable(npt) if isinstance(f, SlowPageBreak): self.handle_pageBreak(slow=1) else: #print( f.__class__.__name__, self.frame.id ) self.handle_pageBreak() self.afterFlowable(f) elif isinstance(f, ActionFlowable): f.apply(self) self.afterFlowable(f) else: frame = self.frame canv = self.canv if self.debug: frame.drawBoundary(canv) #handle scaling to fit a PdfImage on self.frame if isinstance(f, Table): pass # controls default behaviour for Table typed flowables #f.setStyle([("GRID", (0, 0), (-1, -1), 0.5, colors.black)]) elif isinstance(f, Spacer): pass if isinstance(f, ap.PdfImage): #print("height of image:",f.drawHeight) #print("height of frame:",frame._aH) xfactor = getattr(f, "_userScaleFactor", None) factor = 1. if xfactor is not None: #print( "applying scale", xfactor) factor = xfactor f = self._scaleApply(f, factor) setattr(f, "_userScaleFactor", None) #resizing image if drawWidth is exceeding the available frame Width _aW if f.drawWidth > frame._aW: factor = frame._aW / f.drawWidth f = self._scaleApply(f, factor) if self.debug: print("PdfImage exceeds available width on frame:", frame.id, frame._aW / cm, frame._aH / cm, f.drawWidth / cm, f.drawHeight / cm, "rescaling to fit frame geometry.") #resizing image if drawHeight is exceeding the available frame Width _aH if f.drawHeight > frame._aH: #print("PdfImage height exceeds height of available space on frame:", # frame.id, # "rescaling to fit frame geometry..." ) factor = frame._aH / f.drawHeight f = self._scaleApply(f, factor) #print("spaceBelow:",frame._aH-f.drawHeight ) #print("spaceBesides:",frame._aW-f.drawWidth ) #print(f.drawHeight) #try to fit it then draw it if frame.add(f, canv, trySplit=self.allowSplitting): if not isinstance(f, FrameActionFlowable): self._curPageFlowableCount += 1 self.afterFlowable(f) _addGeneratedContent(flowables, frame) else: if self.allowSplitting: # see if this is a splittable thing S = frame.split(f, canv) n = len(S) else: n = 0 if n: if not isinstance(S[0], (PageBreak, SlowPageBreak, ActionFlowable, DDIndenter)): if not frame.add(S[0], canv, trySplit=0): ident = "Splitting error(n==%d) on page %d in\n%s\nS[0]=%s" % \ (n, self.page, self._fIdent(f, 60, frame), self._fIdent(S[0], 60, frame)) #leave to keep apart from the raise raise LayoutError(ident) self._curPageFlowableCount += 1 self.afterFlowable(S[0]) flowables[0:0] = S[ 1:] # put rest of splitted flowables back on the list _addGeneratedContent(flowables, frame) else: flowables[ 0:0] = S # put splitted flowables back on the list else: if hasattr(f, '_postponed'): pass #print( f.__class__.__name__, self.frame.id, f.drawWidth, f.drawHeight, ) # ident = "Flowable %s%s too large on page %d in frame %r%s of template %r" % \ # (self._fIdent(f, 60, frame), # _fSizeString(f), # self.page, # self.frame.id, # self.frame._aSpaceString(), # self.pageTemplate.id) # #leave to keep apart from the raise # raise LayoutError(ident) # this ought to be cleared when they are finally drawn! f._postponed = 1 mbe = getattr(self, '_multiBuildEdits', None) if mbe: mbe((delattr, f, '_postponed')) # put the flowable back flowables.insert(0, f) self.handle_frameEnd()
def start(self, c): # deprecation("pdf:frame") c.addStory(NextPageTemplate(self.attr["name"]))
def test0(self): "This makes one long multi-page paragraph." # Build story. story = [] styleSheet = getSampleStyleSheet() h1 = styleSheet['Heading1'] h1.spaceBefore = 18 bt = styleSheet['BodyText'] bt.spaceBefore = 6 story.append(Paragraph('Test of context-relative indentation', h1)) story.append(Spacer(18, 18)) story.append(Indenter(0, 0)) story.append( Paragraph( "This should be indented 0 points at each edge. " + ("spam " * 25), bt)) story.append(Indenter(0, 0)) story.append(Indenter(36, 0)) story.append( Paragraph( "This should be indented 36 points at the left. " + ("spam " * 25), bt)) story.append(Indenter(-36, 0)) story.append(Indenter(0, 36)) story.append( Paragraph( "This should be indented 36 points at the right. " + ("spam " * 25), bt)) story.append(Indenter(0, -36)) story.append(Indenter(36, 36)) story.append( Paragraph( "This should be indented 36 points at each edge. " + ("spam " * 25), bt)) story.append(Indenter(36, 36)) story.append( Paragraph( "This should be indented a FURTHER 36 points at each edge. " + ("spam " * 25), bt)) story.append(Indenter(-72, -72)) story.append( Paragraph( "This should be back to normal at each edge. " + ("spam " * 25), bt)) story.append(Indenter(36, 36)) story.append( Paragraph(("""This should be indented 36 points at the left and right. It should run over more than one page and the indent should continue on the next page. """ + (random.randint(0, 10) * 'x') + ' ') * 20, bt)) story.append(Indenter(-36, -36)) story.append(NextPageTemplate('updown')) story.append(FrameBreak()) story.append( Paragraph('Another test of context-relative indentation', h1)) story.append(NextPageTemplate( 'normal')) # so NEXT page is different template... story.append( Paragraph( """This time we see if the indent level is continued across frames...this page has 2 frames, let's see if it carries top to bottom. Then onto a totally different template.""", bt)) story.append(Indenter(0, 0)) story.append( Paragraph( "This should be indented 0 points at each edge. " + ("spam " * 25), bt)) story.append(Indenter(0, 0)) story.append(Indenter(36, 72)) story.append( Paragraph(("""This should be indented 36 points at the left and 72 at the right. It should run over more than one frame and one page, and the indent should continue on the next page. """ + (random.randint(0, 10) * 'x') + ' ') * 35, bt)) story.append(Indenter(-36, -72)) story.append( Paragraph( "This should be back to normal at each edge. " + ("spam " * 25), bt)) doc = MyDocTemplate(outputfile('test_platypus_indents.pdf')) doc.multiBuild(story)
def pisaLoop(node, context, path=None, **kw): if path is None: path = [] # Initialize KW if not kw: kw = { "margin-top": 0, "margin-bottom": 0, "margin-left": 0, "margin-right": 0, } else: kw = copy.copy(kw) # indent = len(path) * " " # only used for debug print statements # TEXT if node.nodeType == Node.TEXT_NODE: # print indent, "#", repr(node.data) #, context.frag context.addFrag(node.data) # context.text.append(node.value) # ELEMENT elif node.nodeType == Node.ELEMENT_NODE: node.tagName = node.tagName.replace(":", "").lower() if node.tagName in ("style", "script"): return path = copy.copy(path) + [node.tagName] # Prepare attributes attr = pisaGetAttributes(context, node.tagName, node.attributes) # log.debug(indent + "<%s %s>" % (node.tagName, attr) + # repr(node.attributes.items())) #, path # Calculate styles context.cssAttr = CSSCollect(node, context) context.cssAttr = mapNonStandardAttrs(context.cssAttr, node, attr) context.node = node # Block? PAGE_BREAK = 1 PAGE_BREAK_RIGHT = 2 PAGE_BREAK_LEFT = 3 pageBreakAfter = False frameBreakAfter = False display = lower(context.cssAttr.get("display", "inline")) # print indent, node.tagName, display, # context.cssAttr.get("background-color", None), attr isBlock = (display == "block") if isBlock: context.addPara() # Page break by CSS if "-pdf-next-page" in context.cssAttr: context.addStory( NextPageTemplate(str(context.cssAttr["-pdf-next-page"]))) if "-pdf-page-break" in context.cssAttr: if str(context.cssAttr["-pdf-page-break"]).lower() == "before": context.addStory(PageBreak()) if "-pdf-frame-break" in context.cssAttr: if str(context.cssAttr["-pdf-frame-break"]).lower() == "before": context.addStory(FrameBreak()) if str(context.cssAttr["-pdf-frame-break"]).lower() == "after": frameBreakAfter = True if "page-break-before" in context.cssAttr: if str(context.cssAttr["page-break-before"]).lower() == "always": context.addStory(PageBreak()) if str(context.cssAttr["page-break-before"]).lower() == "right": context.addStory(PageBreak()) context.addStory(PmlRightPageBreak()) if str(context.cssAttr["page-break-before"]).lower() == "left": context.addStory(PageBreak()) context.addStory(PmlLeftPageBreak()) if "page-break-after" in context.cssAttr: if str(context.cssAttr["page-break-after"]).lower() == "always": pageBreakAfter = PAGE_BREAK if str(context.cssAttr["page-break-after"]).lower() == "right": pageBreakAfter = PAGE_BREAK_RIGHT if str(context.cssAttr["page-break-after"]).lower() == "left": pageBreakAfter = PAGE_BREAK_LEFT if display == "none": # print "none!" return # Translate CSS to frags # Save previous frag styles context.pushFrag() # Map styles to Reportlab fragment properties CSS2Frag(context, kw, isBlock) # EXTRAS transform_attrs(context.frag, ( ("keepWithNext", "-pdf-keep-with-next"), ("outline", "-pdf-outline"), ("borderLeftColor", "-pdf-outline-open"), ), context.cssAttr, getBool ) if "-pdf-outline-level" in context.cssAttr: context.frag.outlineLevel = int( context.cssAttr["-pdf-outline-level"]) if "-pdf-word-wrap" in context.cssAttr: context.frag.wordWrap = context.cssAttr["-pdf-word-wrap"] # handle keep-in-frame keepInFrameMode = None keepInFrameMaxWidth = 0 keepInFrameMaxHeight = 0 if "-pdf-keep-in-frame-mode" in context.cssAttr: value = str( context.cssAttr["-pdf-keep-in-frame-mode"]).strip().lower() if value in ("shrink", "error", "overflow", "truncate"): keepInFrameMode = value else: keepInFrameMode = "shrink" # Added because we need a default value. if "-pdf-keep-in-frame-max-width" in context.cssAttr: keepInFrameMaxWidth = getSize( "".join(context.cssAttr["-pdf-keep-in-frame-max-width"])) if "-pdf-keep-in-frame-max-height" in context.cssAttr: keepInFrameMaxHeight = getSize( "".join(context.cssAttr["-pdf-keep-in-frame-max-height"])) # ignore nested keep-in-frames, tables have their own KIF handling keepInFrame = keepInFrameMode is not None and context.keepInFrameIndex is None if keepInFrame: # keep track of current story index, so we can wrap everythink # added after this point in a KeepInFrame context.keepInFrameIndex = len(context.story) # BEGIN tag klass = globals().get("pisaTag%s" % node.tagName.replace(":", "").upper(), None) obj = None # Static block elementId = attr.get("id", None) staticFrame = context.frameStatic.get(elementId, None) if staticFrame: context.frag.insideStaticFrame += 1 oldStory = context.swapStory() # Tag specific operations if klass is not None: obj = klass(node, attr) obj.start(context) # Visit child nodes context.fragBlock = fragBlock = copy.copy(context.frag) for nnode in node.childNodes: pisaLoop(nnode, context, path, **kw) context.fragBlock = fragBlock # END tag if obj: obj.end(context) # Block? if isBlock: context.addPara() # XXX Buggy! # Page break by CSS if pageBreakAfter: context.addStory(PageBreak()) if pageBreakAfter == PAGE_BREAK_RIGHT: context.addStory(PmlRightPageBreak()) if pageBreakAfter == PAGE_BREAK_LEFT: context.addStory(PmlLeftPageBreak()) if frameBreakAfter: context.addStory(FrameBreak()) if keepInFrame: # get all content added after start of -pdf-keep-in-frame and wrap # it in a KeepInFrame substory = context.story[context.keepInFrameIndex:] context.story = context.story[:context.keepInFrameIndex] context.story.append( KeepInFrame( content=substory, maxWidth=keepInFrameMaxWidth, maxHeight=keepInFrameMaxHeight, mode=keepInFrameMode)) # mode wasn't being used; it is necessary for tables or images at # end of page. context.keepInFrameIndex = None # Static block, END if staticFrame: context.addPara() for frame in staticFrame: frame.pisaStaticStory = context.story context.swapStory(oldStory) context.frag.insideStaticFrame -= 1 # context.debug(1, indent, "</%s>" % (node.tagName)) # Reset frag style context.pullFrag() # Unknown or not handled else: # context.debug(1, indent, "???", node, node.nodeType, repr(node)) # Loop over children for node in node.childNodes: pisaLoop(node, context, path, **kw)
def exportToPDF(path, title, author, description, container, marker_beg, marker_end, replace_where, replace_by, tmargin=30, bmargin=20, lmargin=30, rmargin=20, font='Helvetica', size=12, mode='Bold'): """ This function produce the pdf itself with all the preferences Parameters: ----------- string: path Where it will be save string: title Document's title string: author Document's author string: description A short description of the file class: container Instance of the program integer: *margin The top, bottom, left and right margin string: font Font name integer: size Basic size of the text. string: mode Modes: Bold, Replace, Raw string: marker_beg, marker_end, replace_where, replace_by Strip sentence variables Returns: -------- other pages """ if font == 'Times-Roman': fontbold = 'Times-Bold' if font == 'Courier': fontbold = 'Courier-Bold' if font == 'Helvetica': fontbold = 'Helvetica-Bold' phrase_base = ParagraphStyle(name='phrase_base', fontName=font, fontSize=size, alignment=TA_JUSTIFY, leftIndent=0.5 * inch) heading_1 = ParagraphStyle(name='heading_1', fontName=fontbold, fontSize=size + 4, leading=22, spaceBefore=12, spaceAfter=6) heading_2 = ParagraphStyle(name='heading_2', fontName=fontbold, fontSize=size + 2, leading=18, spaceBefore=6, spaceAfter=6) heading_3 = ParagraphStyle(name='heading_3', fontName=font, fontSize=size + 1, leading=14, spaceBefore=6, spaceAfter=6) centered = ParagraphStyle(name='centered', fontName=font, fontSize=18, leading=26, alignment=1, spaceAfter=26) desc_style = ParagraphStyle(name='desc_style', fontName=font, fontSize=size + 2) title_style = ParagraphStyle(name='title_style', fontName=font, fontSize=size + 12) author_style = ParagraphStyle(name='author_style', fontName=font, fontSize=size + 3) doc = MyDocTemplate(path, pagesize=A4, rightMargin=rmargin * mm, leftMargin=lmargin * mm, topMargin=tmargin * mm, bottomMargin=bmargin * mm) doc.title = title doc.author = author doc.description = description frameT = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal') doc.addPageTemplates([ PageTemplate('first', frames=frameT, onPage=myFirstPage), PageTemplate('toc', frames=frameT, onPage=myTOCPages), PageTemplate('laters', frames=frameT, onPage=myLaterPages) ]) Story = [] Story.append(Spacer(1, 12)) Story.append(Paragraph(title, title_style)) Story.append(Spacer(1, 50)) Story.append(Paragraph(author, author_style)) Story.append(Spacer(1, 150)) Story.append(Paragraph(description, desc_style)) Story.append(NextPageTemplate('toc')) Story.append(PageBreak()) Story.append(Paragraph('Table of contents', centered)) toc = TableOfContents() toc.levelStyles = [heading_1, heading_2, heading_3] Story.append(toc) Story.append(NextPageTemplate('laters')) Story.append(PageBreak()) sections = container.listSections() if "Not Classified" in sections: sections.remove("Not Classified") for snum, sec in enumerate(sections): Story.append(Paragraph(str(snum + 1) + '. ' + sec, heading_1)) Story.append(Spacer(1, 12)) components = container.listComponents(qsections=[sec]) if "Not Classified" in components: components.remove("Not Classified") for compnum, comp in enumerate(components): Story.append( Paragraph( str(snum + 1) + '.' + str(compnum + 1) + '. ' + comp, heading_2)) Story.append(Spacer(1, 12)) strategies = container.listStrategies(qsections=[sec], qsubsections=[comp]) if "Not Classified" in strategies: strategies.remove("Not Classified") nummenos = 0 for stranum, stra in enumerate(strategies): Story.append( Paragraph( str(snum + 1) + '.' + str(compnum + 1) + '.' + str(stranum - nummenos + 1) + '. ' + stra, heading_3)) Story.append(Spacer(1, 12)) lista = container.listSentences(section=[sec], subsection=[comp], function=[stra]) if lista == []: Story.pop() Story.pop() nummenos += 1 for lista in container.listSentences(section=[sec], subsection=[comp], function=[stra]): if lista != []: idv, secv, subsv, funcv, sentv, refv = lista if sentv != 'NULL': if mode != 'Raw': sentv = container.adjustSentence( sentv, marker_beg, marker_end, replace_where, replace_by, mode) if refv == 'NULL': refv = 'None' ptext = sentv + ' Reference: ' + refv Story.append(Paragraph(ptext, phrase_base)) Story.append(Spacer(1, 12)) doc.multiBuild(Story)