def _get_style(self): tblstyle = TableStyle([ ('SPAN', (0, 0), (-1, 0)), ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), ('FONTSIZE', (0, 0), (-1, -1), 9), ('TEXTCOLOR', (0, 0), (-1, -1), colors.black), ('LINEBELOW', (0, 0), (-1, 0), 1, colors.black), ('LINEBELOW', (0, 1), (-1, 1), 1, colors.black), # ('ALIGN', (2, 0), (2, 0), 'LEFT'), ('LINEBELOW', (0, 3), (-1, 3), 1.5, colors.black), # ('LINEBELOW', (0, 0), (-1, -1), 1, colors.red), # ('LINEBEFORE', (0, 0), (-1, -1), 1, colors.black), ('ALIGN', (2, 0), (-1, -1), 'CENTER') ]) for ir in self.int_plat_age_rowids: tblstyle.add('SPAN', (1, ir), (3, ir)) tblstyle.add('SPAN', (1, ir + 1), (2, ir + 1)) for si in self.sample_rowids: tblstyle.add('SPAN', (1, si), (-1, si))
def build_pdf(self, response): cleaned_data = self.filterset.form.cleaned_data agrupamento = cleaned_data['agrupamento'] elements = [] #print('data ini', datetime.now()) data = self.get_data() #print('data fim', datetime.now()) style = TableStyle([ ('FONTSIZE', (0, 0), (-1, -1), 8), ('LEADING', (0, 0), (-1, -1), 7), ('GRID', (0, 0), (-1, -1), 0.1, colors.black), ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), ('LEFTPADDING', (0, 0), (-1, -1), 3), ('RIGHTPADDING', (0, 0), (-1, -1), 3), ]) style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE') #print('enumerate ini', datetime.now()) for i, value in enumerate(data): if len(value) <= 1: style.add('SPAN', (0, i), (-1, i)) if len(value) == 0: style.add('INNERGRID', (0, i), (-1, i), 0, colors.black), style.add('GRID', (0, i), (-1, i), -1, colors.white) style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black) if len(value) == 1: style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black) #print('enumerate fim', datetime.now()) # if not agrupamento or agrupamento == 'sem_agrupamento': # style.add('ALIGN', (0, 0), (0, -1), 'CENTER') #print('table ini', datetime.now()) rowHeights = 20 t = LongTable(data, rowHeights=rowHeights, splitByRow=True) t.setStyle(style) if len(t._argW) == 5: t._argW[0] = 1.8 * cm t._argW[1] = 6 * cm t._argW[2] = 6.5 * cm t._argW[3] = 9.5 * cm t._argW[4] = 2.4 * cm elif len(t._argW) == 4: t._argW[0] = 2 * cm t._argW[1] = 10 * cm t._argW[2] = 11.5 * cm t._argW[3] = 3 * cm for i, value in enumerate(data): if len(value) == 0: t._argH[i] = 7 continue for cell in value: if isinstance(cell, list): t._argH[i] = (rowHeights) * ( len(cell) - (0 if len(cell) > 1 else 0)) break elements.append(t) #print('table fim', datetime.now()) #print('build ini', datetime.now()) doc = SimpleDocTemplate( response, pagesize=landscape(A4), rightMargin=1.25 * cm, leftMargin=1.25 * cm, topMargin=1.1 * cm, bottomMargin=0.8 * cm) doc.build(elements)
def build_pdf(self, response): cleaned_data = self.filterset.form.cleaned_data agrupamento = cleaned_data['agrupamento'] elements = [] #print('data ini', datetime.now()) data = self.get_data() #print('data fim', datetime.now()) style = TableStyle([ ('FONTSIZE', (0, 0), (-1, -1), 8), ('LEADING', (0, 0), (-1, -1), 7), ('GRID', (0, 0), (-1, -1), 0.1, colors.black), ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), ('LEFTPADDING', (0, 0), (-1, -1), 3), ('RIGHTPADDING', (0, 0), (-1, -1), 3), ]) style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE') #print('enumerate ini', datetime.now()) for i, value in enumerate(data): if len(value) <= 1: style.add('SPAN', (0, i), (-1, i)) if len(value) == 0: style.add('INNERGRID', (0, i), (-1, i), 0, colors.black), style.add('GRID', (0, i), (-1, i), -1, colors.white) style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black) if len(value) == 1: style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black) #print('enumerate fim', datetime.now()) # if not agrupamento or agrupamento == 'sem_agrupamento': # style.add('ALIGN', (0, 0), (0, -1), 'CENTER') #print('table ini', datetime.now()) rowHeights = 20 t = LongTable(data, rowHeights=rowHeights, splitByRow=True) t.setStyle(style) if len(t._argW) == 5: t._argW[0] = 1.8 * cm t._argW[1] = 6 * cm t._argW[2] = 6.5 * cm t._argW[3] = 9.5 * cm t._argW[4] = 2.4 * cm elif len(t._argW) == 4: t._argW[0] = 2 * cm t._argW[1] = 10 * cm t._argW[2] = 11.5 * cm t._argW[3] = 3 * cm for i, value in enumerate(data): if len(value) == 0: t._argH[i] = 7 continue for cell in value: if isinstance(cell, list): t._argH[i] = (rowHeights) * (len(cell) - (0 if len(cell) > 1 else 0)) break elements.append(t) #print('table fim', datetime.now()) #print('build ini', datetime.now()) doc = SimpleDocTemplate(response, pagesize=landscape(A4), rightMargin=1.25 * cm, leftMargin=1.25 * cm, topMargin=1.1 * cm, bottomMargin=0.8 * cm) doc.build(elements)
def appendEvaluationList(obj, document): elemList = [] if hasattr(obj, 'requirement') \ and obj.requirement is not None: my_catalog = zapi.getUtility(ICatalog) res = my_catalog.searchResults(oid_index=obj.requirement) if len(res) > 0: requirementObj = iter(res).next() reqTitle = requirementObj.ikName reqComment = requirementObj.ikComment elemList.append(RptPara(reqTitle, doc=document)) elemList.append(RptPara(reqComment, doc=document)) elemList.append(Spacer(0, 4 * mm)) # Evaluations Done evaluations = getEvaluationsDone(obj) if len(evaluations) > 0: styleSheet = getRptStyleSheet() style1 = styleSheet['Small'] style2 = styleSheet['Infobox'] elemList.append( RptPara('Evaluations Done: ', style=style2, doc=document)) colWidths = [15 * mm, 60 * mm, 20 * mm, 40 * mm] data = [[ RptPara('<b>Pos</b>', style=style1, doc=document), RptPara('<b>Requirement</b>', style=style1, doc=document), RptPara('<b>Value</b>', style=style1, doc=document), RptPara('<b>Evaluator</b>', style=style1, doc=document) ]] rowColor = getTabBackgroundColor() rowColorLight = getTabBackgroundColorLight() ik_tbl_style = TableStyle([\ ('BACKGROUND', (0, 0), (-1, 0), rowColor), ('LEFTPADDING', (0, 0), (-1, -1), 1 * mm), ('RIGHTPADDING', (0, 0), (-1, -1), 1 * mm), ('BOTTOMPADDING', (0, 0), (-1, -1), 1 * mm), ('TOPPADDING', (0, 0), (-1, -1), 2 * mm), ('FONTSIZE', (0, 0), (-1, -1), 8), ('ALIGN', (0, 0), (-1, -1), 'LEFT'), ('ROWBACKGROUNDS',(0,0),(-1,-1),[rowColor, rowColorLight]), ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), ('BOX', (0, 0), (-1, -1), 0.25, colors.black), ]) pos = 0 for evaluation in evaluations.values(): pos = pos + 1 if evaluation.value == 'Pass': ik_tbl_style.add('BACKGROUND', (2, pos), (2, pos), colors.green) elif evaluation.value == 'Fail': ik_tbl_style.add('BACKGROUND', (2, pos), (2, pos), colors.red) else: pass if len(evaluation.requirement) == 0: data.append([ RptPara(evaluation.requirement.getIndexString(), style=style1, doc=document), RptPara(evaluation.requirement.ikName, style=style1, doc=document), RptPara(evaluation.value, style=style1, doc=document), RptPara(evaluation.evaluator.title, style=style1, doc=document), ]) t0 = Table(data, hAlign='RIGHT', style=ik_tbl_style, colWidths=colWidths) elemList.append(t0) elemList.append(Spacer(0, 3 * mm)) # Evaluations ToDo evaluations = getEvaluationsTodo(obj) if len(evaluations) > 0: styleSheet = getRptStyleSheet() style1 = styleSheet['Small'] style2 = styleSheet['Infobox'] elemList.append( RptPara('Evaluations ToDo: ', style=style2, doc=document)) #colWidths = [75 * mm, 20 * mm, 40 * mm] colWidths = [15 * mm, 120 * mm] data = [[ RptPara('<b>Pos</b>', style=style1, doc=document), RptPara('<b>Requirement</b>', style=style1, doc=document), #RptPara('<b>Value</b>', style=style1, doc=document), #RptPara('<b>Evaluator</b>', style=style1, doc=document) ]] rowColor = getTabBackgroundColor() rowColorLight = getTabBackgroundColorLight() ik_tbl_style = TableStyle([\ ('BACKGROUND', (0, 0), (-1, 0), rowColor), ('LEFTPADDING', (0, 0), (-1, -1), 1 * mm), ('RIGHTPADDING', (0, 0), (-1, -1), 1 * mm), ('BOTTOMPADDING', (0, 0), (-1, -1), 1 * mm), ('TOPPADDING', (0, 0), (-1, -1), 2 * mm), ('FONTSIZE', (0, 0), (-1, -1), 8), ('ALIGN', (0, 0), (-1, -1), 'LEFT'), ('ROWBACKGROUNDS',(0,0),(-1,-1),[rowColor, rowColorLight]), ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), ('BOX', (0, 0), (-1, -1), 0.25, colors.black), ]) #pos = 0 for evaluation in evaluations: # pos = pos + 1 # if evaluation.value == 'Pass': # ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos), colors.green) # elif evaluation.value == 'Fail': # ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos), colors.red) # else: # pass if len(evaluation.keys()) == 0: data.append([ RptPara(evaluation.getIndexString(), style=style1, doc=document), RptPara(evaluation.ikName, style=style1, doc=document), # RptPara(evaluation.value, # style=style1, # doc=document), # RptPara(evaluation.evaluator.title, # style=style1, # doc=document), ]) t0 = Table(data, hAlign='RIGHT', style=ik_tbl_style, colWidths=colWidths) elemList.append(t0) elemList.append(Spacer(0, 3 * mm)) return elemList
def pdf(group, username, list, show_header=True, show_footer=True): """PDF version of list""" content = BytesIO() columns = list.column_set.all() accounts = list.accounts() margin = 0.5 * cm font_name = "Times-Roman" font_name_bold = "Times-Bold" font_size = 12 font_size_small = 10 font_size_min = 8 head_height = 30 # pt foot_height = 15 # pt logo_height = 25 # pt font_size_name = font_size_small font_size_short_name = font_size_small font_size_balance = font_size_small if list.orientation == list.LANDSCAPE: height, width = A4 else: width, height = A4 grid_style = TableStyle(parent=GRID_STYLE) # Create canvas for page and set fonts p = canvas.Canvas(content, (width, height)) show_logo = bool(group.logo and group.logo.storage.exists(group.logo.path)) if show_logo: # Find scaling ratio ratio = group.logo.width / group.logo.height # Load logo with correct scaling logo = Image( group.logo.path, width=logo_height * ratio, height=logo_height ) def draw_header(): if not show_header: return if show_logo: logo.drawOn( p, width - margin - logo_height * ratio, height - margin - logo_height, ) # Setup rest of header p.setFont(font_name, font_size) p.drawString( margin, height - margin - font_size, f"{group}: {list.name}" ) p.setFont(font_name, font_size_small) p.drawString( margin, height - margin - font_size - font_size + 2, "%s: %s %s %s" % (_("Printed"), str(date.today()), _("by"), username), ) footer = [] if group.email: footer.append(group.email) if group.account_number: footer.append(group.get_account_number_display()) if list.comment.strip(): footer.append(list.comment.replace("\n", " ").replace("\r", " ")) def draw_footer(): if not show_footer: return p.drawString(margin, margin, " - ".join(footer)) blacklisted_note = _("Blacklisted accounts are marked with: ") p.drawRightString(width - margin - 10, margin, blacklisted_note) p.setFillColor(BLACKLISTED_COLOR) p.rect(width - margin - 10, margin, 8, 8, fill=1, stroke=0) p.setFont(font_name, font_size) if not accounts: no_accounts_message = _("Sorry, this list is empty.") draw_header() p.drawString( margin, height - font_size - margin - head_height, no_accounts_message, ) draw_footer() p.save() return content elif not columns: no_columns_message = _( "Sorry, this list isn't set up correctly, " "please add some columns." ) draw_header() p.drawString( margin, height - font_size - margin - head_height, no_columns_message, ) draw_footer() p.save() return content # Store col widths col_width = [] header = [_("Name")] if list.account_width: col_width.append(list.account_width) if list.short_name_width: col_width.append(list.short_name_width) if list.account_width and list.short_name_width: header.append("") if list.balance_width: header.append(_("Balance")) col_width.append(list.balance_width) if list.short_name_width > 0 and list.account_width > 0: grid_style.add("SPAN", (0, 0), (1, 0)) base_x = len(header) for c in columns: header.append(c.name) col_width.append(c.width) # Calculate relative col widths over to absolute points for i, w in enumerate(col_width): col_width[i] = ( float(w) / float( (list.listcolumn_width or 0) + list.balance_width + (list.account_width or 0) + (list.short_name_width or 0) ) * (width - 2 * margin) ) # Intialise table with header data = [header] for i, a in enumerate(accounts): color = ALTERNATE_COLORS[(i + 1) % len(ALTERNATE_COLORS)] if list.double: i *= 2 extra_row_height = 1 else: extra_row_height = 0 i += 1 grid_style.add("BACKGROUND", (0, i), (-1, i + extra_row_height), color) row = [] if list.account_width: row.append(a.name) # Check if we need to reduce col font size while ( col_width[len(row) - 1] < p.stringWidth(row[-1], font_name, font_size_name) + 12 and font_size_name > font_size_min ): font_size_name -= 1 if list.short_name_width: short_name = a.short_name if not short_name and a.owner: short_name = a.owner.username row.append(short_name or a.name) # Check if we need to reduce col font size while ( col_width[len(row) - 1] < p.stringWidth(row[-1], font_name, font_size_name) + 12 and font_size_short_name > font_size_min ): font_size_short_name -= 1 if list.balance_width: row.append("%d" % a.normal_balance()) # XXX: currently warnings are only shown if balance is shown, this # if needs to be moved if you want to change that if a.needs_warning(): grid_style.add( "FONTNAME", (0, i), (base_x - 1, i), font_name_bold ) grid_style.add( "TEXTCOLOR", (base_x - 1, i), (base_x - 1, i), WARN_TEXT_COLOR, ) # Check if we need to reduce col font size while ( col_width[len(row) - 1] < p.stringWidth(str(row[-1]), font_name, font_size_balance) + 12 and font_size_balance > font_size_min ): font_size_balance -= 1 if a.is_blocked(): if list.balance_width: grid_style.add( "TEXTCOLOR", (base_x - 1, i), (base_x - 1, i), BLACKLISTED_TEXT_COLOR, ) grid_style.add( "FONTNAME", (0, i), (base_x - 1, i), font_name_bold ) grid_style.add( "BACKGROUND", (base_x, i), (-1, i + extra_row_height), BLACKLISTED_COLOR, ) row.extend([""] * len(header[base_x:])) else: row.extend(header[base_x:]) data.append(row) if list.double: data.append([""] * len(row)) grid_style.add("SPAN", (0, i), (0, i + extra_row_height)) if list.balance_width: grid_style.add("SPAN", (1, i), (1, i + extra_row_height)) grid_style.add("FONTSIZE", (0, 0), (-1, -1), font_size_small) # Set font size for names grid_style.add("FONTSIZE", (0, 1), (0, -1), font_size_name) grid_style.add("ALIGN", (0, 0), (-1, -1), "LEFT") grid_style.add("ALIGN", (base_x, 0), (-1, -1), "RIGHT") grid_style.add("FONTNAME", (0, 0), (-1, 0), font_name_bold) # Set font size for balance if list.balance_width: grid_style.add( "FONTSIZE", (base_x - 1, 1), (base_x - 1, -1), font_size_balance ) grid_style.add("ALIGN", (base_x - 1, 1), (base_x - 1, -1), "RIGHT") grid_style.add("TEXTCOLOR", (base_x, 1), (-1, -1), FAINT_COLOR) if list.double: grid_style.add("TOPPADDING", (base_x, 1), (-1, -1), 2) grid_style.add("BOTTOMPADDING", (base_x, 1), (-1, -1), 2) grid_style.add("VALIGN", (0, 1), (-1, -1), "TOP") grid_style.add("GRID", (0, 0), (-1, -1), 0.25, BORDER_COLOR) # Create table t = Table(data, colWidths=col_width, style=grid_style, repeatRows=1) rest = None avail_w = width - 2 * margin avail_h = height - 2 * margin - head_height - foot_height while t: # Figure out how big table will be t_width, t_height = t.wrapOn(p, avail_w, avail_h) if not rest and t_height > height - 2 * margin - head_height: t, rest = t.split(avail_w, avail_h) continue # Draw on canvas draw_header() t.drawOn(p, margin, height - t_height - margin - head_height) draw_footer() if rest: # set t to the second table and reset rest t, rest = (rest, None) # Show new page p.showPage() else: # Leave loop break p.save() return content
def appendEvaluationList(obj, document): elemList = [] if hasattr(obj, 'requirement') \ and obj.requirement is not None: my_catalog = zapi.getUtility(ICatalog) res = my_catalog.searchResults(oid_index=obj.requirement) if len(res) > 0: requirementObj = iter(res).next() reqTitle = requirementObj.ikName reqComment = requirementObj.ikComment elemList.append(RptPara(reqTitle, doc=document)) elemList.append(RptPara(reqComment, doc=document)) elemList.append(Spacer(0, 4 * mm)) # Evaluations evaluations = getEvaluations(obj) if len(evaluations) > 0: styleSheet = getRptStyleSheet() style1 = styleSheet['Small'] style2 = styleSheet['Infobox'] elemList.append(RptPara('Evaluations: ', style=style2, doc=document)) colWidths = [75 * mm, 20 * mm, 40 * mm] data = [[ RptPara('<b>Requirement</b>', style=style1, doc=document), RptPara('<b>Value</b>', style=style1, doc=document), RptPara('<b>Evaluator</b>', style=style1, doc=document) ]] ik_tbl_style = TableStyle([\ ('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey), ('LEFTPADDING', (0, 0), (-1, -1), 2 * mm), ('RIGHTPADDING', (0, 0), (-1, -1), 2 * mm), ('BOTTOMPADDING', (0, 0), (-1, -1), 2 * mm), ('TOPPADDING', (0, 0), (-1, -1), 2 * mm), ('FONTSIZE', (0, 0), (-1, -1), 8), ('ALIGN', (0, 0), (-1, -1), 'LEFT'), ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), ('BOX', (0, 0), (-1, -1), 0.25, colors.black), ]) pos = 0 for evaluation in evaluations.values(): pos = pos + 1 if evaluation.value == 'Pass': ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos), colors.green) elif evaluation.value == 'Fail': ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos), colors.red) else: pass data.append([ RptPara(evaluation.requirement.ikName, style=style1, doc=document), RptPara(evaluation.value, style=style1, doc=document), RptPara(evaluation.evaluator.title, style=style1, doc=document), ]) t0 = Table(data, hAlign='RIGHT', style=ik_tbl_style, colWidths=colWidths) elemList.append(t0) elemList.append(Spacer(0, 4 * mm)) return elemList
def _get_style(self, rows): ''' set TableStyle add styles for row/col blocks style.add('SPAN', (col_s, row_s), (col_e, row_e)) also set row heights ''' _get_idxs = lambda x: self._get_idxs(rows, x) _get_se = lambda x: (x[0][0], x[-1][0]) # (col, row) style = TableStyle() title_row = 0 sample_row = 1 sample_row2 = 2 name_row = 3 unit_row = 4 style.add('GRID', (0, 0), (-1, -1), 0.25, colors.red) style.add('ALIGN', (0, unit_row), (-1, -1), 'LEFT') style.add('LEFTPADDING', (0, unit_row), (-1, -1), 1) # set style for title row if self.add_title: style.add('SPAN', (0, title_row), (-1, title_row)) style.add('LINEBELOW', (0, 0), (-1, 0), 1.5, colors.black) # set style for sample row for s, e in self._sample_summary_row1.spans: style.add('SPAN', (s, sample_row), (e, sample_row)) style.add('LINEBELOW', (s, sample_row), (e, sample_row), 1.5, colors.black) for s, e in self._sample_summary_row2.spans: style.add('SPAN', (s, sample_row2), (e, sample_row2)) # set style for name header style.add('LINEABOVE', (0, name_row), (-1, name_row), 1.5, colors.black) # set style for unit header style.add('LINEBELOW', (0, unit_row), (-1, unit_row), 1.5, colors.black) # set style for summary rows # summary_idxs = [(i, v) for i, v in enumerate(rows) # if isinstance(v, SummaryRow)] summary_idxs = _get_idxs(SummaryRow) for idx, summary in summary_idxs: style.add('LINEABOVE', (0, idx), (-1, idx), 1.5, colors.black) for si, se in summary.spans: style.add('SPAN', (si, idx), (se, idx)) analysis_idxs = _get_idxs(AnalysisRow) sidx, eidx = _get_se(analysis_idxs) # sidx, eidx = analysis_idxs[0][0], analysis_idxs[-1][0] style.add('VALIGN', (0, sidx), (-1, eidx), 'MIDDLE') style.add('ALIGN', (0, sidx), (-1, eidx), 'CENTER') for idx, _analysis in analysis_idxs: if idx % 2 == 0: style.add('BACKGROUND', (0, idx), (-1, idx), colors.lightgrey, ) # set for footnot rows footnote_idxs = _get_idxs(FootNoteRow) sidx, eidx = _get_se(footnote_idxs) style.add('VALIGN', (0, sidx), (-1, eidx), 'MIDDLE') for idx, _v in footnote_idxs: style.add('SPAN', (0, idx), (-1, idx)) # style.add('VALIGN', (1, idx), (-1, idx), 'MIDDLE') footer_idxs = _get_idxs(FooterRow) sidx, eidx = _get_se(footer_idxs) style.add('VALIGN', (0, sidx), (-1, eidx), 'MIDDLE') for idx, v in footer_idxs: for si, se in v.spans: style.add('SPAN', (si, idx), (se, idx)) return style
def build_pdf(self, response): CONTATO = 0 TELEFONES_PREFERENCIAL = 1 CIDADE = 0 ENDERECO = 1 BAIRRO = 2 NUMERO = 3 GRUPO = 4 ID = 5 NOME = 6 self.set_headings() self.set_styles() self.set_cabec(self.h5) estilo = self.h_style corpo_relatorio = [] self.add_relat_title(corpo_relatorio) registros = self.get_data() for dados in registros: endereco = ','.join(dados[CONTATO][ENDERECO:NUMERO]) item = [ Paragraph(dados[CONTATO][CIDADE], estilo), Paragraph(dados[CONTATO][GRUPO], estilo), Paragraph(dados[CONTATO][NOME], estilo), Paragraph(endereco, estilo), Paragraph(dados[TELEFONES_PREFERENCIAL], estilo), ] corpo_relatorio.append(item) style = TableStyle([ ('FONTSIZE', (0, 0), (-1, -1), 8), ('LEADING', (0, 0), (-1, -1), 7), ('GRID', (0, 0), (-1, -1), 0.1, colors.black), ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), ('LEFTPADDING', (0, 0), (-1, -1), 3), ('RIGHTPADDING', (0, 0), (-1, -1), 3), ]) style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE') for i, value in enumerate(corpo_relatorio): if len(value) <= 1: style.add('SPAN', (0, i), (-1, i)) if len(value) == 0: style.add('INNERGRID', (0, i), (-1, i), 0, colors.black), style.add('GRID', (0, i), (-1, i), -1, colors.white) style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black) if len(value) == 1: style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black) rowHeights = 20 t = LongTable(corpo_relatorio, rowHeights=rowHeights, splitByRow=True) t.setStyle(style) if len(t._argW) == 5: t._argW[0] = 1.8 * cm t._argW[1] = 6 * cm t._argW[2] = 6.5 * cm t._argW[3] = 9.5 * cm t._argW[4] = 2.4 * cm elif len(t._argW) == 4: t._argW[0] = 2 * cm t._argW[1] = 10 * cm t._argW[2] = 11.5 * cm t._argW[3] = 3 * cm for i, value in enumerate(corpo_relatorio): if len(value) == 0: t._argH[i] = 7 continue for cell in value: if isinstance(cell, list): t._argH[i] = (rowHeights) * (len(cell) - (0 if len(cell) > 1 else 0)) break elements = [t] doc = SimpleDocTemplate(response, pagesize=landscape(A4), rightMargin=1.25 * cm, leftMargin=1.25 * cm, topMargin=1.1 * cm, bottomMargin=0.8 * cm) doc.build(elements)
def pdf(request, guid): import settings import reportlab.pdfgen.canvas from reportlab.lib import pagesizes, units, colors, utils from reportlab.platypus import Paragraph, Image from reportlab.platypus.tables import Table, TableStyle from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet from django.contrib.humanize.templatetags.humanize import intcomma company = fact.models.Slot.company() invoice = get_object_or_404(fact.models.Invoice, pk=guid) if not invoice.date_posted or not invoice.date_due: return redirect(reverse('fact.views.detailed', kwargs={'guid':guid})) response = HttpResponse(mimetype='application/pdf') response['Content-Disposition'] = 'attachment; filename=' + _('invoice') + '-' + invoice.id + '.pdf' p = reportlab.pdfgen.canvas.Canvas(response, pagesize=pagesizes.A4) width, height = pagesizes.A4 font = 'Helvetica' # Load options and payment text options = fact.models.Option.opt_list(request.LANGUAGE_CODE) for key, value in options.iteritems(): options['payment_text'] = options['payment_text'].replace('%' + key + '%', value) options['payment_text'] = options['payment_text'].replace('\n', '<br/>') # Right-hand stuff x = units.cm * 14; p.setFont(font + '-Bold', 18) p.drawString(x, height-(units.cm*4.5), _('Invoice %s') % invoice.id) p.setFont(font, 10) p.drawString(x, height-(units.cm*5.5), _('Invoice date: %s') % invoice.date_invoice.strftime('%d.%m.%Y')) p.drawString(x, height-(units.cm*6), _('Due date: %s') % invoice.date_due.strftime('%d.%m.%Y')) # Logo img = utils.ImageReader(settings.FACT_LOGO) iw, ih = img.getSize() aspect = ih / float(iw) img = Image(settings.FACT_LOGO, width=units.cm*4, height=units.cm*4*aspect) img.drawOn(p, x+(units.cm*1), height-(units.cm*2.25)) # Left-hand header stuff x = units.cm * 2; p.setFont(font + '-Oblique', 8) p.drawString(x, height-(units.cm*1.25), company['name']) address = company['address'].split("\n") base = 1.65 for a in address: p.drawString(x, height-(units.cm*base), a) base += 0.4 # Recipient name and address y = units.cm*4.5 base = 0.5 customer = invoice.customer p.setFont(font, 10) p.drawString(x, height-y, customer.addr_name); y += units.cm*base p.drawString(x, height-y, customer.addr_addr1); y += units.cm*base p.drawString(x, height-y, customer.addr_addr2); y += units.cm*base p.drawString(x, height-y, customer.addr_addr3); y += units.cm*base p.drawString(x, height-y, customer.addr_addr4); y += units.cm*base y += units.cm*2 # Main p.setFont(font + '-Bold', 14) p.drawString(x, height-y, _('Specification')) y += units.cm*1 p.setFont(font, 10) fmt = '{0:.2f}' # Get our invoice entries, headers, etc style = TableStyle() invoice_entries = [] headers = [_('Description'), _('Amount'), _('Type'), _('Unit price'), _('VAT'), _('Net')] style.add('FONT', (0,0), (-1,0), font + '-Bold') style.add('LINEBELOW', (0,0), (-1,0), 1, colors.black) for entry in invoice.entries: invoice_entries.append([ entry.description, intcomma(fmt.format(entry.quantity)), _(entry.action), intcomma(fmt.format(entry.unitprice)), intcomma(fmt.format(entry.tax_percent)) + '%', intcomma(fmt.format(entry.net)) ]) style.add('LINEBELOW', (0, len(invoice_entries)), (-1, len(invoice_entries)), 1, colors.black) sums = [] sums.append([_('Net'), '', '', '', '', intcomma(fmt.format(invoice.net))]) sums.append([_('VAT'), '', '', '', '', intcomma(fmt.format(invoice.tax))]) if invoice.payments.count() > 0: sums.append([_('Subtotal'), '', '', '', '', intcomma(fmt.format(invoice.gross))]) style.add('LINEBELOW', (0, len(invoice_entries)+3), (-1, len(invoice_entries)+3), 1, colors.black) for payment in invoice.payments.all(): sums.append([_('Paid %s') + payment.post_date.strftime('%d.%m.%Y'), '', '', '', '', intcomma(fmt.format(payment.amount))]) ln = len(invoice_entries) + len(sums) style.add('LINEBELOW', (0, ln), (-1, ln), 1, colors.black) else: style.add('LINEBELOW', (0, len(invoice_entries)+2), (-1, len(invoice_entries)+2), 1, colors.black) sums.append([_('Amount due'), '', '', '', '', intcomma(fmt.format(invoice.due))]) ln = len(invoice_entries) + len(sums) style.add('BACKGROUND', (0, ln), (-1, ln), colors.wheat) style.add('FONT', (0, ln), (-1, ln), font + '-Bold') style.add('LINEBELOW', (0, ln), (-1, ln), 2, colors.black) # Draw the table t = Table([headers] + invoice_entries + sums, ([units.cm*6.5, units.cm*1.75, units.cm*2, units.cm*2.5, units.cm*2, units.cm*2.25]) ) t.setStyle(style) w, h = t.wrapOn(p, units.cm*19, units.cm*8) y += h t.drawOn(p, x, height-y) # Bank account number stylesheet = getSampleStyleSheet() if invoice.notes: txt = invoice.notes + '<br/><br/>' else: txt = '' txt += options['payment_text'] pr = Paragraph(txt, stylesheet['BodyText']) w, h = pr.wrapOn(p, units.cm*17, units.cm*6) y += pr.height + (units.cm*1) pr.drawOn(p, x, height-y) # Footer stuff p.setFont(font + '-BoldOblique', 8) p.drawString(x, units.cm*2.8, company['name']) p.setFont(font + '-Oblique', 8) p.drawString(x, units.cm*2.4, address[0]) p.drawString(x, units.cm*2, address[1]) p.drawString(units.cm*8, units.cm*2.4, 'Web: ' + company['url']) p.drawString(units.cm*8, units.cm*2, 'E-post: ' + company['email']) p.drawString(units.cm*14, units.cm*2.4, 'Telefon: ' + company['phone']) p.drawString(units.cm*14, units.cm*2, 'Org.nr: ' + company['id']) # Close the PDF object cleanly, and we're done. p.showPage() p.save() return response