This post shows the basics of how to create a PDF invoice using Python and xtopdf, my Python library for PDF generation.
Here is the code, in file InvoiceToPDF.py. It's rudimentary, but shows the basics involved, and can be built upon to create more complex invoices with more information:
''' InvoiceToPDF.py This program shows how to convert invoice data from Python data structures into a PDF invoice. Author: Vasudev Ram Copyright 2015 Vasudev Ram ''' import sys import time from PDFWriter import PDFWriter def error_exit(message): sys.stderr.write(message) sys.exit(1) def InvoiceToPDF(pdf_filename, data): try: # Get the invoice data from the dict. font_name = data['font_name'] font_size = data['font_size'] header = data['header'] footer = data['footer'] invoice_number = data['invoice_number'] invoice_customer = data['invoice_customer'] invoice_date_time = data['invoice_date_time'] invoice_line_items = data['invoice_line_items'] except KeyError as ke: error_exit("KeyError: {}".format(ke)) try: with PDFWriter(pdf_filename) as pw: # Generate the PDF invoice from the data. pw.setFont(font_name, font_size) pw.setHeader(header) pw.setFooter(footer) pw.writeLine('-' * 60) pw.writeLine('Invoice Number: ' + str(invoice_number)) pw.writeLine('Invoice Customer: ' + invoice_customer) pw.writeLine('Invoice Date & Time: ' + invoice_date_time) pw.writeLine('-' * 60) pw.writeLine('Invoice line items:') pw.writeLine('S. No.'.zfill(5) + ' ' + 'Description'.ljust(10) + \ ' ' + 'Unit price'.ljust(10) + ' ' + 'Quantity'.ljust(10) + ' ' + \ str('Ext. Price').rjust(8)) pw.writeLine('-' * 60) sum_ext_price = 0 for line_item in invoice_line_items: id, desc, price, quantity = line_item pw.writeLine(str(id).zfill(5) + ' ' + desc.ljust(10) + \ ' ' + str(price).rjust(10) + ' ' + str(quantity).rjust(10) + \ str(price * quantity).rjust(10)) sum_ext_price += price * quantity pw.writeLine('-' * 60) pw.writeLine('Total:'.rjust(38) + str(sum_ext_price).rjust(10)) pw.writeLine('-' * 60) except IOError as ioe: error_exit("IOError: {}".format(ioe)) except Exception as e: error_exit("Exception: {}".format(e)) def testInvoiceToPDF(pdf_filename): # Get the Unix-style date from the system ... cdt = time.ctime(time.time()).split() # ... and format it a little differently. current_date_time = cdt[0] + ' ' + cdt[1] + ' ' + cdt[2] + \ ', ' + cdt[4] + ', ' + cdt[3][:5] data = { \ 'font_name': 'Courier', \ 'font_size': 12, \ 'header': 'Customer Invoice', \ 'footer': 'Generated by xtopdf: http://bit.ly/xtopdf', \ 'invoice_number': 12345, \ 'invoice_customer': 'Mr. Vasudev Ram', \ 'invoice_date_time': current_date_time, \ 'invoice_line_items': \ [ [ 01, 'Chair', 100, 10 ], \ [ 02, 'Table', 200, 20 ], \ [ 03, 'Cupboard', 300, 30 ], \ [ 04, 'Bed', 400, 40 ], \ [ 05, 'Wardrobe', 500, 50 ], \ ] } InvoiceToPDF(pdf_filename, data) def main(): if len(sys.argv) != 2: error_exit("Usage: {} pdf_filename".format(sys.argv[0])) testInvoiceToPDF(sys.argv[1]) if __name__ == '__main__': main()Run the program with a command like:
$ python InvoiceToPDF.py Invoice.pdfHere is a screenshot of the resulting PDF invoice in Foxit Reader:
Note: The use of the dict named data is not strictly needed. I simply used it to illustrate the technique of packing the multiple data items needed for the invoice, into a single dict, and then unpack those needed items in the function that actually generates the PDF. I could have done away with the dict and just used standalone variables in this simple program. But in a larger program where the invoice data is collected / generated in one or more functions, and the PDF is generated in another function, this technique or something similar can be of use, to reduce the number of individual arguments that need to be passed around.
- Enjoy.
- Vasudev Ram - Online Python training and programming Dancing Bison EnterprisesSignup to hear about new products and services that I create. Posts about Python Posts about xtopdf
No comments:
Post a Comment