def plate(request): try: o = Order.objects.filter(session=request.shop_session, is_history=True).latest('id') config, create = ConfigModel.objects.get_or_create(id=1) domain = Site.objects.get_current().domain except: pass else: if config.organization and config.office1 and o.address and o.name: pdf = FPDF('P','mm','A4') pdf.set_author(domain) pdf.add_page() pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True) pdf.add_font('DejaVuBold', '', 'DejaVuSansCondensed-Bold.ttf', uni=True) pdf.set_fill_color(229, 229, 229); pdf.set_font('DejaVu', '', 5); pdf.write(9, _(u"Created by %(date)s on %(domain)s. Order #%(id)d.") % {'date':datetime.datetime.now().strftime('%d.%m.%Y %H:%M'), 'domain':domain, 'id':o.id}) pdf.ln(9) pdf.set_font('DejaVuBold', '', 9); pdf.write(9, _(u"Recipient:")) pdf.ln(9) pdf.set_font('DejaVu', '', 8); if config.office1: pdf.write(5, _(u"Address: %s") % config.office1) pdf.ln(5) if config.organization: pdf.write(5, _(u"Name: %s") % config.organization) pdf.ln(5) pdf.set_font('DejaVuBold', '', 9); pdf.write(9, _(u"Sender:")) pdf.ln(9) pdf.set_font('DejaVu', '', 8); if o.address: pdf.write(5, _(u"Address: %s") % o.address) pdf.ln(5) if o.name: pdf.write(5, _(u"Name: %s") % o.name) pdf.ln(9) pdf.set_font('DejaVu', '', 5); pdf.write(5, _(u"Cut and paste on the packaging")) pdf.ln(5) s = pdf.output('Plate.pdf', 'S') response = HttpResponse(s, mimetype='application/pdf; charset=cp1251') response['Content-Disposition'] = 'attachment; filename=plate.pdf' return response return HttpResponse('')
def pokepdf(pokemon): # FPDF Object pdf = FPDF("L", "mm", "A5") # Add page pdf.add_page() # Paint the background pdf.set_fill_color(*color.get(pokemon["type"][0], (255, ))) pdf.rect(0, 0, 210, 297, "F") # Set font pdf.set_font(*fonts["title"]) pdf.set_xy(20, 10) # Add Pokeball ball = {False: "pokeball", True: "masterball"}[pokemon["legendary"]] pdf.image(f"images/balls/{ball}.png", pdf.get_x(), pdf.get_y() + 25, w=20) # Add Pokemon Name pdf.cell(w=0, txt=f"{pokemon['id']} - {pokemon['name']}".title(), align="C", ln=1) # Add Pokemon Sprite pdf.image(pokemon["sprite_url"], 80, pdf.get_y() + 10, w=50) # Set new font font = fonts["flavor"] pdf.set_font(*font) pdf.set_xy(10, 70) # Cut text if larger than page flavor = chunks(pokemon["flavor"], font) # Add flavor text for i in flavor: pdf.cell(w=0, h=5, txt=i, align="C", ln=2) # Add type symbols for i, typ in enumerate(pokemon["type"]): if len(pokemon["type"]) == 1: pos = [90] else: pos = [50, 120] pdf.image(f"images/types/{typ}.png", pos[i], pdf.get_y() + 15, w=40) # Export pdf path = f"output/{pokemon['id']}_{pokemon['name']}.pdf" pdf.output(path) print(f"pdf saved to {path}")
def relatedness(ibd_dataframe, outDir): dups_text = open(outDir + '/' + 'duplicate_pairs.txt', 'w') # outputs pairs with Z0, Z1, Z2 score remove_dups = open(outDir + '/remove_all_duplicate_pairs.txt', 'w') # outputs duplicate samples for PLINK format removal pdf = FPDF() # create new PDF pdf.add_page() pdf.set_margins(20, 10, 20) pdf.set_font('Arial', 'B', 24) pdf.set_x(20) pdf.multi_cell(0, 30, "Relatedness", 0, 1, 'L') pdf.line(20, 32, 190, 32) pdf.set_font('Arial', 'B', 16) pdf.set_fill_color(200) pdf.multi_cell(0, 10, 'Total Number of Sample Pairs Analyzed: ' + str(len(ibd_dataframe.index)), 1, 'L', True) duplicates = ibd_dataframe.loc[ibd_dataframe['Z2'] > 0.97] parent_offspring = ibd_dataframe.loc[(ibd_dataframe['Z1'] > 0.97) & (ibd_dataframe['Z0'] < 0.05) & (ibd_dataframe['Z2'] < 0.05)] full_sibs = ibd_dataframe.loc[(ibd_dataframe['Z0'] < 0.40) & (ibd_dataframe['Z2'] > 0.16)] second_degree = ibd_dataframe.loc[(ibd_dataframe['Z0'] < 0.60) & (ibd_dataframe['Z1'] < 0.58) & (ibd_dataframe['Z2'] < 0.05)] unrelated = ibd_dataframe.loc[ibd_dataframe['Z0'] > 0.78] # format data so it can be put into usable format by PLINK --remove first_in_pair = duplicates[['FID1', 'IID1']] second_in_pair = duplicates[['FID2', 'IID2']] first_in_pair.columns = ['FID', 'IID'] second_in_pair.columns = ['FID', 'IID'] merged_removals = first_in_pair.merge(second_in_pair, how='outer', on=['FID', 'IID']) print merged_removals[['FID', 'IID']] merged_removals[['FID', 'IID']].to_csv(remove_dups.name, sep='\t', index=False, header=False) # output file created to PLINK --remove pdf.set_font('Arial', '', 16) pdf.set_x(30) pdf.multi_cell(0, 10, '# of duplicate pairs: '+str(len(duplicates.index)), 1, 1, 'L') pdf.set_x(30) pdf.multi_cell(0, 10, '# of parent-offspring pairs: '+str(len(parent_offspring.index)), 1, 1, 'L') pdf.set_x(30) pdf.multi_cell(0, 10, '# of full siblings pairs: '+str(len(full_sibs.index)), 1, 1, 'L') pdf.set_x(30) pdf.multi_cell(0, 10, '# of 2nd degree pairs: '+str(len(second_degree.index)), 1, 1, 'L') pdf.set_x(30) pdf.multi_cell(0, 10, '# of unrelated pairs: '+str(len(unrelated.index)), 1, 1, 'L') duplicates.to_csv(dups_text.name, sep='\t', index=False) return pdf, remove_dups.name
def export_as_pdf(): pdf = FPDF() pdf.add_page() pdf.set_font('Times', '', 8) epw = pdf.w - 3 * pdf.l_margin col_width = epw / 2 data = data_pdf th = pdf.font_size for row in data: for datum in row: if datum == row[0]: pdf.set_fill_color(135, 206, 235) pdf.multi_cell(col_width, 2 * th, str(datum), border=1, align='C', fill=True) else: pdf.multi_cell(col_width, 2 * th, str(datum), border=1, align='C') pdf.ln(2 * th) for row in data_cena_pdf: for datum in row: if datum == row[0]: pdf.set_fill_color(143, 237, 143) pdf.multi_cell(col_width, 2 * th, str(datum), border=1, align='C', fill=True) else: pdf.multi_cell(col_width, 2 * th, str(datum), border=1, align='C') pdf.ln(2 * th) html = create_download_link( pdf.output(dest='S').encode('Latin-1'), "Menu") return st.markdown(html, unsafe_allow_html=True)
def w_content(self, content_record): # InputType: self, List # ReturnType: No return, will create a content PDF "export_content.pdf" based on recognized text PDF # Functionality: Create content PDF for better indexing page number of desired image text. print(' Creating content for recognized images...') pdf_content = FPDF() pdf_content.add_page() pdf_content.set_font('Times', 'B', 18) pdf_content.set_fill_color(r=160) pdf_content.cell(w=180, h=9, txt='CONTENT', border=0, ln=1, align='C', fill=1) pdf_content.set_font('Times', '', 12) pdf_content.multi_cell(w=0, h=5, txt=''.join(content_record)) pdf_content.output("export_content.pdf") pdf_content.close()
def PDF(address, portscan, filename): try: date = datetime.now() date = date.strftime('%Y/%m/%d %X') pdf = FPDF() pdf.add_page() pdf.set_font('Courier', '', 20) pdf.cell(0, 25, "\tASILE-B") pdf.image('./files/img/Orange.png', 180, 15, 15, 15) pdf.ln() pdf.set_font('Courier', '', 12) pdf.cell(0, 15, 'Scan report : ') pdf.ln() pdf.cell(0, 5, "\t\t\t\tIP address\t: {}".format(address)) pdf.ln() pdf.cell(0, 5, "\t\t\t\tDate\t\t\t\t\t\t\t: {}".format(date)) pdf.ln() pdf.cell( 0, 5, "\t\t\t\tOpen ports\t: {}".format(len(list(portscan.keys())))) pdf.ln() pdf.ln() pdf.ln() pdf.set_fill_color(0, 0, 0) pdf.cell(190 / 4, 5, "Port number", 1, 0, 'C') pdf.cell(190 / 4, 5, "Status", 1, 0, 'C') pdf.cell(190 / 4, 5, "Service", 1, 0, 'C') pdf.cell(190 / 4, 5, "Credentials", 1, 0, 'C') for port in list(portscan.keys()): pdf.ln() pdf.cell(190 / 4, 5, port, 1, 0, 'C') pdf.cell(190 / 4, 5, 'open', 1, 0, 'C') if portscan[port][1] == 0: pdf.cell(190 / 4, 5, '{}*'.format(portscan[port][0]), 1, 0, 'C') pdf.cell(190 / 4, 5, '', 1, 0, 'C') elif portscan[port][1] == 1: pdf.cell(190 / 4, 5, portscan[port][0], 1, 0, 'C') if len(portscan[port]) == 3: pdf.cell(190 / 4, 5, portscan[port][2], 1, 0, 'C') else: pdf.cell(190 / 4, 5, 'not found', 1, 0, 'C') pdf.output('files/pdf/{}.pdf'.format(filename), 'F') except: return b'Error', 'html'
def test_local_context_inherited_shared_props(tmp_path): "The only thing that should differ between the 2 squares is their opacity" pdf = FPDF() pdf.add_page() pdf.set_font("Helvetica", "", 12) pdf.set_draw_color(0, 128, 255) pdf.set_fill_color(255, 128, 0) pdf.set_line_width(2) pdf.set_dash_pattern(dash=0.5, gap=9.5, phase=3.25) with pdf.local_context( fill_opacity=0.5): # => triggers creation of a local GraphicsStyle pdf.rect(x=60, y=60, w=60, h=60, style="DF") pdf.rect(x=60, y=150, w=60, h=60, style="DF") assert_pdf_equal(pdf, HERE / "local_context_inherited_shared_props.pdf", tmp_path)
def printReport(): df = pd.read_csv("OUTPUT/HDIrank2019_02_mergedDataframes.csv") df = df.drop(columns="Unnamed: 0") reg = df.groupby("region").mean().drop( columns=["HDIrank", "LastYearRank"]).T.round(2) pdf = FPDF('P', 'mm', 'A4') pdf.add_page() font_type = ('Arial', 'B', 16) num_col = 6 w, h = 190, 277 pdf.set_font(*font_type) pdf.set_text_color(0) pdf.set_draw_color(0) pdf.cell(w, 10, 'Datos Acumulados', 1, 1, 'C') pdf.set_line_width(0.2) for col in reg.columns: pdf.cell(w / num_col, 10, col, 1, 0, 'C') pdf.ln() pdf.set_fill_color(243, 95, 95) font_type = ('Arial', '', 12) pdf.set_font(*font_type) ''' NOT WORKING! def fit_word(string,cell_w,font_type): ver = FPDF() #font_type(font,style,size)) ver.set_font(*font_type) # if string fits, return it unchanged if ver.get_string_width(string)<cell_w: return string # cut string until it fits while ver.get_string_width(string)>=cell_w: string = string[:-1] # replace last 3 characters with "..." string = string[:-3] + "..." return string ''' for index, row in reg.iterrows(): for value in reg.columns: pdf.cell(w / num_col, 10, row[value], 1, 0, 'C', 0) pdf.ln() pdf.output("OUTPUT/report.pdf", 'F') return "Repo done"
def createPDF(self): pdf = FPDF() pdf.add_page() pdf.set_font('Arial', 'B', 18) # header pdf.image("images/ImagLogo.GIF", 170, 3, 25) pdf.cell(0, 10, "Report", border=False, ln=1, align="C") pdf.ln() #####General Information pdf.set_font('Arial', 'B', 12) pdf.set_fill_color(213, 201, 239) pdf.cell(0, 9, 'General Information', 0, 1, 'L', 1) pdf.ln(3) pdf.line(8, 20, 150, 20) pdf.set_font('Arial', 'IB', 13) pdf.cell( 130, 10, txt="Paitant ID : " + self.P_ID + " ", ln=1, align='E', ) pdf.set_font('Arial', 'B', 12) pdf.cell(130, 10, txt="Check up No:", align="W") pdf.cell(100, 10, txt=" Test Result Data: " + datetime.date.today().strftime("%d-%m-%y"), ln=1, align="E") ##Result pdf.ln() pdf.set_font('Arial', 'B', 12) pdf.set_fill_color(213, 201, 239) pdf.cell(0, 9, ' Result Infromation', 0, 1, 'L', 1) pdf.image(self.imagePa, 90, 100, 100) pdf.ln() pdf.set_font('Arial', 'B', 16) pdf.cell(0, 10, txt=" The disease is " + self.result + "", align="W") # footer pdf.set_font('Arial', '', 13) pdf.set_auto_page_break(auto=True, margin=15) pdf.set_y(270) pdf.cell(0, 10, f'Page {pdf.page_no()}/nb', align="C") pdf.alias_nb_pages(alias='nb') # add another cell pdf.output("results/" + self.P_ID + ".pdf")
def generatePDF(userid, maxportfolioid): sql_statement = "SELECT symbol, purchase_price, lot_size from portfolio where userid = %s and portfolioid = %s" data = (userid, maxportfolioid) connection = DBconnection(sql_statement, data) Symbol = [i[0] for i in connection] PurchasePrice = [i[1] for i in connection] Lot_Size = [i[2] for i in connection] pdf = FPDF() #header of the pdf file header = 'Specifically curated for ' + str(userid) pdf.add_page() pdf.set_font('Arial', 'B', 16) w = pdf.get_string_width(header) + 6 pdf.set_x((210 - w) / 2) pdf.cell(w, 9, header, 0, 0, 'C') pdf.line(20, 18, 210 - 20, 18) pdf.ln(10) pdf.set_font('Times', '', 12) pdf.multi_cell( 0, 5, 'Here is a list of suggested financial instruments for your peruse.') for i in range(len(Symbol)): pdf.ln() pdf.set_font('Arial', '', 12) pdf.set_fill_color(200, 220, 255) pdf.cell( 0, 6, 'Financial Instrument ' + str(i + 1) + ": " + str(Symbol[i]) + " Unit Price " + str(PurchasePrice[i]) + " Lot Size " + str(Lot_Size[i]), 0, 1, 'L', 1) pdf.ln() pdf.set_font('Courier', 'B', 12) pdf.multi_cell( 0, 5, 'A detailed analysis on ' + Symbol[i] + '---------------') #pdf.set_y(0) #on top of the page pdf.set_y(-30) #30 CM from the bottom of the page pdf.set_font('Arial', '', 8) pdf.set_text_color(0) pdf.cell(0, 5, 'Page ' + str(pdf.page_no()), 0, 0, 'C') pdf.output(str(userid) + '.pdf', 'F') return pdf
def create_pdf_page(codes_array, start, stop, pdf=None): """creates a single pdf page from codes_array[start:stop] Arguments: codes_array {[list]} -- [list of codes] start {[int]} -- [starting index] stop {[int]} -- [stop index] Keyword Arguments: pdf {[filepath]} -- [path to pdf to be appended to] (default: {None = new one will be created}) """ if not pdf: pdf = FPDF(orientation='P', unit='mm', format='A4') pdf.set_font('Arial') pdf.set_font_size(16) pdf.set_margins(3, 3.5, 3) pdf.set_auto_page_break(False) pdf.add_page() # two rows i = start for y in range(3, 149, 145): # 4 per row for x in range(3, 157, 51): if i > stop: return offset = (x, y + 0.5) # ticket offset_padding = (offset[0] + 1.5, offset[1] + 1.5) pdf.set_xy(offset[0], offset[1]) pdf.set_fill_color(150, 10, 10) pdf.cell(51, 145, "", 1, 1, 'c', True) code = codes_array[i] image_tempfile = create_qr(code) pdf.image(image_tempfile.name, offset_padding[0], offset_padding[1], 48, 48, 'PNG') os.unlink(image_tempfile.name) image_tempfile.close() pdf.set_xy(offset_padding[0], offset[1] + 51) pdf.set_fill_color(10, 150, 10) pdf.cell(48, 6, str(code), 1, 1, 'C', True) pdf.set_xy(offset_padding[0], offset[1] + 58.5) pdf.cell(48, 85, fill=True) i += 1
def build_chart(self, output_name, mins): length = len(protein_seq(self)) chunks = Chart.get_bits(self) pdf = FPDF('L') pdf.add_page() height = (125 / len(self.struct_sequences[1:])) / len(chunks[0][0][0]) mult = height - 1 for i in range(len(chunks)): for m in range(len(chunks[i])): for z in range(len(chunks[i][m])): r, g, b = float(chunks[i][m][z][0]), float( chunks[i][m][z][1]), float(chunks[i][m][z][2]) pdf.set_fill_color(r, g, b) pdf.rect((z + (z * .9)) + 2, ((m + (mult * m) + (i * 60) + 5)), 1.9, height, style='F') pdf.line((0 + (0 * .9)) + 2, (m + (mult * m) + (i * 60) + 5), (z + (z * .9)) + 3.9, (m + (mult * m) + (i * 60) + 5)) pdf.set_font("Arial", style='B', size=5.5) pieces = get_chunks(self) for Y in range(len(chunks)): for B in range(len(pieces[Y])): pdf.text((B + (B * .9)) + 2.2, ((Y * 60) + 4.5), pieces[Y][B]) option_list = ['Helix', 'Coil', 'Strand'] for q in range(3): red = float(mins[q][0]) green = float(mins[q][1]) blue = float(mins[q][2]) pdf.set_font("Arial", style='B', size=18) pdf.set_fill_color(red, green, blue) pdf.rect(230, (q * 7) + q + 185, 15, 7, style='F') pdf.text(247, (q * 7) + q + 190, option_list[q]) pdf.output(output_name)
def generate_pdf(card, qrcode_enabled=True) -> str: """ Make a PDF from a card :param card: dict from fetcher.py :return: Binary PDF buffer """ from eclaire.base import SPECIAL_LABELS, MAX_LABEL_CHARS pdf = FPDF("L", "mm", (62, 140)) pdf.set_margins(2.8, 2.8, 2.8) pdf.set_auto_page_break(False, margin=0) pdf.add_page() font = pkg_resources.resource_filename("eclaire", "font/Clairifont.ttf") pdf.add_font("Clairifont", fname=font, uni=True) pdf.set_font("Clairifont", size=40) pdf.multi_cell(0, 18, txt=card.name.upper(), align="L") if qrcode_enabled: qrcode = generate_qr_code(card.shortUrl) qrcode_file = mktemp(suffix=".png", prefix="trello_qr_") qrcode.save(qrcode_file) pdf.image(qrcode_file, 118, 35, 20, 20) os.unlink(qrcode_file) # May we never speak of this again. pdf.set_fill_color(255, 255, 255) pdf.rect(0, 55, 140, 20, "F") pdf.set_font("Clairifont", "", 14) pdf.set_y(-4) labels = ", ".join([ label.name for label in card.labels if label.name not in SPECIAL_LABELS ])[:MAX_LABEL_CHARS] pdf.multi_cell(0, 0, labels, 0, "R") return pdf.output(dest="S").encode("latin-1")
def output_pdf(logger, all_news, about_website=None, file_name=None): """Function which create or overwrites PDF-file with selected fresh or cached news""" logger.info('Convert to PDF-format') pdf = FPDF() pdf.add_page() if about_website is not None: pdf.set_font("Arial", "B", size=14) pdf.set_fill_color(200, 220, 255) for value in about_website.values(): line = 1 pdf.cell(190, 8, txt=value, ln=line, align="C") line += 1 pdf.set_font("Arial", size=10) pdf.set_line_width(1) pdf.set_draw_color(35, 41, 153) for news in all_news: link = news['Source of image'] for key, value in news.items(): if key != 'Summary': pdf.multi_cell(190, 6, txt=f'{key}: {value}', align="L") else: position_y = pdf.get_y() try: filename, _ = urllib.request.urlretrieve(link) pdf.image(filename, 80, position_y, h=30, type='jpeg', link=link) pdf.ln(31) os.remove(filename) except Exception as ex: logger.warning("Error finding image: {}, {}.".format(type(ex), ex)) pdf.multi_cell(190, 6, txt=f'{key}: {value}', align="L") position_y = pdf.get_y() pdf.set_line_width(1) pdf.set_draw_color(35, 41, 153) pdf.line(10, position_y, 200, position_y) logger.info('Creating of PDF-file') try: pdf.output(file_name) logger.info('Converted successfully!') except Exception as ex: logger.error("PDF file writing error : {}, {}.".format(type(ex), ex))
def test_graphics_context(tmp_path): pdf = FPDF() pdf.add_page() pdf.set_font("helvetica", "", 12) pdf.set_text_color(0x00, 0xFF, 0x00) pdf.set_fill_color(0xFF, 0x88, 0xFF) pdf.set_y(20) pdf.cell(txt="outer 01", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) with pdf.local_context(): pdf.set_font("courier", "BIU", 30) pdf.set_text_color(0xFF, 0x00, 0x00) pdf.set_fill_color(0xFF, 0xFF, 0x00) pdf.cell(txt="inner 01", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) pdf.set_x(70) with pdf.rotation(30, pdf.get_x(), pdf.get_y()): pdf.set_fill_color(0x00, 0xFF, 0x00) pdf.cell(txt="inner 02", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) pdf.set_stretching(150) pdf.cell(txt="inner 03", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) pdf.cell(txt="outer 02", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) assert_pdf_equal(pdf, HERE / "graphics_context.pdf", tmp_path)
def change_data_to_pdf(data): pdf = FPDF(orientation='L', unit='mm') # pdf = fpdf.FPDF('L', 'mm', format=(30, 10)) pdf = fpdf.FPDF(format='A4') pdf.add_page() pdf.set_font("Arial", size=12,) pdf.cell(150, 10, txt="Results Sheet", ln=1, align="C") # border styling pdf.set_line_width(1) pdf.set_fill_color(0, 255, 0) pdf.rect(2, 2, 205, 160) # excel cell data text = f""" Name: {data[1]} Father Name: {data[2]} subject Math: {data[3]} Chemistry: {data[4]} Biology: {data[5]} Geology: {data[6]} English: {data[7]} Average score: Final Result: """ # show excel data pdf.set_right_margin(444) pdf.multi_cell(150, 9, text, align='R') # adding Image pdf.image('images/1_jobs.jpeg', x=50, y=50, w=50) # pdf.cell(400, 40, txt="{}".format('images/Ahmad.jpeg'), ln=1) pdf.ln() pdf.output("File.pdf")
def generate_pdf(card): """ Make a PDF from a card :param card: dict from fetcher.py :return: Binary PDF buffer """ from eclaire.base import SPECIAL_LABELS pdf = FPDF('L', 'mm', (62, 140)) pdf.set_margins(2.8, 2.8, 2.8) pdf.set_auto_page_break(False, margin=0) pdf.add_page() font = pkg_resources.resource_filename('eclaire', 'font/Clairifont.ttf') pdf.add_font('Clairifont', fname=font, uni=True) pdf.set_font('Clairifont', size=48) pdf.multi_cell(0, 18, txt=card.name.upper(), align='L') qrcode = generate_qr_code(card.url) qrcode_file = mktemp(suffix='.png', prefix='trello_qr_') qrcode.save(qrcode_file) pdf.image(qrcode_file, 118, 35, 20, 20) os.unlink(qrcode_file) # May we never speak of this again. pdf.set_fill_color(255, 255, 255) pdf.rect(0, 55, 140, 20, 'F') pdf.set_font('Clairifont', '', 16) pdf.set_y(-4) labels = ', '.join([ label.name for label in card.labels if label.name not in SPECIAL_LABELS ]) pdf.multi_cell(0, 0, labels, 0, 'R') return pdf.output(dest='S')
def generate_pdf(card): """ Make a PDF from a card :param card: dict from fetcher.py :return: Binary PDF buffer """ from eclaire.base import SPECIAL_LABELS pdf = FPDF('L', 'mm', (62, 140)) pdf.set_margins(2.8, 2.8, 2.8) pdf.set_auto_page_break(False, margin=0) pdf.add_page() font = pkg_resources.resource_filename('eclaire', 'font/Clairifont.ttf') pdf.add_font('Clairifont', fname=font, uni=True) pdf.set_font('Clairifont', size=48) pdf.multi_cell(0, 18, txt=card.name.upper(), align='L') qrcode = generate_qr_code(card.url) qrcode_file = mktemp(suffix='.png', prefix='trello_qr_') qrcode.save(qrcode_file) pdf.image(qrcode_file, 118, 35, 20, 20) os.unlink(qrcode_file) # May we never speak of this again. pdf.set_fill_color(255, 255, 255) pdf.rect(0, 55, 140, 20, 'F') pdf.set_font('Clairifont', '', 16) pdf.set_y(-4) labels = ', '.join([label.name for label in card.labels if label.name not in SPECIAL_LABELS]) pdf.multi_cell(0, 0, labels, 0, 'R') return pdf.output(dest='S')
def pdf(location, x): print('Trwa generowanie pliku pdf.') pdf = FPDF() pdf.add_page() pdf.set_xy(0, 0) pdf.set_font('arial', style='', size=14) pdf.cell(40) logo = ''.join([location, '\\' + x + '.png']) pdf.image(logo, x=90, y=15, w=pdf.w / 2.0, h=pdf.h / 5.0) pdf.ln(5) pdf.cell(40, 20, 'Raport ze strony ' + x) pdf.ln(10) pdf.cell(30, 15, str(date.today())) pdf.ln(65) pdf.cell(0, 15, 'Kolory:') pdf.ln(15) for line in open(''.join([location, '\\colors.txt'])): colors = line.split(" ") red, green, blue = hex_rgb(colors[0]) pdf.set_fill_color(red, green, blue) pdf.cell(30, 15, ' ', fill=True) pdf.cell(30, 15, str(colors[0]), fill=False) pdf.cell(20) pdf.cell(10, 15, str(colors[1]), fill=False) pdf.ln(15) pdf.ln(15) pdf.cell(15) pdf.cell(30, 15, 'Tablice pixeli:') pdf.ln(10) pdf.x = 5 img1 = cv2.imread(''.join([location, '\\fig1.png'])) img2 = cv2.imread(''.join([location, '\\fig2.png'])) figure = np.concatenate((img1, img2), axis=1) cv2.imwrite('out.png', figure) pdf.image('out.png', x=None, y=None, w=pdf.w / 1.1, h=pdf.h / 4.0) os.remove("out.png") pdf.output(x + '.pdf', 'F')
def heterozygosity(het_dataframe, thresh, minThresh, outDir): pdf = FPDF() # create new PDF pdf.add_page() pdf.set_margins(20, 10, 20) pdf.set_font('Arial', 'B', 24) pdf.set_x(20) pdf.multi_cell(0, 30, "Heterozygosity", 0, 1, 'L') pdf.line(20, 32, 190, 32) sample_fails = open(outDir + '/samples_failing_heterozygosity.txt', 'w') fail_het = het_dataframe.loc[((het_dataframe['F'] > thresh) | (het_dataframe['F'] < minThresh))] fail_het[['FID', 'IID']].to_csv(sample_fails.name, sep='\t', index=False, header=False) # format it FID <tab> IID <new line> # sorts inbreeing coeffiecient score to rank for ploting het_dataframe.sort_values(by='F', ascending=True, axis=0, inplace=True) het_dataframe = het_dataframe.reset_index() het_dataframe['rank'] = het_dataframe.index pdf.set_font('Arial', '', 12) pdf.multi_cell(0, 5, 'Heterozygosity is calculated on the merged sample space. Samples with extreme levels of heterozygosity as measured by \ the F inbreeding coefficient, may be indicative of a sample exhibiting poor quality. The current inbreeding coefficient threshold is set \ to ' + str(thresh) + '. Any F value above this threshold is filtered out.', 0, 1, 'J') pdf.multi_cell(0, 5, '\n', 0, 1, 'J') pdf.set_font('Arial', 'B', 16) pdf.set_fill_color(200) pdf.multi_cell(0, 8, 'Total Number Samples Analyed: '+ str(len(het_dataframe.index)), 1, 'L', True) pdf.set_x(30) pdf.multi_cell(0, 8, 'Total Number Samples Failing: '+ str(len(fail_het.index)), 1, 1, 'L') het_dataframe.plot(kind='scatter', x='rank', y='F', title='Ranked Inbreeding Coefficient scores', s=7) plt.tight_layout(pad=2, w_pad=2, h_pad=2) plt.savefig(outDir+'/'+'heterozygosity_plot.png') plt.close() pdf.image(outDir+'/'+'heterozygosity_plot.png', x=10, y=130, w=190, h=150) return sample_fails.name, pdf
def createpdf(path_image, savepath, results): # Generate FPDF object and add page pdf = FPDF("P", "mm", "A4") # (orientation, unit, format) pdf.add_page() # Vision logo pdf.image("images/logo.png", x=160, y=20, w=39, h=26) # Title pdf.set_font("Arial", "B", 28) # (letter type, style, size) pdf.set_text_color(4, 23, 34) #pdf.set_draw_color(220,220,220) # give color to borders pdf.set_fill_color(255, 255, 255) # backgrund cell color pdf.set_xy(25, 40) pdf.cell(0, 20, "OCT Diagnostic", 0, 2, "C", True) # Image pdf.image(path_image, x=120, y=80, w=59, h=59) # Text pdf.set_font("Arial", "", 12) pdf.set_text_color(10, 10, 10) pdf.cell(25, 20, "", 0, 2, "L") pdf.cell(0, 15, f"Choroidal Neovascularization : {round(results[0]*100, 2)} %", 0, 2, "L") pdf.cell(0, 15, f"Diabetic Macular Edema : {round(results[1]*100, 2)} %", 0, 2, "L") pdf.cell(0, 15, f"Drusen : {round(results[2]*100, 2)} %", 0, 2, "L") pdf.cell(0, 15, f"Normal : {round(results[3]*100, 2)} %", 0, 2, "L") # Save File pdf.output(f"{savepath}.pdf", "F")
def createpdf(country, owner): # Generate FPDF object and add page pdf = FPDF("P", "mm", "A4") # (orientation, unit, format) pdf.add_page() # Title pdf.set_font("Courier", "B", 20) # (letter type, style, size) pdf.set_text_color(15, 20, 85) #pdf.set_draw_color(220,220,220) # give color to borders pdf.set_fill_color(200, 200, 200) if country == "Both": pdf.cell(0, 20, f"Mortality in Ghana and Spain - Report", 0, 1, "C", True) else: pdf.cell(0, 20, f"{country} hospitals - mortality report", 0, 1, "C", True) #FPDF.set_title(title = f"{country} hospitals - mortality report") # Image pdf.image("OUTPUT/graphic.png", x=25, y=40, w=150, h=110) # Text pdf.set_font("Arial", "", 12) pdf.set_text_color(10, 10, 10) txt = situation(country, owner) report = writing_analysis(txt, country) #pdf.cell(0, 240, report) #FPDF.text(x=0, y=140, report) #FPDF.set_xy(0.00, 10.00) pdf.set_xy(25, 160) pdf.write(10, report) # Save File pdf.output("OUTPUT/Report.pdf", "F")
def some_initialisations(self, copyname): document = FPDF(orientation='P', unit='mm', format='A4') doctitle = "Tax invoice - " + copyname document.set_title(doctitle) document.set_margins( 20, 20, 20 ) # left, top, right...... Define before creating page, otherwise will ruin formatting #Libreoffice ref: 11pt=3.88mm, 48 lines @1.2, 50 lines @1.15, 38 lines @1.5 line spacing # big character to font height is 75% approx. #space to char ht: 89%, 99%, 75%, 153% respectively for 1.15, 1.2, 1 and 1.5 line spacing #net char height for 11pt is 3.88*.75=2.91 mm #net space height for 11pt is 2.59 @1.15, 2.88 @1.2, 2.18 @1, 4.45 @1.5 # cell ht: 5.5 @1.15, 5.8 @1.2, 5.1 @1, 7.35 @1.5 #There is no page for the moment, so we have to add one with add_page. document.add_page() document.set_font("Times", size=11) document.set_text_color(20, 20, 20) document.set_fill_color(255, 255, 255) # cell fill colour, visible if cell property fill set to true document.set_draw_color(175, 175, 175) # border color, used for all drawing operations (lines, rectangles and cell borders) return document
def minor_allele_freq(dictMAF, thresh): pdf = FPDF() # create new PDF pdf.add_page() pdf.set_margins(20, 10, 20) pdf.set_font('Arial', 'B', 24) pdf.set_x(20) pdf.multi_cell(0, 30, "Minor Allele Frequency", 0, 1, 'L') pdf.line(20, 32, 190, 32) pdf.set_font('Arial', 'B', 16) pdf.set_fill_color(200) # iterate through all ethnic groups for LD pruning stats for key, value in dictMAF.iteritems(): pdf.multi_cell(0, 8, str(key), 1, 'L', True) pdf.set_x(30) pdf.multi_cell(0, 8, 'Total Number of SNPs analyzed: ' + str(value[0]), 1, 1, 'L') pdf.set_x(30) pdf.multi_cell(0, 8, 'Total Number of SNPs MAF >= ' + str(thresh) + ': ' + str(value[1]) + ' (' + str("%.2f" % round((float(value[1])/float(value[0]))*100, 2)) + '%)', 1, 1, 'L') pdf.set_x(30) pdf.multi_cell(0, 8, 'Total Number of SNPs MAF <= ' + str(thresh) + ': ' + str(value[2]) + ' (' + str("%.2f" % round((float(value[2])/float(value[0]))*100, 2)) + '%)', 1, 1, 'L') pdf.multi_cell(0, 8, '\n\n', 0, 1, 'J') return pdf
# Process strip data for name, numbers in config['strips'].items(): # Log print(f'Writing {name}.pdf:', end='') # Prepare PDF pdf = FPDF( orientation=config['papersize']['orientation'], format=config['papersize']['name'], unit='mm', ) pdf.add_page() pdf.set_fill_color(0, 0, 0) # Parse data strips = parse_strips(numbers) thickness = sum(strips) # Draw lines start = (float(config['papersize']['width']) - thickness) / 2 black = True y = 0 for th in strips: if (black): pdf.rect( x=0, y=start + y, w=float(config['papersize']['height']),
# .set_text_color(r,g=-1,b=-1) pdf.set_text_color(198, 21, 21) pdf.cell(190, 10, 'print("Hello, World!")', "LRB", 1, 'C') pdf.set_font('Arial', 'B', 16) pdf.set_text_color(0) pdf.cell(95, 10, "C", 1, 0, 'C') # .set_draw_color(r,g,b) pdf.set_draw_color(198, 21, 21) # .set_line_width(size) in user defined unit pdf.set_line_width(1) pdf.cell(95, 10, "Python", 1, 0, 'C') pdf.set_draw_color(4, 139, 63) pdf.set_fill_color(4, 139, 63) pdf.line(10, 50, 200, 10) pdf.set_draw_color(4, 139, 63) pdf.set_fill_color(4, 139, 63) # .rect(x,y,w,h,style) pdf.rect(10, 60, 190, 10, 'DF') pdf.set_draw_color(198, 21, 21) pdf.set_fill_color(198, 21, 21) # use parameter as values for i in range(72, 157, 12): pdf.rect(10, i, 190, 10, 'DF') # .image for jpeg, png and gif images pdf.image('zamora.png',
class kut2fpdf(object): _document = None # Aquí se irán guardando los datos del documento logger = None _xml = None _xml_data = None _page_orientation = None _page_size = None _bottom_margin = None _left_margin = None _right_margin = None _top_margin = None _page_top = {} _data_row = None # Apunta a la fila actual en data _parser_tools = None _avalible_fonts = [] def __init__(self): self.logger = logging.getLogger("kut2rml") checkDependencies({"fpdf": "fpdf"}) from pineboolib.plugins.kugar.parsertools import parsertools self._parser_tools = parsertools() """ Convierte una cadena de texto que contiene el ".kut" en un pdf y retorna la ruta a este último. @param name. Nombre de ".kut". @param kut. Cadena de texto que contiene el ".kut". @param data. Cadena de texto que contiene los datos para ser rellenados en el informe. @return Ruta a fichero pdf. """ def parse(self, name, kut, data): try: self._xml = self._parser_tools.loadKut(kut) except Exception: self.logger.exception( "KUT2FPDF: Problema al procesar %s.kut", name) return False try: self._xml_data = load2xml(data) except Exception: self.logger.exception("KUT2FPDF: Problema al procesar xml_data") return False self.setPageFormat(self._xml) # self._page_orientation = # self._page_size = from fpdf import FPDF self._document = FPDF(self._page_orientation, "pt", self._page_size) # Seteamos rutas a carpetas con tipos de letra ... # Cargamos las fuentes disponibles for f in self._document.core_fonts: self.logger.debug("KUT2FPDF :: Adding font %s", f) self._avalible_fonts.append(f) self.newPage() self.processDetails() pdfname = pineboolib.project.getTempDir() pdfname += "/%s_%s.pdf" % (name, datetime.datetime.now().strftime("%Y%m%d%H%M%S")) # Datos del creador del documento self._document.set_title(name) self._document.set_author("Pineboo - kut2fpdf plugin") self._document.output(pdfname, 'F') return pdfname """ Indica el techo para calcular la posición de los objetos de esa sección. @return Número con el techo de la página actual. """ def topSection(self): return self._page_top[str(self._document.page_no())] """ Actualiza el valor del techo de la página actual. Se suele actualizar al procesar una sección. @param value. Numero que elspecifica el nuevo techo. """ def setTopSection(self, value): self._page_top[str(self._document.page_no())] = value """ Añade una nueva página al documento. """ def newPage(self): self._document.add_page(self._page_orientation) self._page_top[str(self._document.page_no())] = self._top_margin self._document.set_margins(self._left_margin, self._top_margin, self._right_margin) # Lo dejo pero no se nota nada # Corta con el borde inferior ... # self._document.set_auto_page_break( # True, self._document.h - self._bottom_margin) self.processSection("PageHeader") """ Procesa las secciones details con sus correspondientes detailHeader y detailFooter. """ def processDetails(self): # Procesamos la cabecera si procede .. prevLevel = 0 level = None for data in self._xml_data.findall("Row"): level = int(data.get("level")) if prevLevel > level: self.processData("DetailFooter", data, prevLevel) elif prevLevel < level: self.processData("DetailHeader", data, level) self.processData("Detail", data, level) prevLevel = level if level: for l in reversed(range(level + 1)): self.processData("DetailFooter", data, l) if self._xml.find("PageFooter"): self.processSection("PageFooter") elif self._xml.find("AddOnFooter"): self.processSection("AddOnFooter") """ Paso intermedio que calcula si detailHeader + detail + detailFooter entran en el resto de la ṕagina. Si no es así crea nueva página. @param section_name. Nombre de la sección a procesar. @param data. Linea de datos a procesar. @param data_level. Nivel de seccion. """ def processData(self, section_name, data, data_level): listDF = self._xml.findall(section_name) for dF in listDF: if dF.get("Level") == str(data_level): if section_name == "Detail" and (not dF.get("DrawIf") or data.get(dF.get("DrawIf"))): heightCalculated = self._parser_tools.getHeight(dF) + self.topSection() for dFooter in self._xml.findall("DetailFooter"): if dFooter.get("Level") == str(data_level): heightCalculated += self._parser_tools.getHeight(dFooter) pageFooter = self._xml.get("PageFooter") if pageFooter: if self._document.page_no() == 1 or pageFooter.get("PrintFrecuency") == "1": heightCalculated += self._parser_tools.getHeight(pageFooter) heightCalculated += self._bottom_margin if heightCalculated > self._document.h: # Si nos pasamos self.processSection("PageFooter") # Pie de página self.newPage() if not dF.get("DrawIf") or data.get(dF.get("DrawIf")): self.processXML(dF, data) #self.logger.debug("%s_BOTTON = %s" % (name.upper(), self.actualVSize[str(self.pagina)])) """ Procesa las secciones fuera de detail, pageHeader, pageFooter, AddOnFooter. @param name. Nombre de la sección a procesar. """ def processSection(self, name): sec_ = self._xml.find(name) if sec_: if sec_.get("PrintFrequency") == "1" or self._document.page_no() == 1: if sec_.tag == "PageFooter": self.setTopSection(self._document.h - int(sec_.get("Height"))) self.processXML(sec_) """ Procesa un elemento de xml. @param xml: El elemento a procesar. @param. data: Linea de datos afectada. """ def processXML(self, xml, data=None): fix_height = True if xml.tag == "DetailFooter": if xml.get("PlaceAtBottom") == "true": self.setTopSection(self.topSection() + self._parser_tools.getHeight(xml)) if xml.tag == "PageFooter": fix_height = False for child in xml.iter(): if child.tag in ("Label", "Field", "Special", "CalculatedField"): self.processText(child, data, fix_height) elif child.tag == "Line": self.processLine(child, fix_height) if xml.get("PlaceAtBottom") != "true": self.setTopSection(self.topSection() + self._parser_tools.getHeight(xml)) """ Procesa una linea. @param xml. Sección de xml a procesar. @param fix_height. Ajusta la altura a los .kut originales, excepto el pageFooter. """ def processLine(self, xml, fix_height=True): color = xml.get("Color") r = 0 if not color else int(color.split(",")[0]) g = 0 if not color else int(color.split(",")[1]) b = 0 if not color else int(color.split(",")[2]) #style = int(xml.get("Style")) width = int(xml.get("Width")) X1 = self.calculateLeftStart(xml.get("X1")) X2 = self.calculateRightEnd(xml.get("X2")) # Ajustar altura a secciones ya creadas Y1 = int(xml.get("Y1")) + self.topSection() Y2 = int(xml.get("Y2")) + self.topSection() if fix_height: Y1 = self._parser_tools.heightCorrection(Y1) Y2 = self._parser_tools.heightCorrection(Y2) self._document.set_line_width(width) self._document.set_draw_color(r, g, b) self._document.line(X1, Y1, X2, Y2) """ Comprueba si excedemos el margen izquierdo de la página actual @param x. Posición a comprobar. @return Valor corregido, si procede. """ def calculateLeftStart(self, x): x = int(x) ret_ = x if x < self._left_margin: ret_ = self._left_margin return ret_ """ Comprueba si excedemos el margen derecho de la página actual @param x. Posición a comprobar. @return Valor corregido, si procede. """ def calculateRightEnd(self, x): x = int(x) ret_ = x if x > (self._document.w - self._right_margin): ret_ = self._document.w - self._right_margin return ret_ """ Procesa una etiqueta. Esta peude ser un campo calculado, una etiqueta, un campo especial o una imagen. @param xml. Sección de xml a procesar. @param fix_height. Ajusta la altura a los .kut originales, excepto el pageFooter. """ def processText(self, xml, data_row=None, fix_height=True): isImage = False text = xml.get("Text") BorderWidth = int(xml.get("BorderWidth")) borderColor = xml.get("BorderColor") # x,y,W,H se calcula y corrigen aquí para luego estar correctos en los diferentes destinos posibles W = int(xml.get("Width")) H = self._parser_tools.getHeight(xml) x = int(xml.get("X")) y = int(xml.get("Y")) + self.topSection() # Añade la altura que hay ocupada por otras secciones if fix_height: y = self._parser_tools.heightCorrection(y) # Corrige la posición con respecto al kut original dataType = xml.get("Datatype") if xml.tag == "Field" and data_row is not None: text = data_row.get(xml.get("Field")) elif xml.tag == "Special": text = self._parser_tools.getSpecial( text[1:len(text) - 1], self._document.page_no()) elif xml.tag == "CalculatedField": if xml.get("FunctionName"): function_name = xml.get("FunctionName") try: nodo = self._parser_tools.convertToNode(data_row) text = str(pineboolib.project.call(function_name, [nodo])) except Exception: self.logger.exception( "KUT2FPDF:: Error llamando a function %s", function_name) return else: if data_row is None: data_row = self._xml_data[0] if xml.get("Field"): text = data_row.get( xml.get("Field")) if not "None" else "" if text and dataType is not None: text = self._parser_tools.calculated(text, int(dataType), xml.get("Precision"), data_row) if dataType == "5": isImage = True if text and text.startswith(filedir("../tempdata")): isImage = True precision = xml.get("Precision") negValueColor = xml.get("NegValueColor") Currency = xml.get("Currency") commaSeparator = xml.get("CommaSeparator") dateFormat = xml.get("DateFormat") if not isImage: self.drawText(x, y, W, H, xml, text) else: self.drawImage(x, y, W, H, xml, text) """ Dibuja un campo texto en la página. @param x. Pos x de la etiqueta. @param y. Pos y de la etiqueta. @param W. Anchura de la etiqueta. @param H. Altura de la etiqueta. @param xml. Sección del xml afectada. @param txt. Texto calculado de la etiqueta a crear. """ def drawText(self, x, y, W, H, xml, txt): if txt in ("None", None): return # Corregimos margenes: x = self.calculateLeftStart(x) W = self.calculateRightEnd(x + W) - x bg_color = xml.get("BackgroundColor").split(",") fg_color = xml.get("ForegroundColor").split(",") self._document.set_text_color(int(fg_color[0]), int(fg_color[1]), int(fg_color[2])) self._document.set_fill_color(int(bg_color[0]), int(bg_color[1]), int(bg_color[2])) if xml.get("BorderStyle") == "1": # FIXME: Hay que ajustar los margenes self.drawRect(x, y, W, H) #font_name, font_size, font_style font_style = "" font_size = int(xml.get("FontSize")) font_name = xml.get("FontFamily").lower() fontW = int(xml.get("FontWeight")) fontI = xml.get("FontItalic") fontU = xml.get("FontUnderlined") # FIXME: hay que ver si es así if fontW > 60 and font_size > 10: font_style += "B" if fontI == "1": font_style += "I" if fontU == "1": font_style += "U" while font_name not in self._avalible_fonts: font_found = self._parser_tools.find_font(font_name) if font_found: self.logger.info("KUT2FPDF::Añadiendo el tipo de letra %s (%s)", font_name, font_found) self._document.add_font(font_name, "", font_found, True) self._avalible_fonts.append(font_name) else: self.logger.warning("KUT2FPDF:: No se encuentra el tipo de letra %s. Sustituido por helvetica.", font_name) font_name = "helvetica" self._document.set_font(font_name, font_style, font_size) # Corregir alineación VAlignment = xml.get("VAlignment") # 0 izquierda, 1 centrado,2 derecha HAlignment = xml.get("HAlignment") if HAlignment == "1": # sobre X # Centrado x = x + (W / 2) - (self._document.get_string_width(txt) / 2) elif HAlignment == "2": # Derecha x = x + W - self._document.get_string_width(txt) else: # Izquierda x = x if VAlignment == "1": # sobre Y # Centrado y = (y + H / 2) + (self._document.font_size_pt / 2) elif VAlignment == "2": # Abajo y = y + W - font_size else: # Arriba y = y self._document.text(x, y, txt) """ Dibuja un cuadrado en la página actual. @param x. Pos x del cuadrado. @param y. Pos y del cuadrado. @param W. Anchura del cuadrado. @param H. Altura del cuadrado. """ def drawRect(self, x, y, W, H): self._document.rect(x, y, W, H, "DF") """ Inserta una imagen en la página actual. @param x. Pos x de la imagen. @param y. Pos y de la imagen. @param W. Anchura de la imagen. @param H. Altura de la imagen. @param xml. Sección del xml afectada. @param file_name. Nombr del fichero de tempdata a usar """ def drawImage(self, x, y, W, H, xml, file_name): self._document.image(file_name, x, y, W, H, "PNG") """ Define los parámetros de la página @param xml: Elemento xml con los datos del fichero .kut a procesar """ def setPageFormat(self, xml): custom_size = None self._bottom_margin = int(xml.get("BottomMargin")) self._left_margin = int(xml.get("LeftMargin")) self._right_margin = int(xml.get("RightMargin")) self._top_margin = int(xml.get("TopMargin")) page_size = int(xml.get("PageSize")) page_orientation = xml.get("PageOrientation") if page_size in [30, 31]: custom_size = [int(xml.get("CustomHeightMM")), int(xml.get("CustomWidthMM"))] self._page_orientation = "P" if page_orientation == "0" else "L" self._page_size = self._parser_tools.converPageSize( page_size, int(page_orientation), custom_size) # devuelve un array
def MakePDFMonthCal (year, month, calParams, outputFile): startMonth = 1 endMonth = 12 # Create a calendar instance if (calParams ['FirstDay'] == SUNDAY): cal = calendar.Calendar (calendar.SUNDAY) else: cal = calendar.Calendar (calendar.MONDAY) pdfFile = FPDF (orientation=calParams['PageOrientation'], unit='in', format='letter') pdfFile.add_page() pdfFile.set_left_margin (calParams['PageXOrigin']) pdfFile.set_top_margin (calParams['PageYOrigin']) calXOffset = 0 calYOffset = 0 calMonth = month fontStyle = '' if (calParams['FontBold'] == True): fontStyle += 'b' if (calParams['FontItalic'] == True): fontStyle += 'i' calHeight = calParams['PageHeight'] calWidth = calParams['PageWidth'] numCols = 1 numRows = 1 if (month == -1): pdfFile.set_draw_color (calParams['DebugColourR'], calParams['DebugColourG'], calParams['DebugColourB']) pdfFile.set_line_width (calParams['DebugLineThickness']) pdfFile.set_xy (calParams['PageXOrigin'], calParams['PageYOrigin']) pdfFile.set_font (calParams['Font'], style=fontStyle, size=INCH_TO_POINT*calParams['YearHeader']) pdfFile.set_text_color (calParams['FontColourR'], calParams['FontColourG'], calParams['FontColourB']) pdfFile.cell (calWidth-calParams['YearGridSpacing'], calParams['YearHeader'], txt=str(year), border=calParams['Debug'], align='C') calParams['PageYOrigin'] += (calParams['YearHeader'] + calParams['YearHeaderSpace']) if (calParams['PageOrientation'] == PORTRAIT): calHeight = (calParams['PageHeight'] - calParams['YearHeader'] - calParams['YearHeaderSpace']) / YEAR_MONTH_ROWS_PORT calWidth = calParams['PageWidth'] / YEAR_MONTH_COLS_PORT numCols = YEAR_MONTH_COLS_PORT numRows = YEAR_MONTH_ROWS_PORT else: calHeight = (calParams['PageHeight'] - calParams['YearHeader'] - calParams['YearHeaderSpace']) / YEAR_MONTH_ROWS_LAND calWidth = calParams['PageWidth'] / YEAR_MONTH_COLS_LAND numCols = YEAR_MONTH_COLS_LAND numRows = YEAR_MONTH_ROWS_LAND calHeight -= calParams['YearGridSpacing'] calWidth -= calParams['YearGridSpacing'] else: startMonth = month endMonth = month for calMonth in range (startMonth, endMonth+1): if (calParams['Debug']): pdfFile.set_draw_color (calParams['DebugColourR'], calParams['DebugColourG'], calParams['DebugColourB']) pdfFile.set_line_width (calParams['DebugLineThickness']) pdfFile.rect (calParams['PageXOrigin'] + calXOffset, calParams['PageYOrigin'] + calYOffset, calWidth, calHeight) # # Make title... # pdfFile.set_text_color (calParams['FontColourR'], calParams['FontColourG'], calParams['FontColourB']) if (calParams['TitleStyle'] == 1): pdfFile.set_xy (calParams['PageXOrigin'] + calXOffset, calParams['PageYOrigin'] + calYOffset) pdfFile.set_font (calParams['Font'], style=fontStyle, size=INCH_TO_POINT*calParams['BlockMonthTitleHeight']*calHeight) pdfFile.cell (calWidth, \ calParams['BlockMonthTitleHeight']*calHeight, \ txt=calendar.month_name[calMonth], \ border=calParams['Debug'], align='C') elif (calParams['TitleStyle'] == 2): pdfFile.set_font (calParams['Font'], style=fontStyle, size=INCH_TO_POINT*calParams['BlockMonthTitleHeight']*calHeight) monthFontWidth = pdfFile.get_string_width (calendar.month_name[calMonth]) yearFontWidth = pdfFile.get_string_width (str(year)) pdfFile.set_xy (calParams['PageXOrigin'] + calXOffset, calParams['PageYOrigin'] + calYOffset) pdfFile.cell (monthFontWidth, calParams['BlockMonthTitleHeight']*calHeight + calYOffset,\ txt=calendar.month_name[calMonth], border=calParams['Debug'], align='L') pdfFile.set_xy (calParams['PageXOrigin'] + calXOffset + calWidth - yearFontWidth, calParams['PageYOrigin'] + calYOffset) pdfFile.cell (yearFontWidth, calParams['BlockMonthTitleHeight']*calHeight + calYOffset,\ txt=str(year), border=calParams['Debug'], align='R') # # Weekday titles... # dayIndices = list ( range (0, NUMBER_WEEKDAYS) ) if (calParams ['FirstDay'] == SUNDAY): dayIndices.insert (0, NUMBER_WEEKDAYS-1) dayIndices.pop () fontScaleFactor, fontMaxWidth, fontMaxSize = FindMaxFontHeight (calParams['Font'], fontStyle, \ calParams['BlockDayTitleHeight'] * calHeight, \ calWidth/NUMBER_WEEKDAYS, \ MAX_WEEKDAY_STR) for day in range (0, NUMBER_WEEKDAYS): pdfFile.set_xy (calParams['PageXOrigin'] + calXOffset + calWidth * day / NUMBER_WEEKDAYS, \ calParams['PageYOrigin'] + calYOffset + (calParams['BlockMonthTitleHeight'] + calParams['BlockTitleSpace']) * calHeight) pdfFile.set_font (calParams['Font'], style=fontStyle, size=fontScaleFactor*calParams['BlockDayTitleHeight']*calHeight) if (calParams['DayTitleStyle'] == 1): pdfFile.cell (calWidth / NUMBER_WEEKDAYS, calParams['BlockDayTitleHeight'] * calHeight, \ txt=calendar.day_name[dayIndices[day]], border=calParams['Debug'], align='C') elif (calParams['DayTitleStyle'] == 2): pdfFile.cell (calWidth / NUMBER_WEEKDAYS, calParams['BlockDayTitleHeight'] * calHeight, \ txt=calendar.day_name[dayIndices[day]], border=calParams['Debug'], align='L') # Horizontal Lines if (calParams['HorizontalLines'] == True): pdfFile.set_line_width (calParams['HorizontalLineThickness']) pdfFile.set_draw_color (calParams['HorizontalLineColourR'], calParams['HorizontalLineColourG'], calParams['HorizontalLineColourB']) HorizontalLineAmount = calParams['HorizontalLineSpacing'] * GRID_ROWS for row in range (0, HorizontalLineAmount + 1): lineXStart = calParams['PageXOrigin'] + calXOffset lineXEnd = calParams['PageXOrigin'] + calXOffset + calWidth lineYStart = calParams['PageYOrigin'] + calYOffset + calHeight \ - (row / HorizontalLineAmount) * calParams['BlockDayRegionHeight'] * calHeight lineYEnd = lineYStart pdfFile.line (lineXStart, lineYStart, lineXEnd, lineYEnd) # boxes... if (calParams['DayGridStyle'] == 4): pdfFile.set_line_width (calParams['GridLineThickness']) pdfFile.set_draw_color (calParams['DayRegionColourR'], calParams['DayRegionColourG'], calParams['DayRegionColourB']) gridOffset = calParams['DayGridSpacing'] for col in range (0, NUMBER_WEEKDAYS): for row in range (0, GRID_ROWS): boxXStart = calParams['PageXOrigin'] + calXOffset + (col / NUMBER_WEEKDAYS) * calWidth + gridOffset boxXEnd = calWidth / NUMBER_WEEKDAYS - 2*gridOffset boxYStart = calParams['PageYOrigin'] + calYOffset + (1 - calParams['BlockDayRegionHeight']) * calHeight \ + calParams['BlockDayRegionHeight'] * calHeight * row / GRID_ROWS + gridOffset boxYEnd = calParams['BlockDayRegionHeight'] * calHeight / GRID_ROWS - 2*gridOffset drawStyle = 'D' if (calParams['DayGridInvert'] == True): pdfFile.set_fill_color (calParams['FontColourR'], calParams['FontColourG'], calParams['FontColourB']) drawStyle = 'F' pdfFile.rect (boxXStart, boxYStart, boxXEnd, boxYEnd, style=drawStyle) # circles if (calParams['DayGridStyle'] == 5 or calParams['DayGridStyle'] == 6): pdfFile.set_line_width (calParams['GridLineThickness']) pdfFile.set_draw_color (calParams['DayRegionColourR'], calParams['DayRegionColourG'], calParams['DayRegionColourB']) gridOffset = calParams['DayGridSpacing'] for col in range (0, NUMBER_WEEKDAYS): for row in range (0, GRID_ROWS): boxXStart = calParams['PageXOrigin'] + calXOffset + (col / NUMBER_WEEKDAYS) * calWidth + gridOffset boxXEnd = calWidth / NUMBER_WEEKDAYS - 2*gridOffset boxYStart = calParams['PageYOrigin'] + calYOffset + (1 - calParams['BlockDayRegionHeight']) * calHeight \ + calParams['BlockDayRegionHeight'] * calHeight * row / GRID_ROWS + gridOffset boxYEnd = calParams['BlockDayRegionHeight'] * calHeight / GRID_ROWS - 2*gridOffset dX = boxXEnd dY = boxYEnd minBoxXStart = maxBoxXStart = boxXStart minBoxXEnd = maxBoxXEnd = boxXEnd minBoxYStart = maxBoxYStart = boxYStart minBoxYEnd = maxBoxYEnd = boxYEnd if (dX < dY): offset = (dY - dX) / 2 minBoxYStart += offset minBoxYEnd -= (2*offset) maxBoxXStart -= offset maxBoxXEnd += offset else: offset = (dX - dY) / 2 minBoxXStart += offset minBoxXEnd -= (2*offset) maxBoxYStart -= offset maxBoxYEnd += (2*offset) drawStyle = 'D' if (calParams['DayGridInvert'] == True): pdfFile.set_fill_color (calParams['FontColourR'], calParams['FontColourG'], calParams['FontColourB']) drawStyle = 'F' pdfFile.ellipse (minBoxXStart, minBoxYStart, minBoxXEnd, minBoxYEnd, style=drawStyle) if (calParams['DayGridStyle'] == 6): pdfFile.ellipse (boxXStart, boxYStart, boxXEnd, boxYEnd) ## ## numbers ## if (calParams['Debug']): pdfFile.set_draw_color (calParams['DebugColourR'], calParams['DebugColourG'], calParams['DebugColourB']) pdfFile.set_line_width (calParams['DebugLineThickness']) fontScaleFactor, fontMaxWidth, fontMaxSize = FindMaxFontHeight (calParams['Font'], fontStyle, \ calParams['BlockDayRegionHeight'] * calHeight / GRID_ROWS, \ calParams['DayFontScale'] * calWidth / NUMBER_WEEKDAYS, MAX_NUMBER_STR) gridOffset = 0 if (calParams['DayNumPlacement'] == 2): gridOffset += max (calParams['DayCornerOffset'] * calWidth / NUMBER_WEEKDAYS, \ calParams['DayCornerOffset'] * calParams['BlockDayRegionHeight'] * calHeight / GRID_ROWS) if (calParams['DayGridStyle'] == 4): gridOffset += calParams['DayGridSpacing'] if (calParams['DayGridInvert'] == True): pdfFile.set_text_color (255, 255, 255) else: pdfFile.set_text_color (calParams['FontColourR'], calParams['FontColourG'], calParams['FontColourB']) # iterate over all the days in the month col = 0 row = 0 for i in cal.itermonthdays (year, calMonth): # if it is a day within the month, not from the previous or next month then display it if (i != 0): # Central placement if (calParams['DayNumPlacement'] == 1): numberXLoc = calParams['PageXOrigin'] + calXOffset + col / NUMBER_WEEKDAYS * calWidth numberYLoc = calParams['PageYOrigin'] + calYOffset + (1 - calParams['BlockDayRegionHeight']) * calHeight \ + (row / GRID_ROWS) * calParams['BlockDayRegionHeight'] * calHeight \ + calParams['BlockDayRegionHeight'] * calHeight / (2 * GRID_ROWS) \ + gridOffset pdfFile.set_xy (numberXLoc, numberYLoc) pdfFile.set_font (calParams['Font'], style=fontStyle, size=fontScaleFactor*calParams['BlockDayRegionHeight'] * calHeight / GRID_ROWS) pdfFile.cell (calWidth/NUMBER_WEEKDAYS, 0, txt=str(i), align='C', border=calParams['Debug']) # Corner placement elif (calParams['DayNumPlacement'] == 2): numberXLoc = calParams['PageXOrigin'] + calXOffset + col / NUMBER_WEEKDAYS * calWidth numberYLoc = calParams['PageYOrigin'] + calYOffset + (1 - calParams['BlockDayRegionHeight']) * calHeight \ + (row / GRID_ROWS) * calParams['BlockDayRegionHeight'] * calHeight if (calParams['HorizontalLines'] == True): pdfFile.set_fill_color (255, 255, 255) pdfFile.rect (numberXLoc, numberYLoc, fontMaxWidth + 3*gridOffset, fontMaxSize / INCH_TO_POINT + 3*gridOffset, style='F') numberXLoc += gridOffset numberYLoc += gridOffset pdfFile.set_xy (numberXLoc, numberYLoc) pdfFile.set_font (calParams['Font'], style=fontStyle, size=fontScaleFactor*calParams['BlockDayRegionHeight'] * calHeight / GRID_ROWS) pdfFile.cell (fontMaxWidth, fontMaxSize / INCH_TO_POINT, txt=str(i), align='L', border=calParams['Debug']) col += 1 if (col % 7 == 0): col = 0 row += 1 if (calParams['Debug']): pdfFile.set_draw_color (calParams['DayRegionColourR'], calParams['DayRegionColourG'], calParams['DayRegionColourB']) pdfFile.set_line_width (calParams['GridLineThickness']) ## ## grid ## pdfFile.set_draw_color (calParams['DayRegionColourR'], calParams['DayRegionColourG'], calParams['DayRegionColourB']) pdfFile.set_line_width (calParams['GridLineThickness']) # horizontal grid lines if (calParams['DayGridStyle'] == 1 or calParams['DayGridStyle'] == 2): for row in range (0, GRID_ROWS+1): lineXStart = calParams['PageXOrigin'] + calXOffset lineXEnd = calParams['PageXOrigin'] + calXOffset + calWidth lineYStart = calParams['PageYOrigin'] + calYOffset + calHeight - (row / GRID_ROWS) * calParams['BlockDayRegionHeight'] * calHeight lineYEnd = lineYStart pdfFile.line (lineXStart, lineYStart, lineXEnd, lineYEnd) # vertical grid lines if (calParams['DayGridStyle'] == 1 or calParams['DayGridStyle'] == 3): for day in range (0, NUMBER_WEEKDAYS+1): lineXStart = calParams['PageXOrigin'] + calXOffset + calWidth - (day / NUMBER_WEEKDAYS) * calWidth lineXEnd = lineXStart lineYStart = calParams['PageYOrigin'] + calYOffset + (1 - calParams['BlockDayRegionHeight']) * calHeight lineYEnd = calParams['PageYOrigin'] + calYOffset + calHeight pdfFile.line (lineXStart, lineYStart, lineXEnd, lineYEnd) if (calMonth % numCols == 0): calXOffset = 0 calYOffset += (calHeight + calParams['YearGridSpacing']) else: calXOffset += calWidth calXOffset += calParams['YearGridSpacing'] pdfFile.output (outputFile) return 0
place = 0 pdf.set_font('Times', 'B', 14) for row in data: index = 0 # Check to see if our 3 colum is a number or not if isinstance(row[2], float): subTotal += row[2] * row[3] data[len(data) - 1][4] = '${:,.2f}'.format(subTotal) row.append(row[2] * row[3]) # Loop through for datum in row: pdf.set_fill_color(255, 255, 255) if place == 0: pdf.set_fill_color(200, 200, 200) elif place == 1: pdf.set_font('Times') elif place == len(data) - 1: pdf.set_fill_color(200, 255, 200) pdf.set_font('Times', 'B') if isinstance(datum, float): datum = '${:,.2f}'.format(datum) pdf.cell(col_width[index], th, str(datum),
scan_date_printer = scan_dt_obj.strftime('%Y-%m-%d') except TypeError: scan_date_printer = None try: dob_dt_obj = datetime.datetime.strptime(birth_date, format_str_birth) except TypeError: pass try: pt_age = scan_dt_obj - dob_dt_obj pt_age = round(pt_age.days / 365.25, 1) except NameError: pt_age = None # note that the_num indicates disease state pdf.set_fill_color(130, 161, 255) ctrl_bold = scd_bold = anem_bold = '' ctrl_fill = scd_fill = anem_fill = False if the_num == '0': ctrl_bold = 'B' ctrl_fill = True elif the_num == '1': scd_bold = 'B' scd_fill = True if the_num == '2': anem_bold = 'B' anem_fill = True pdf.set_font('arial', 'B', 24)
def ImrimirPDF(self, saleId): # Obtener los datos de la base de datos (datos de la venta y los elementos) datos = db.Salerecord(saleId) # guardar los datos de la venta en datos_sale datos_sale = datos[0] #Guardar los datos de los elementos de la venta en datos_items datos_items = datos[1] # Formatear el numero de la venta (ej: 0000000023) facturaNumero = str(("0"*(10-len(str(saleId))))+str(saleId)) # Obtener los datos de la tienda/empresa desde la base de datos Datos = db.SelectConfigNS() logo = self.ResourcePath('logo.png') pdf = FPDF() pdf.add_page() # pdf.add_font('courier', '', 'cour.ttf', uni=True) # pdf.add_font('courier', '', 'cour.ttf', uni=True) pdf.set_font('courier', '', 13.0) pdf.set_xy(105.0, 16.0) pdf.cell(ln=0, h=22.0, align='L', w=75.0, txt='', border=0) pdf.set_line_width(0.0) pdf.rect(15.0, 45.0, 180.0, 90.0) # Marco Principal pdf.set_line_width(0.0) #pdf.rect(95.0, 15.0, 10.0, 10.0) # cuadrito # LOGOTIPO pdf.image(logo, 27.0, 10.0, link='', type='', w=0, h=20) pdf.set_font('courier', 'B', 16.0) pdf.set_xy(95.0, 18.0) #pdf.cell(ln=0, h=2.0, align='C', w=10.0, txt='Hola 1', border=0) # DATOS DE LA EMPRESA pdf.set_font('courier', '', 8.0) pdf.set_xy(115.0, 25.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="Tel: "+str(Datos[3]), border=0) pdf.set_xy(115.0, 28.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="Web: "+str(Datos[4]), border=0) pdf.set_xy(115.0, 31.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="E-mail: "+Datos[7], border=0) pdf.set_xy(115.0, 34.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="NIT: "+str(Datos[8]), border=0) pdf.set_font('courier', '', 7.0) pdf.set_xy(115.0, 35.0) pdf.cell(ln=0, h=7.0, align='L', w=60.0, txt='Fecha:', border=0) pdf.set_xy(145.0, 35.0) pdf.cell(ln=0, h=7.0, align='L', w=40.0, txt=datos_sale[1], border=0) pdf.rect(15.0, 9.0, 180.0, 35.8) # header datos principales pdf.set_xy(95.0, 21.5) pdf.set_line_width(0.0) pdf.set_font('arial', 'B', 13.0) pdf.set_xy(15.0, 10.5) pdf.cell(ln=0, h=5.5, align='C', w=180.0, txt='Comprobante de venta', border=0) # pdf.line(100.0, 25.0, 100.0, 57.0) #linea vertical header pdf.set_font('arial', 'B', 14.0) pdf.set_xy(143.0, 15.5) pdf.cell(ln=0, h=9.5, align='L', w=60.0, txt=facturaNumero, border=0) pdf.set_xy(115.0, 17.5) pdf.cell(ln=0, h=5.5, align='L', w=10.0, txt='N\xba: ', border=0) pdf.set_font('courier', 'B', 12.0) pdf.set_xy(17.0, 30.5) pdf.cell(ln=0, h=5.0, align='L', w=98.0, txt=Datos[1], border=0)#Datos[1] nombre pdf.set_font('courier', '', 12.0) pdf.set_xy(17.0, 26.5) pdf.set_font('courier', '', 8.0) pdf.cell(ln=0, h=5.0, align='L', w=98.0, txt="", border=0) #Datos[2] slogan pdf.set_xy(17.0, 34.5) pdf.set_font('courier', '', 8.0) pdf.multi_cell( h=4.0, align='L', w=80.0, txt=Datos[5], border=0, ) pdf.set_xy(115.0, 39.5) pdf.set_font('courier', '', 8.0) pdf.multi_cell( h=4.0, align='L', w=80.0, txt="Atendido por: ", border=0, ) pdf.set_xy(145.0, 39.5) pdf.multi_cell( h=4.0, align='L', w=80.0, txt=db.SelectUser(datos_items[0][7])[0][1], border=0, ) #Datos del cliente nombre = "" for i in datos_sale[3].split(" "): nombre = nombre+i.capitalize()+" " if(str(datos[0][4])=="1"): pdf.set_fill_color(244, 244,244 ) else: pdf.set_fill_color(255, 255,204 ) pdf.set_xy(15.0, 45.0) pdf.cell(ln=0, h=5.0, align='L', w=180.0, txt='', fill=1) pdf.set_line_width(0.0) pdf.line(15.0, 50.0, 185.0, 50.0) #Linea de cabecera pdf.set_font('courier', '', 10.0) pdf.set_xy(17.0, 44.3) pdf.cell(ln=0, h=6.0, align='L', w=13.0, txt='Cliente: '+nombre, border=0) pdf.set_xy(110.0, 44.3) pdf.cell(ln=0, h=6.0, align='L', w=18.0, txt='Nit: '+datos_sale[5].upper(), border=0) pdf.set_xy(163.0, 44.3) if(str(datos[0][4])=="1"): est = "CREDITO" else: est = "PAGADO" pdf.cell(ln=0, h=6.0, align='L', w=18.0, txt=est, border=0) pdf.set_xy(133.0, 69.0) #pdf.cell(ln=0, h=6.0, align='L', w=42.0, txt='Springfield', border=0) pdf.set_line_width(0.0) pdf.line(15.0, 50.0, 195.0, 50.0) #linea header de productos pdf.set_line_width(0.0) pdf.line(35.0, 50.0, 35.0, 130.0) #Separador 3 pdf.line(50.0, 50.0, 50.0, 130.0) #Separador 2 pdf.line(150.0, 50.0, 150.0, 130.0) #Separador 4 pdf.line(172.0, 50.0, 172.0, 135.0) #Separador 5 pdf.set_font('courier', '', 8.0) pdf.set_xy(14.0, 50.0) pdf.cell(ln=0, h=5.0, align='C', w=15.0, txt='Codigo', border=0) pdf.set_xy(35.0, 50.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Cantidad', border=0) pdf.set_xy(50.0, 50.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Producto', border=0) pdf.set_xy(150.0, 50.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Precio', border=0) pdf.set_xy(173.0, 50.0) pdf.cell(ln=0, h=5.0, align='L', w=20.0, txt='Total', border=0) pdf.set_line_width(0.0) pdf.line(15.0, 55.0, 195.0, 55.0) lineaN = 55.0 contador = 0 for elemento in datos_items: contador = contador+1 pdf.set_xy(15.0, lineaN) pdf.set_font('courier', '', 8.0) if len(elemento[6]) > 10: elemento[6] = elemento[6][:10] pdf.cell(ln=0, h=5.0, align='L', w=15.0, txt=elemento[6].upper(), border=0) # CODIGO pdf.set_xy(35.0, lineaN) pdf.cell(ln=0, h=5.0, align='C', w=15.0, txt=str(elemento[4]), border=0) # CANTIDAD pdf.set_xy(35.0+15, lineaN) if len(elemento[5]) > 57: pdf.cell( h=5.0, align='L', w=100.0, txt=elemento[5][:57], border=0) # NOMBRE else: pdf.cell(ln=0, h=5.0, align='L', w=100.0, txt=elemento[5], border=0) # NOMBRE pdf.set_xy(150.0, lineaN) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt=self.TSep(self.formatCant(elemento[3])), border=0) # PRECIO pdf.set_xy(173.0, lineaN) pdf.cell(ln=0, h=5.0, align='L', w=20.0, txt=self.TSep(self.formatCant(elemento[3]*elemento[4])), border=0) # TOTAL lineaN = lineaN+4 pdf.set_line_width(0.0) pdf.line(15.0, 130.0, 195.0, 130.0) pdf.set_xy(70.0, 130.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Total', border=0) pdf.set_xy(173.0, 130.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt=self.TSep(self.formatCant(datos_sale[2])), border=0) #------------ SEGUNDA PARTE ---------------# ln2 = 141 pdf.set_line_width(0.0) pdf.rect(15.0, ln2+45.0, 180.0, 90.0) # Marco Principal pdf.rect(15.0, ln2+9.0, 180.0, 35.8) # header datos principales pdf.set_font('arial', 'B', 13.0) pdf.set_xy(15.0, ln2+10.5) pdf.cell(ln=0, h=5.5, align='C', w=180.0, txt='Comprobante de venta', border=0) # LOGOTIPO pdf.image(logo, 27.0, ln2+10.0, link='', type='', w=0, h=20) pdf.set_font('courier', 'B', 16.0) pdf.set_xy(ln2+95.0, 18.0) #pdf.cell(ln=0, h=2.0, align='C', w=10.0, txt='Hola 1', border=0) # DATOS DE LA EMPRESA pdf.set_font('courier', '', 8.0) pdf.set_xy(115.0, ln2+25.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="Tel: "+str(Datos[3]), border=0) pdf.set_xy(115.0, ln2+28.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="Web: "+str(Datos[4]), border=0) pdf.set_xy(115.0, ln2+31.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="E-mail: "+Datos[7], border=0) pdf.set_xy(115.0, ln2+34.0) pdf.cell(ln=0, h=4.0, align='L', w=75.0, txt="NIT: "+str(Datos[8]), border=0) pdf.set_font('courier', '', 7.0) pdf.set_xy(115.0, ln2+35.0) pdf.cell(ln=0, h=7.0, align='L', w=60.0, txt='Fecha:', border=0) pdf.set_xy(145.0, ln2+35.0) pdf.cell(ln=0, h=7.0, align='L', w=40.0, txt=datos_sale[1], border=0) pdf.set_xy(95.0, ln2+21.5) pdf.set_line_width(0.0) # pdf.line(100.0, 25.0, 100.0, 57.0) #linea vertical header pdf.set_font('arial', 'B', 14.0) pdf.set_xy(143.0, ln2+15.5) pdf.cell(ln=0, h=9.5, align='L', w=60.0, txt=facturaNumero, border=0) pdf.set_xy(115.0, ln2+17.5) pdf.cell(ln=0, h=5.5, align='L', w=10.0, txt='N\xba: ', border=0) pdf.set_font('courier', 'B', 12.0) pdf.set_xy(17.0, ln2+30.5) pdf.cell(ln=0, h=5.0, align='L', w=98.0, txt=Datos[1], border=0)#Datos[1] nombre pdf.set_font('courier', '', 12.0) pdf.set_xy(17.0, ln2+26.5) pdf.set_font('courier', '', 8.0) pdf.cell(ln=0, h=5.0, align='L', w=98.0, txt="", border=0) #Datos[2] slogan pdf.set_xy(17.0, ln2+34.5) pdf.set_font('courier', '', 8.0) pdf.multi_cell( h=4.0, align='L', w=80.0, txt=Datos[5], border=0, ) pdf.set_xy(115.0, ln2+39.5) pdf.set_font('courier', '', 8.0) pdf.multi_cell( h=4.0, align='L', w=80.0, txt="Atendido por: ", border=0, ) pdf.set_xy(145.0, ln2+39.5) pdf.multi_cell( h=4.0, align='L', w=80.0, txt=db.SelectUser(datos_items[0][7])[0][1], border=0, ) #Datos del cliente nombre = "" for i in datos_sale[3].split(" "): nombre = nombre+i.capitalize()+" " if(str(datos[0][4])=="1"): pdf.set_fill_color(244, 244,244 ) else: pdf.set_fill_color(255, 255,204 ) pdf.set_xy(15.0, ln2+45.0) pdf.cell(ln=0, h=5.0, align='L', w=180.0, txt='', fill=1) pdf.set_line_width(0.0) pdf.line(15.0, ln2+50.0, 195.0, ln2+50.0) #Linea de cabecera pdf.set_font('courier', '', 10.0) pdf.set_xy(17.0, ln2+44.3) pdf.cell(ln=0, h=6.0, align='L', w=13.0, txt='Cliente: '+nombre, border=0) pdf.set_xy(110.0, ln2+44.3) pdf.cell(ln=0, h=6.0, align='L', w=18.0, txt='Nit: '+datos_sale[5].upper(), border=0) pdf.set_xy(163.0, ln2+44.3) pdf.cell(ln=0, h=6.0, align='L', w=18.0, txt=est, border=0) pdf.set_xy(133.0, ln2+69.0) #pdf.cell(ln=0, h=6.0, align='L', w=42.0, txt='Springfield', border=0) pdf.set_line_width(0.0) pdf.line(15.0, ln2+50.0, 195.0, ln2+50.0) #linea header de productos pdf.set_line_width(0.0) pdf.line(35.0, ln2+50.0, 35.0, ln2+130.0) #Separador 3 pdf.line(50.0, ln2+50.0, 50.0, ln2+130.0) #Separador 2 pdf.line(150.0, ln2+50.0, 150.0, ln2+130.0) #Separador 4 pdf.line(172.0, ln2+50.0, 172.0, ln2+135.0) #Separador 5 pdf.set_font('courier', '', 8.0) pdf.set_xy(14.0, ln2+50.0) pdf.cell(ln=0, h=5.0, align='C', w=15.0, txt='Codigo', border=0) pdf.set_xy(35.0, ln2+50.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Cantidad', border=0) pdf.set_xy(50.0, ln2+50.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Producto', border=0) pdf.set_xy(150.0, ln2+50.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Precio', border=0) pdf.set_xy(173.0, ln2+50.0) pdf.cell(ln=0, h=5.0, align='L', w=20.0, txt='Total', border=0) pdf.set_line_width(0.0) pdf.line(15.0, ln2+55.0, 195.0, ln2+55.0) lineaN = ln2+55.0 contador = 0 for elemento in datos_items: contador = contador+1 pdf.set_xy(15.0, lineaN) pdf.set_font('courier', '', 8.0) if len(elemento[6]) > 10: elemento[6] = elemento[6][:10] pdf.cell(ln=0, h=5.0, align='L', w=15.0, txt=elemento[6].upper(), border=0) # CODIGO pdf.set_xy(35.0, lineaN) pdf.cell(ln=0, h=5.0, align='C', w=15.0, txt=str(elemento[4]), border=0) # CANTIDAD pdf.set_xy(35.0+15, lineaN) if len(elemento[5]) > 57: pdf.cell( h=5.0, align='L', w=100.0, txt=elemento[5][:57], border=0) # NOMBRE else: pdf.cell(ln=0, h=5.0, align='L', w=100.0, txt=elemento[5], border=0) # NOMBRE pdf.set_xy(150.0, lineaN) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt=self.TSep(self.formatCant(elemento[3])), border=0) # PRECIO pdf.set_xy(173.0, lineaN) pdf.cell(ln=0, h=5.0, align='L', w=20.0, txt=self.TSep(self.formatCant(elemento[3]*elemento[4])), border=0) # TOTAL lineaN = lineaN+4 pdf.set_line_width(0.0) pdf.line(15.0, ln2+130.0, 195.0, ln2+130.0) pdf.set_xy(70.0, ln2+130.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt='Total', border=0) pdf.set_xy(173.0, ln2+130.0) pdf.cell(ln=0, h=5.0, align='L', w=125.0, txt=self.TSep(self.formatCant(datos_sale[2])), border=0) pdf.output('invoice.pdf', 'F') if sys.platform.startswith("linux"): os.system("evince ./invoice.pdf") else: #os.system("invoice.pdf") import subprocess subprocess.Popen("invoice.pdf", shell=True, bufsize=255, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def createCertificate( workshop_name, workshop_day, workshop_month, workshop_year, workshop_speaker, student_name, student_mail, chair_IEEE ): l_name = unicode( student_name, "utf-8" ) w_name = unicode( workshop_name, "utf-8" ) c_name = unicode( chair_IEEE, "utf-8" ) s_name = unicode( workshop_speaker, "utf-8" ) # PDF File Properties pdf=FPDF('L','mm','A4') pdf.set_margins(left=0,top=0,right=0) pdf.set_auto_page_break(False,margin=0) pdf.add_page() # ISEPinIEEE Logo pdf.set_font('Arial','',30) pdf.cell(297,40,'',0,1,'C')#fill=True pdf.image('logos/isepinieee_logo.jpg',190,5, 0,35,'','') # Workshop Title pdf.set_text_color(0,102,153) pdf.cell(293,20,w_name,0,1,'R') # Cetificate Bar pdf.set_fill_color(0,102,153) pdf.set_text_color(255,255,255) pdf.set_font('Arial','',48) pdf.cell(297,35,'Certificate',0,1,'C',fill=True) pdf.cell(297,10,'',0,1,'C') # Certificate Text pdf.set_font('Arial','',20) pdf.set_text_color(0,0,0) # This pdf element is used to center ( Note: (297-240)/2 = 28.5) pdf.cell(19,20,'',0,0,'C') pdf.multi_cell(259,12.5, 'We certifiy that '+l_name+' participated in the talk \"'+w_name+'\", organized by the ISEPinIEEE.',0,1,'C') #MultiCell( 200, 40, $reportSubtitle, 1); # Certificate Date pdf.cell(297,10,'',0,1,'C') pdf.cell(19,15,'',0,0,'C') pdf.cell(240,10,'Porto, '+workshop_month+' '+str(workshop_day)+', '+str(workshop_year),0,1,'L') #Speaker & Chair Signature pdf.image(workshop_name+'/signatures/speaker.jpg',167.5,170, 0, 17,'','') pdf.image(workshop_name+'/signatures/chair.jpg',240.5,170, 0, 17,'','') #Speaker & Chair pdf.set_font('Arial','',18) pdf.cell(150,20,'',0,0,'C') pdf.cell(73.5,20,'Speaker',0,0,'C') pdf.cell(73.5,20,'Chair',0,1,'C') pdf.cell(150,35,'',0,0,'C') pdf.cell(73.5,35,s_name,0,0,'C') pdf.cell(73.5,35,c_name,0,1,'C') #SpeakerLine & ChairLine pdf.line(155, 180, 218, 180) pdf.line(228, 180, 292, 180) # IEEE and ISEP logos pdf.image('logos/ieee_logo.jpg',20,175, 0, 17,'','') pdf.image('logos/isep_logo.jpg',85,175, 0, 17,'','') # Save PDF File certificate_name = hashlib.md5(student_mail) pdf.output(workshop_name+'/'+certificate_name.hexdigest()+'.pdf','F')
def excel_to_pdf(filename, title): data = read_excel(filename) # Creating the pdf instance and seting init values pdf = FPDF() pdf.add_page() pdf.set_xy(0, 0) background_url = os.path.join(STATIC_ROOT, 'img/pdf-lineas.png') pdf.image(background_url, 0, 0, pdf.w, pdf.h + 20, type='png') # Generating The header of the file image_url = os.path.join(STATIC_ROOT, 'img/logo.png') pdf.image(image_url, x=10, y=8, w=75, h=27, type='png') pdf.set_font('arial', 'BU', 12) pdf.set_text_color(236, 126, 30) pdf.y = 40 pdf.cell(20) pdf.cell(0, 10, title, 0, 2, 'C') # Generating the table header pdf.set_font('arial', 'B', 12) pdf.set_text_color(255) pdf.cell(150, 10, 'Productos', 1, 0, 'C', True) pdf.cell(20, 10, 'Unid', 1, 2, 'C', True) pdf.cell(-150) # Seting values of font for the table's values pdf.set_font('arial', '', 8) pdf.set_text_color(0) pdf.set_fill_color(255, 255, 255) for row in data: # Getting row's data height = 10 # col_a nombre producto, col_b unidad. col_a = str(row[0]) col_b = str(row[1]) # Save top coordinate top = pdf.y # Calculate x position of next cell offset = pdf.x + 150 pdf.multi_cell(150, height, '%s' % (col_a), 1, 'J', True) # Reset y coordinate pdf.y = top # Move to computed offset pdf.x = offset if (len(col_a) > 120): height += height pdf.multi_cell(20, height, '%s' % (col_b), 1, 'C', True) pdf.cell(10) if pdf.y == 250: pdf.add_page() pdf.image(background_url, 0, 0, pdf.w, pdf.h + 20, type='png') pdf.y = 40 pdf.cell(10) pdf.image(image_url, x=10, y=8, w=75, h=27, type='png') pdf.set_font('arial', 'BU', 12) pdf.set_text_color(236, 126, 30) pdf.y = 40 pdf.cell(0, 10, title, 0, 2, 'C') # Seting values of font for the table's values pdf.set_font('arial', '', 8) pdf.set_text_color(0) pdf.set_fill_color(255, 255, 255) return pdf
class PDFPrinter: PAGE_FORMAT = 'A4' UNIT = 'mm' MARGIN = 10 CONTENT_WIDTH = 297 - 2 * MARGIN CONTENT_HEIGHT = 210 - 2 * MARGIN HEADER_HEIGHT = 30 NOTES_HEIGHT = 17 TABLE_HEIGHT = CONTENT_HEIGHT - HEADER_HEIGHT - NOTES_HEIGHT FONT_S = 7 FONT_XS = 6.5 def __init__(self): self.colors = {} self.timelinesCount = None self.fontSize = 12 self.textColor = Color.WHITE self.pdf = FPDF(orientation='L', unit=PDFPrinter.UNIT, format=PDFPrinter.PAGE_FORMAT) self.pdf.add_font('regular', '', os.path.join('fonts', 'ubuntu', 'Ubuntu-B.ttf'), uni=True) self.pdf.add_font('condensed', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Regular.ttf'), uni=True) self.pdf.add_font('italic', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Bold.ttf'), uni=True) self.pdf.set_font("regular", size=self.fontSize) self.pdf.add_page() self.pdf.set_margins(PDFPrinter.MARGIN, PDFPrinter.MARGIN, PDFPrinter.MARGIN) self.uglyMeasure = FPDF(orientation='L', unit=PDFPrinter.UNIT, format=PDFPrinter.PAGE_FORMAT) self.uglyMeasure.add_font('regular', '', os.path.join('fonts', 'ubuntu', 'Ubuntu-B.ttf'), uni=True) self.uglyMeasure.add_font('condensed', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Regular.ttf'), uni=True) self.uglyMeasure.add_font('italic', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Bold.ttf'), uni=True) self.uglyMeasure.set_font("regular", size=self.fontSize) self.uglyMeasure.add_page() def defineColor(self, key, color): hex = color.lstrip('#') self.colors[key.lower()] = tuple( int(hex[i:i + 2], 16) for i in (0, 2, 4)) def printHeader(self, names): self.timelinesCount = len(names) boxWidth = PDFPrinter.CONTENT_WIDTH / self.timelinesCount boxPos = 0 for name in names: color = self.colors[name.lower()] x = PDFPrinter.MARGIN + boxWidth * boxPos y = PDFPrinter.MARGIN w = boxWidth h = 7 self._box(x, y, w, h, color=color, lineColor=Color.BLACK, lineWidth=0.1) self._text(x, y, w, h, text=name, color=self.textColor, font='regular', size=self.fontSize) boxPos += 1 def printTimetable(self, timetable): colCount = len(timetable.keys()) colWidth = PDFPrinter.CONTENT_WIDTH / colCount tablePositionY = 30 tableHeight = PDFPrinter.TABLE_HEIGHT + 1 tableHeaderHeight = 7 timelineRowHeight = tableHeight - tableHeaderHeight timelineRowPositionY = tablePositionY + tableHeaderHeight timeBlockWidth = (colWidth - 2) / self.timelinesCount timeWindow = self._findTimeWindow(timetable) yPerMin = (timelineRowHeight - 2) / (timeWindow["toTime"] - timeWindow["fromTime"]) colNo = 0 for key, schedules in timetable.items(): x = PDFPrinter.MARGIN + colWidth * colNo self._box(x=x, y=tablePositionY, w=colWidth, h=tableHeaderHeight, color=Color.LIGHT_GREY, lineColor=Color.BLACK, lineWidth=0.2) self._text(x=x, y=tablePositionY, w=colWidth, h=tableHeaderHeight, text=key, color=Color.BLACK, font='regular', size=self.fontSize) self._box(x=x, y=timelineRowPositionY, w=colWidth, h=timelineRowHeight, color=None, lineColor=Color.BLACK, lineWidth=0.2) self._drawTimeblocks(schedules, areaWidth=timeBlockWidth, areaPositionX=x, areaPositionY=timelineRowPositionY + 0.8, scaleY=yPerMin, timeWindowStart=timeWindow["fromTime"]) colNo += 1 def _drawTimeblocks(self, schedules, areaWidth, areaPositionX, areaPositionY, scaleY, timeWindowStart): timeBlockNo = 0 for person, timelines in schedules.items(): blockColor = self.colors[person.lower()] blockPositionX = areaPositionX + areaWidth * timeBlockNo + 0.5 * timeBlockNo + 0.5 for timeline in timelines: fromTimePosY = scaleY * (self._timeToInt(timeline.fromTime) - timeWindowStart) + 0.4 blockPositionY = areaPositionY + fromTimePosY blockHeight = scaleY * (self._timeToInt(timeline.toTime) - timeWindowStart) - fromTimePosY self._box(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight, color=blockColor, lineColor=None) if (timeline.kind == "~"): self._drawLeftLines(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight) elif (timeline.kind == "d"): self._drawTwoRightLines(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight) elif (timeline.kind == "e"): self._drawEmptyRightCorner(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight) self._drawTimeblockLabels(areaX=blockPositionX, areaY=blockPositionY, areaW=areaWidth, areaH=blockHeight, timeline=timeline, backColor=blockColor) timeBlockNo += 1 def _drawLeftLines(self, x, y, w, h): hw = h / w posX = x posXM = x + w posY = y posYM = y + h jump = 3 while (posXM > x): posX += jump posXM -= jump posY += jump * hw posYM -= jump * hw if jump == 2: jump = 0.5 else: jump = 2 if (posX < x + w and posY < y + h): self._line(posX, y, x, posY, Color.WHITE, lineWidth=0.2) if (posXM > x and posYM > y): self._line(posXM, y + h, x + w, posYM, Color.WHITE, lineWidth=0.2) def _drawTwoRightLines(self, x, y, w, h): hw = h / w posX = x posXM = x + w posY = y posYM = y + h jump = 2 for _ in range(4): posX += jump posXM -= jump posY += jump * hw posYM -= jump * hw # if jump == 2: # jump = 0.7 # else: # jump = 2 if (posX < x + w and posY < y + h): self._line(posX, y + h, x, posYM, Color.WHITE, lineWidth=0.3) if (posXM > x and posYM > y): self._line(posXM, y, x + w, posY, Color.WHITE, lineWidth=0.3) def _drawEmptyRightCorner(self, x, y, w, h): hw = h / w posX = x posXM = x + w posY = y posYM = y + h jump = 1 for p in range(9): posX += jump posXM -= jump posY += jump * hw posYM -= jump * hw if p > 5: jump = 1 else: jump = 0.2 if (posX < x + w and posY < y + h): self._line(posX, y + h, x, posYM, Color.WHITE, lineWidth=0.2) if (posXM > x and posYM > y): self._line(posXM, y, x + w, posY, Color.WHITE, lineWidth=0.2) def _drawTimeblockLabels(self, areaX, areaY, areaW, areaH, timeline, backColor): label = [] if (timeline.name): label.append(timeline.name.upper()) for component in timeline.components: label.append(component.upper()) if (label): self._textBlock(x=areaX, y=areaY, w=areaW, h=areaH, textLines=label, color=Color.WHITE, font='condensed', size=PDFPrinter.FONT_XS, align='C', backColor=backColor) if (timeline.fromTime): textSize = self._measure(text=timeline.fromTime, font='italic', size=PDFPrinter.FONT_S) self._text(x=areaX, y=areaY - 1, w=areaW / 2, h=textSize.y, text=timeline.fromTime, color=Color.WHITE, font='italic', size=PDFPrinter.FONT_S, align='L', backColor=backColor) if (timeline.toTime): textSize = self._measure(text=timeline.toTime, font='italic', size=PDFPrinter.FONT_S) self._text(x=areaX + areaW / 2, y=areaY + areaH - textSize.y + 1, w=areaW / 2, h=textSize.y, text=timeline.toTime, color=Color.WHITE, font='italic', size=PDFPrinter.FONT_S, align='R', backColor=backColor) def printNotes(self, notes): x = PDFPrinter.MARGIN y = PDFPrinter.MARGIN + PDFPrinter.HEADER_HEIGHT + PDFPrinter.TABLE_HEIGHT w = PDFPrinter.CONTENT_WIDTH h = 5 for note in notes: y += h self._text(x, y, w, 0, text=note, color=Color.BLACK, font='regular', size=self.fontSize, align='L') def save(self, fileName): self.pdf.output(fileName) def _measure(self, text, font, size): self.uglyMeasure.set_font(font, size=size) self.uglyMeasure.set_xy(0, 0) self.uglyMeasure.write(size / 2.83, txt=text) sizeX = self.uglyMeasure.get_x() self.uglyMeasure.write(size / 2.83, txt="\n") sizeY = self.uglyMeasure.get_y() result = Size(sizeX, sizeY) return result def _text(self, x, y, w, h, text, color, font, size, align='C', backColor=None): self.pdf.set_text_color(color[0], color[1], color[2]) self.pdf.set_font(font, size=size) self.pdf.set_xy(x, y) fillBackground = False if (backColor): self.pdf.set_fill_color(backColor[0], backColor[1], backColor[2]) fillBackground = True self.pdf.cell(w, h, txt=text, ln=1, align=align, fill=fillBackground) def _textBlock(self, x, y, w, h, textLines, color, font, size, align='C', backColor=None): textH = 0 texts = [] for line in textLines: textSize = self._measure(text=line, font=font, size=size) textSize.y += 1 textH += textSize.y texts.append({"txt": line, "height": textSize.y}) self.pdf.set_text_color(color[0], color[1], color[2]) self.pdf.set_font(font, size=size) posY = y + (h - textH) / 2 fillBackground = False if (backColor): self.pdf.set_fill_color(backColor[0], backColor[1], backColor[2]) fillBackground = True for line in texts: self.pdf.set_xy(x, posY) self.pdf.cell(w, line["height"], txt=line["txt"], align=align, fill=fillBackground) posY += line["height"] def _box(self, x, y, w, h, color, lineColor, lineWidth=0): style = '' if (lineColor): self.pdf.set_line_width(lineWidth) self.pdf.set_draw_color(lineColor[0], lineColor[1], lineColor[2]) style += 'D' if (color): self.pdf.set_fill_color(color[0], color[1], color[2]) style += 'F' self.pdf.rect(x, y, w, h, style) def _line(self, x1, y1, x2, y2, color, lineWidth): self.pdf.set_line_width(lineWidth) self.pdf.set_draw_color(color[0], color[1], color[2]) self.pdf.line(x1, y1, x2, y2) def _findTimeWindow(self, timetable): minTime = self._timeToInt("24:00") maxTime = self._timeToInt("00:00") for daySchedule in timetable.values(): for personalSchedule in daySchedule.values(): for schedule in personalSchedule: f = self._timeToInt(schedule.fromTime) t = self._timeToInt(schedule.toTime) minTime = min(minTime, f, t) maxTime = max(maxTime, f, t) return {"fromTime": minTime, "toTime": maxTime} def _timeToInt(self, str): parts = str.split(':') return int(parts[0]) * 60 + int(parts[1])
class kut2fpdf(object): _document = None # Aquí se irán guardando los datos del documento logger = None _xml = None _xml_data = None _page_orientation = None _page_size = None _bottom_margin = None _left_margin = None _right_margin = None _top_margin = None _page_top = {} _data_row = None # Apunta a la fila actual en data _parser_tools = None _avalible_fonts = None _unavalible_fonts = None design_mode = None _actual_data_line = None _no_print_footer = False _actual_section_size = None increase_section_size = None last_detail = False actual_data_level = None last_data_processed = None prev_level = None draws_at_header = None detailn = None name_ = None _actual_append_page_no = None reset_page_count = None def __init__(self): self.logger = logging.getLogger("kut2fpdf") checkDependencies({"fpdf": "pyfpdf"}) from pineboolib.plugins.kugar.parsertools import parsertools self._parser_tools = parsertools() self._avalible_fonts = [] self._unavalible_fonts = [] self.design_mode = FLSettings().readBoolEntry("ebcomportamiento/kugar_debug_mode") self._actual_data_line = None self._no_print_footer = False self.increase_section_size = 0 self.actual_data_level = 0 self.prev_level = -1 self.draws_at_header = {} self.detailn = {} self.name_ = None self._actual_append_page_no = 0 self.reset_page_count = False self.new_page = False """ Convierte una cadena de texto que contiene el ".kut" en un pdf y retorna la ruta a este último. @param name. Nombre de ".kut". @param kut. Cadena de texto que contiene el ".kut". @param data. Cadena de texto que contiene los datos para ser rellenados en el informe. @return Ruta a fichero pdf. """ def parse(self, name, kut, data, report = None, flags = []): try: self._xml = self._parser_tools.loadKut(kut) except Exception: self.logger.exception( "KUT2FPDF: Problema al procesar %s.kut", name) return False try: self._xml_data = load2xml(data) except Exception: self.logger.exception("KUT2FPDF: Problema al procesar xml_data") return False self.name_ = name self.setPageFormat(self._xml) # self._page_orientation = # self._page_size = if report is None: from fpdf import FPDF self._actual_append_page_no = -1 self._document = FPDF(self._page_orientation, "pt", self._page_size) for f in self._document.core_fonts: self.logger.debug("KUT2FPDF :: Adding font %s", f) self._avalible_fonts.append(f) else: self._document = report # Seteamos rutas a carpetas con tipos de letra ... # Cargamos las fuentes disponibles next_page_break = (flags[2] == 1) if len(flags) == 3 else True page_append = (flags[1] == 1) if len(flags) > 1 else False page_display = (flags[0] == 1) if len(flags) > 0 else False if page_append: self.prev_level = -1 self.last_detail = False page_break = False if self.new_page: page_break = True self.new_page = False if self.reset_page_count: self.reset_page_no() self.reset_page_count = False if self.design_mode: print("Append", page_append) print("Display", page_display) print("Page break", next_page_break) if next_page_break: self.reset_page_count = True if page_display: self.new_page = True self.processDetails(not page_break) #FIXME:Alguno valores no se encuentran for p in self._document.pages.keys(): page_content = self._document.pages[p]["content"] for h in self.draws_at_header.keys(): page_content = page_content.replace(h, str(self.draws_at_header[h])) self._document.pages[p]["content"] = page_content #print(self.draws_at_header.keys()) self._document.set_title(self.name_) self._document.set_author("Pineboo - kut2fpdf plugin") return self._document def get_file_name(self): import os pdf_name = aqApp.tmp_dir() pdf_name += "/%s_%s.pdf" % (self.name_, datetime.datetime.now().strftime("%Y%m%d%H%M%S")) if os.path.exists(pdf_name): os.remove(pdf_name) if self._document is not None: self._document.output(pdf_name, 'F') return pdf_name else: return None """ Indica el techo para calcular la posición de los objetos de esa sección. @return Número con el techo de la página actual. """ def topSection(self): return self._page_top[str(self._document.page_no())] """ Actualiza el valor del techo de la página actual. Se suele actualizar al procesar una sección. @param value. Numero que elspecifica el nuevo techo. """ def setTopSection(self, value): self._actual_section_size = value - self.topSection() self._page_top[str(self._document.page_no())] = value """ Añade una nueva página al documento. """ def newPage(self, data_level, add_on_header = True): self._document.add_page(self._page_orientation) self._page_top[str(self._document.page_no())] = self._top_margin self._document.set_margins(self._left_margin, self._top_margin, self._right_margin) # Lo dejo pero no se nota nada self._no_print_footer = False if self.design_mode: self.draw_margins() self._actual_section_size = 0 self._actual_append_page_no += 1 if self.design_mode: print("Nueva página", self.number_pages()) #l_ini = data_level #l_end = self.prev_level #if l_ini == l_end: # l_end = l_end + 1 #if l_ini <= l_end: # for l in range(l_ini , l_end): # print(l) # self.processSection("AddOnHeader", str(l)) pg_headers = self._xml.findall("PageHeader") for ph in pg_headers: if self.number_pages() == 0 or ph.get("PrintFrequency") == "1": ph_level = ph.get("Level") if ph.get("Level") is not None else None self.processSection("PageHeader", ph_level) break if add_on_header and not self.number_pages() == 0: for l in range(data_level + 1): self.processSection("AddOnHeader", str(l)) #Por ahora se omite detail header """ Procesa las secciones details con sus correspondientes detailHeader y detailFooter. """ def processDetails(self, keep_page = None): # Procesamos la cabecera si procede .. top_level = 0 level = 0 first_page_created = keep_page if keep_page is not None and self._document.page_no() > 0 else False rows_array = self._xml_data.findall("Row") for data in rows_array: self._actual_data_line = data level = int(data.get("level")) if level > top_level: top_level = level if not first_page_created: self.newPage(level) first_page_created = True if rows_array[len(rows_array) - 1] is data: self.last_detail = True if level < self.prev_level: for l in range(level + 1, self.prev_level + 1): self.processData("DetailFooter", self.last_data_processed, l) if not str(level) in self.detailn.keys(): self.detailn[str(level)] = 0 else: self.detailn[str(level)] += 1 if level > self.prev_level: self.processData("DetailHeader", data, level) self.processData("Detail", data, level) self.last_data_processed = data self.prev_level = level if not self._no_print_footer: for l in reversed(range(top_level + 1)): self.processData("DetailFooter", data, l) """ Paso intermedio que calcula si detailHeader + detail + detailFooter entran en el resto de la ṕagina. Si no es así crea nueva página. @param section_name. Nombre de la sección a procesar. @param data. Linea de datos a procesar. @param data_level. Nivel de seccion. """ def processData(self, section_name, data, data_level): self.actual_data_level = data_level listDF = self._xml.findall(section_name) data_size = len(listDF) for dF in listDF: draw_if = dF.get("DrawIf") show = True if draw_if: show = data.get(draw_if) if dF.get("Level") == str(data_level) and show not in ("None", "False"): if section_name in ("DetailHeader","Detail"): heightCalculated = self._parser_tools.getHeight(dF) + self.topSection() if section_name is "DetailHeader": for detail in self._xml.findall("Detail"): if detail.get("Level") == str(data_level): heightCalculated += self._parser_tools.getHeight(detail) for dFooter in self._xml.findall("DetailFooter"): if dFooter.get("Level") == str(data_level): heightCalculated += self._parser_tools.getHeight(dFooter) #for addFooter in self._xml.findall("AddOnFooter"): # if addFooter.get("Level") == str(data_level): # heightCalculated += self._parser_tools.getHeight(addFooter) pageFooter = self._xml.get("PageFooter") if pageFooter: if self._document.page_no() == 1 or pageFooter.get("PrintFrecuency") == "1": heightCalculated += self._parser_tools.getHeight(pageFooter) heightCalculated += self._bottom_margin if heightCalculated > self._document.h: # Si nos pasamos self._no_print_footer = True #Vemos el tope por abajo limit_bottom = self._document.h - self._parser_tools.getHeight(self._xml.get("AddOnFooter")) actual_size = self._parser_tools.getHeight(dF) + self.topSection() if (actual_size > limit_bottom + 2) or self.last_detail: # +2 se usa de margen extra self.processSection("AddOnFooter", str(data_level)) self.newPage(data_level) self.processXML(dF, data) if dF.get("NewPage") == "true" and not self.last_detail: self.newPage(data_level, False) break #Se ejecuta una sola instancia """ Procesa las secciones fuera de detail @param name. Nombre de la sección a procesar. """ def processSection(self, name, level=0): sec_list = self._xml.findall(name) sec_ = None for s in sec_list: if s.get("Level") == str(level) or s.get("Level") is None: sec_ = s if sec_ is not None: if sec_.get("PrintFrequency") == "1" or self._document.page_no() == 1 or name in ("AddOnHeader","AddOnFooter"): self.processXML(sec_) """ Procesa un elemento de xml. @param xml: El elemento a procesar. @param. data: Linea de datos afectada. """ def processXML(self, xml, data=None): fix_height = True if data is None: data = self._actual_data_line if self.design_mode: print("Procesando", xml.tag, data.get("level")) size_updated = False if xml.tag == "DetailFooter": if xml.get("PlaceAtBottom") == "true": self.setTopSection(self._document.h - self._parser_tools.getHeight(xml)) size_updated = True if xml.tag == "PageFooter": fix_height = False self.fix_extra_size() #Sirve para actualizar la altura con lineas que se han partido porque son muy largas for label in xml.iter("Label"): self.processText(label, data, fix_height) for field in xml.iter("Field"): self.processText(field, data, fix_height) for special in xml.iter("Special"): self.processText(special, data, fix_height, xml.tag) for calculated in xml.iter("CalculatedField"): self.processText(calculated, data, fix_height, xml.tag) #Busco draw_at_header en DetailFooter y los meto también if xml.tag == "DetailHeader": detail_level = xml.get("Level") for df in self._xml.iter("DetailFooter"): if df.get("Level") == detail_level: for cf in df.iter("CalculatedField"): if cf.get("DrawAtHeader") == "true": header_name = "%s_header_%s_%s" % (self.detailn[detail_level], detail_level, cf.get("Field")) self.draws_at_header[header_name] = "" self.processText(cf, data, fix_height, xml.tag) for line in xml.iter("Line"): self.processLine(line, fix_height) if not size_updated: self.setTopSection(self.topSection() + self._parser_tools.getHeight(xml)) def fix_extra_size(self): if self.increase_section_size > 0: self.setTopSection(self.topSection() + self.increase_section_size) self.increase_section_size = 0 """ Procesa una linea. @param xml. Sección de xml a procesar. @param fix_height. Ajusta la altura a los .kut originales, excepto el pageFooter. """ def processLine(self, xml, fix_height=True): color = xml.get("Color") r = 0 if not color else int(color.split(",")[0]) g = 0 if not color else int(color.split(",")[1]) b = 0 if not color else int(color.split(",")[2]) style = int(xml.get("Style")) width = int(xml.get("Width")) X1 = self.calculateLeftStart(xml.get("X1")) X1 = self.calculateWidth(X1, 0, False) X2 = self.calculateLeftStart(xml.get("X2")) X2 = self.calculateWidth(X2, 0, False) # Ajustar altura a secciones ya creadas Y1 = int(xml.get("Y1")) + self.topSection() Y2 = int(xml.get("Y2")) + self.topSection() if fix_height: Y1 = self._parser_tools.ratio_correction(Y1) Y2 = self._parser_tools.ratio_correction(Y2) self._document.set_line_width(width) self._document.set_draw_color(r, g, b) dash_length = 1 space_length = 1 if style == 2: dash_length = 20 space_length = 20 elif style == 3: dash_length = 10 space_length = 10 self._document.dashed_line(X1, Y1, X2, Y2, dash_length, space_length) #else: # self._document.line(X1, Y1, X2, Y2) """ Comprueba si excedemos el margen izquierdo de la página actual @param x. Posición a comprobar. @return Valor corregido, si procede. """ def calculateLeftStart(self, x): return self._parser_tools.ratio_correction(int(x)) + self._left_margin """ Comprueba si excedemos el margen derecho de la página actual @param x. Posición a comprobar. @return Valor corregido, si procede. """ def calculateWidth(self, width, pos_x, fix_ratio = True): width = int(width) if fix_ratio: width = self._parser_tools.ratio_correction(int(width)) ret_ = width limit = self._document.w - self._right_margin if pos_x + width > limit: ret_ = limit - pos_x return ret_ """ Procesa una etiqueta. Esta puede ser un campo calculado, una etiqueta, un campo especial o una imagen. @param xml. Sección de xml a procesar. @param fix_height. Ajusta la altura a los .kut originales, excepto el pageFooter. """ def processText(self, xml, data_row=None, fix_height=True, section_name = None): is_image = False is_barcode = False text = xml.get("Text") borderColor = xml.get("BorderColor") field_name = xml.get("Field") # x,y,W,H se calcula y corrigen aquí para luego estar correctos en los diferentes destinos posibles W = int(xml.get("Width")) H = self._parser_tools.getHeight(xml) x = int(xml.get("X")) y = int(xml.get("Y")) + self.topSection() # Añade la altura que hay ocupada por otras secciones if fix_height: y = self._parser_tools.ratio_correction(y) # Corrige la posición con respecto al kut original data_type = xml.get("DataType") if xml.tag == "Field" and data_row is not None: text = data_row.get(field_name) elif xml.tag == "Special": if text == "": if xml.get("Type") == "1": text = "PageNo" text = self._parser_tools.getSpecial( text, self._actual_append_page_no) calculation_type = xml.get("CalculationType") if calculation_type is not None and xml.tag != "Field": if calculation_type == "6": function_name = xml.get("FunctionName") try: nodo = self._parser_tools.convertToNode(data_row) from pineboolib.pncontrolsfactory import aqApp ret_ = aqApp.call(function_name, [nodo, field_name]) if ret_ is False: return else: text = str(ret_) except Exception: self.logger.exception( "KUT2FPDF:: Error llamando a function %s", function_name) return elif calculation_type == "1": text = self._parser_tools.calculate_sum(field_name, self.last_data_processed, self._xml_data, self.actual_data_level) elif calculation_type in ("5"): if data_row is None: data_row = self._xml_data[0] text = data_row.get(field_name) if data_type is not None: text = self._parser_tools.calculated(text, int(data_type), xml.get("Precision"), data_row) if data_type == "5": is_image = True elif data_type == "6": is_barcode = True if xml.get("BlankZero") == "1" and text is not None: res_ = re.findall(r'\d+', text) res_ = "".join(res_) if int(res_) == 0: return if text is not None and text.startswith(filedir("../tempdata")): is_image = True negValueColor = xml.get("NegValueColor") Currency = xml.get("Currency") commaSeparator = xml.get("CommaSeparator") dateFormat = xml.get("DateFormat") if is_image: self.draw_image(x, y, W, H, xml, text) elif is_barcode: self.draw_barcode(x, y, W, H, xml, text) else: level = data_row.get("level") if level and str(level) in self.detailn.keys(): val = "%s_header_%s_%s" % ( self.detailn[str(level)], level,field_name) if xml.get("DrawAtHeader") == "true" and level: if section_name == "DetailHeader": val = "" self.drawText(x, y, W, H, xml, val) print(level, section_name, val, text) if section_name == "DetailFooter" and xml.get("DrawAtHeader") == "true": self.draws_at_header[val] = text print("Añadiendo a", val, text, level) else: self.drawText(x, y, W, H, xml, text) """ Dibuja un campo texto en la página. @param x. Pos x de la etiqueta. @param y. Pos y de la etiqueta. @param W. Anchura de la etiqueta. @param H. Altura de la etiqueta. @param xml. Sección del xml afectada. @param txt. Texto calculado de la etiqueta a crear. """ def drawText(self, x, y, W, H, xml, txt): if txt in ("None", None): return txt = self._parser_tools.restore_text(txt) resizeable = False if xml.get("ChangeHeight") == "1": resizeable = True height_resized = False orig_x = x orig_y = y orig_W = W orig_H = H # Corregimos margenes: x = self.calculateLeftStart(x) W = self.calculateWidth(W, x) #bg_color = xml.get("BackgroundColor").split(",") fg_color = self.get_color(xml.get("ForegroundColor")) self._document.set_text_color(fg_color[0], fg_color[1], fg_color[2]) #self._document.set_draw_color(255, 255, 255) #if xml.get("BorderStyle") == "1": # FIXME: Hay que ajustar los margenes #font_name, font_size, font_style font_style = "" font_size = int(xml.get("FontSize")) font_name_orig = xml.get("FontFamily").lower() if xml.get("FontFamily") is not None else "helvetica" font_name = font_name_orig font_w = xml.get("FontWeight") if font_w in (None, "50"): #Normal font_w = 100 elif int(font_w) >= 65: font_style += "B" font_w = 100 fontI = xml.get("FontItalic") fontU = xml.get("FontUnderlined") # FIXME: hay que ver si es así background_color = self.get_color(xml.get("BackgroundColor")) #if background_color != [255,255,255]: #Los textos que llevan fondo no blanco van en negrita # font_style += "B" if fontI == "1": font_style += "I" if fontU == "1": font_style += "U" font_full_name = "%s%s" % (font_name, font_style) if font_full_name not in self._avalible_fonts: font_found = self._parser_tools.find_font(font_full_name) if font_found: self.logger.warning("KUT2FPDF::Añadiendo el tipo de letra %s (%s)", font_full_name, font_found) self._document.add_font(font_full_name, "", font_found, True) self._avalible_fonts.append(font_full_name) else: if font_full_name not in self._unavalible_fonts: self.logger.warning("KUT2FPDF:: No se encuentra el tipo de letra %s. Sustituido por helvetica%s." %(font_full_name, font_style)) self._unavalible_fonts.append(font_full_name) font_name = "helvetica" if font_name is not font_name_orig and font_name_orig.lower().find("narrow") > -1: font_w = 85 self._document.set_font(font_name, font_style, font_size) self._document.set_stretching(font_w) # Corregir alineación VAlignment = xml.get("VAlignment") # 0 izquierda, 1 centrado,2 derecha HAlignment = xml.get("HAlignment") layout_direction = xml.get("layoutDirection") start_section_size = self._actual_section_size result_section_size = 0 #Miramos si el texto sobrepasa el ancho array_text = [] array_n = [] text_lines = [] if txt.find("\n") > -1: for t in txt.split("\n"): array_n.append(t) if array_n: #Hay saltos de lineas ... for n in array_n: text_lines.append(n) else: #No hay saltos de lineas text_lines.append(txt) for tl in text_lines: str_width = self._document.get_string_width(tl) if str_width > W + 2 and xml.tag !="Label" and resizeable: #Una linea es mas larga que el ancho del campo(Dejando 2 de juego) height_resized = True array_text = self.split_text(tl, W) else: array_text.append(tl) #calculated_h = orig_H * len(array_text) self.drawRect(orig_x, orig_y, orig_W, orig_H, xml) processed_lines = 0 extra_size = 0 for actual_text in array_text: if actual_text is None: continue processed_lines += 1 if processed_lines > 1: extra_size += font_size + 2 if HAlignment == "1": # sobre X # Centrado x = x + (W / 2) - (self._document.get_string_width(actual_text) / 2) #x = x + (W / 2) - (str_width if not height_resized else W / 2) elif HAlignment == "2": # Derecha x = x + W - self._document.get_string_width(actual_text) - 2 # -2 de margen #x = x + W - str_width if not height_resized else W else: # Izquierda x = x + 2 if VAlignment == "1": # sobre Y # Centrado #y = (y + ((H / 2) / processed_lines)) + (((self._document.font_size_pt / 2) / 2) * processed_lines) y = ( orig_y + ( orig_H / 2))+ ((self._document.font_size_pt / 2) /2) elif VAlignment == "2": # Abajo y = orig_y + orig_H - font_size else: # Arriba y = orig_y + font_size y = y + extra_size if self.design_mode: self.write_debug(self.calculateLeftStart(orig_x), y, "Hal:%s, Val:%s, T:%s st:%s" % (HAlignment, VAlignment, txt, font_w), 6, "green") if xml.tag == "CalculatedField": self.write_debug(self.calculateLeftStart(orig_x), y, "CalculatedField:%s, Field:%s" % (xml.get("FunctionName"), xml.get("Field")), 3, "blue") self._document.text(x, y, actual_text) result_section_size += start_section_size result_section_size = result_section_size - start_section_size if self.increase_section_size < extra_size: #Si algun incremento extra hay superior se respeta self.increase_section_size = extra_size def split_text(self, texto, limit_w): list_ = [] linea_ = None for t in texto.split(" "): if linea_ is None and t == "": continue if linea_ is not None: if self._document.get_string_width(linea_ + t) > limit_w: list_.append(linea_) linea_ = "" else: linea_ = "" linea_ += "%s " % t list_.append(linea_) return list_ """ Dibuja un cuadrado en la página actual. @param x. Pos x del cuadrado. @param y. Pos y del cuadrado. @param W. Anchura del cuadrado. @param H. Altura del cuadrado. """ def get_color(self, value): value = value.split(",") r = None g = None b = None if len(value) == 3: r = int(value[0]) g = int(value[1]) b = int(value[2]) else: r = int(value[0:2]) g = int(value[3:5]) b = int(value[6:8]) return [r,g,b] def drawRect(self, x, y, W, H, xml = None): style_ = "" border_color = None bg_color = None line_width = self._document.line_width border_width = 0.2 #Calculamos borde y restamos del ancho orig_x = x orig_y = y orig_w = W x = self.calculateLeftStart(orig_x) W = self.calculateWidth(W, x) if xml is not None and not self.design_mode: if xml.get("BorderStyle") == "1": border_color = self.get_color(xml.get("BorderColor")) self._document.set_draw_color(border_color[0], border_color[1], border_color[2]) style_ += "D" bg_color = self.get_color(xml.get("BackgroundColor")) self._document.set_fill_color(bg_color[0], bg_color[1], bg_color[2]) style_ = "F" + style_ border_width = int(xml.get("BorderWidth") if xml.get("BorderWidth") else 0.2) else: self.write_cords_debug(x,y,W,H, orig_x, orig_w) style_ = "D" self._document.set_draw_color(0, 0, 0) if style_ is not "": self._document.set_line_width(border_width) self._document.rect(x, y, W, H, style_) self._document.set_line_width(line_width) self._document.set_xy(orig_x, orig_y) #self._document.set_draw_color(255, 255, 255) #self._document.set_fill_color(0, 0, 0) def write_cords_debug(self, x, y, w, h, ox, ow): self.write_debug(x,y,"X:%s Y:%s W:%s H:%s orig_x:%s, orig_W:%s" % (round(x, 2),round(y, 2),round(w, 2),round(h, 2), round(ox, 2), round(ow, 2)), 2, "red") def write_debug(self, x,y,text, h, color = None): orig_color = self._document.text_color r = None g = None b = None current_font_family = self._document.font_family current_font_size = self._document.font_size_pt current_font_style = self._document.font_style if color is "red": r = 255 g = 0 b = 0 elif color is "green": r = 0 g = 255 b = 0 elif color is "blue": r = 0 g = 0 b = 255 self._document.set_text_color(r,g,b) self._document.set_font_size(4) self._document.text(x, y + h, text) self._document.text_color = orig_color #self._document.set_xy(orig_x, orig_y) self._document.set_font(current_font_family, current_font_style, current_font_size) """ Inserta una imagen en la página actual. @param x. Pos x de la imagen. @param y. Pos y de la imagen. @param W. Anchura de la imagen. @param H. Altura de la imagen. @param xml. Sección del xml afectada. @param file_name. Nombr del fichero de tempdata a usar """ def draw_image(self, x, y, W, H, xml, file_name): import os if not file_name.lower().endswith(".png"): file_name = self._parser_tools.parseKey(file_name) if file_name is not None and os.path.exists(file_name): x = self.calculateLeftStart(x) W = self.calculateWidth(W, x) self._document.image(file_name, x, y, W, H, "PNG") def draw_barcode(self, x, y, W, H, xml, text): if text == "None": return from pineboolib.fllegacy.flcodbar import FLCodBar file_name = aqApp.tmp_dir() file_name += "/%s.png" % (text) type = xml.get("CodBarType") if not os.path.exists(file_name): bar_code = FLCodBar(text) #Code128 if type is not None: type = bar_code.nameToType(type.lower()) bar_code.setType(type) pix = bar_code.pixmap() if not pix.isNull(): pix.save(file_name, "PNG") self.draw_image(x , y, W, H, xml, file_name) """ Define los parámetros de la página @param xml: Elemento xml con los datos del fichero .kut a procesar """ def setPageFormat(self, xml): custom_size = None self._bottom_margin = int(xml.get("BottomMargin")) self._left_margin = int(xml.get("LeftMargin")) self._right_margin = int(xml.get("RightMargin")) self._top_margin = int(xml.get("TopMargin")) page_size = int(xml.get("PageSize")) page_orientation = xml.get("PageOrientation") if page_size in [30, 31]: custom_size = [int(xml.get("CustomHeightMM")), int(xml.get("CustomWidthMM"))] self._page_orientation = "P" if page_orientation == "0" else "L" self._page_size = self._parser_tools.converPageSize( page_size, int(page_orientation), custom_size) # devuelve un array def draw_margins(self): self.draw_debug_line(0 + self._left_margin , 0, 0+ self._left_margin , self._page_size[1]) #Vertical derecha self.draw_debug_line(self._page_size[0] - self._right_margin , 0, self._page_size[0] - self._right_margin , self._page_size[1])#Vertical izquierda self.draw_debug_line(0, 0 + self._top_margin, self._page_size[0], 0 + self._top_margin) #Horizontal superior self.draw_debug_line(0, self._page_size[1] - self._bottom_margin, self._page_size[0], self._page_size[1] - self._bottom_margin) #Horizontal inferior def draw_debug_line(self, X1, Y1, X2, Y2, title= None, color="GREY"): dash_length = 2 space_length = 2 r = 0 g = 0 b = 0 if color == "GREY": r = 220 g = 220 b = 220 self._document.set_line_width(1) self._document.set_draw_color(r, g, b) self._document.dashed_line(X1, Y1, X2, Y2, dash_length, space_length) def number_pages(self): return self._actual_append_page_no if self._actual_append_page_no > 0 else 0 def reset_page_no(self): self._actual_append_page_no = -1
w = pdf.get_string_width(header) + 6 pdf.set_x((210 - w) / 2) pdf.cell(w, 9, header, 0, 0, 'C') pdf.line(20, 18, 210 - 20, 18) #line break pdf.ln(10) pdf.set_font('Times', '', 12) pdf.multi_cell( 0, 5, 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.' ) pdf.ln() pdf.set_font('Arial', '', 12) pdf.set_fill_color(200, 220, 255) pdf.cell(0, 6, 'Chapter %d : %s' % (1, 'Sample Label'), 0, 1, 'L', 1) pdf.ln() pdf.set_font('Courier', 'B', 12) pdf.multi_cell( 0, 5, 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.' ) pdf.ln() pdf.set_font('', 'U', 11) pdf.multi_cell( 0, 6, 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using \'Content here, content here\', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for \'lorem ipsum\' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose.' )
def save_history(request): stdate, spdate = None, None if 'stdate' in request.GET: stdate = datetime.datetime.strptime(request.GET.get('stdate'), '%d.%m.%Y') if 'spdate' in request.GET: spdate = datetime.datetime.strptime(request.GET.get('spdate'), '%d.%m.%Y') if stdate and spdate: o = Order.objects.filter(Q(date__gte=stdate) & Q(date__lte=spdate)).order_by('date') domain = Site.objects.get_current().domain def ImprovedTable(pdf, oo, data): header = [_(u"#id"), _(u"Title"), _(u"Price"), _(u"Count"), _(u"Cost")] w = [20, 70, 20, 20, 20] for i in range(len(header)): pdf.cell(w[i], 5, u'%s' % header[i], 1, 0, 'C', 1) pdf.ln() for row in data: pdf.cell(w[0], 5, u'%d' % row.product.id, 'LR') pdf.cell(w[1], 5, u'%s' % row.product.title, 'LR') pdf.cell(w[2], 5, u'%d' % row.get_cost(), 'LR', 0, 'R') pdf.cell(w[3], 5, u'%d' % row.count, 'LR', 0, 'R') pdf.cell(w[4], 5, u'%d' % row.get_total_cost(), 'LR', 0, 'R') pdf.ln() if oo.is_delivery: pdf.cell(w[0], 5, u'-', 'LR') pdf.cell(w[1], 5, _(u"Delivery"), 'LR') pdf.cell(w[2], 5, u'%d' % oo.cost_delivery, 'LR', 0, 'R') pdf.cell(w[3], 5, u'-', 'LR', 0, 'R') pdf.cell(w[4], 5, u'%d' % oo.cost_delivery, 'LR', 0, 'R') pdf.ln() pdf.cell(sum(w), 0, '', 'T') return pdf pdf = FPDF('P','mm','A4') pdf.set_author(domain) pdf.add_page() pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True) pdf.add_font('DejaVuBold', '', 'DejaVuSansCondensed-Bold.ttf', uni=True) pdf.set_fill_color(229, 229, 229); pdf.set_font('DejaVu', '', 5); pdf.write(5, _(u"History created at %s") % datetime.datetime.now().strftime('%d.%m.%Y %H:%M')) pdf.ln(5) pdf.set_font('DejaVuBold', '', 8); pdf.write(5, _(u"History")) pdf.ln(5) for x in o: op = x.get_op() if op.count(): pdf.set_font('DejaVuBold', '', 8); pdf.write(5, u'Order #%d at %s on sum %d. Status: %s. Products:' % ( x.id, x.date.strftime('%d.%m.%Y %H:%M'), x.get_total_cost(), x.status.title )) pdf.ln(5) pdf.set_font('DejaVu', '', 5); pdf = ImprovedTable(pdf, x, x.get_op()) pdf.ln(5) s = pdf.output('History.pdf', 'S') response = HttpResponse(s, mimetype='application/pdf; charset=cp1251') response['Content-Disposition'] = 'attachment; filename=History.pdf' return response return HttpResponse('')