Welcome, guest | Sign In | My Account | Store | Cart

This recipe shows the basics of how to generate invoices as PDF documents, using xtopdf, a Python toolkit for PDF creation. An example of creating a simple invoice through Python and xtopdf code is shown.

xtopdf is available on Bitbucket at:

https://bitbucket.org/vasudevram/xtopdf

and you can find many links with examples of using xtopdf, how to install it, etc., from this Google search:

https://google.com/search?q=xtopdf

This sub-feed of my blog:

http://jugad2.blogspot.com/search/label/xtopdf

gives access to all my blog posts labelled xtopdf.

Python, 92 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
'''
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()

While the example is simple, it illustrates some of the main things one needs to do in order to generate PDF invoices programmatically - writing invoice header fields, separator lines, invoice line items, calculations and footer fields, and left/right/center justification of text and numeric fields as needed. It can be used as a foundation to build upon, to create more complex invoices that contain more fields and more information. To keep the example small and concentrate on the main points to be shown, the invoice data is hard-coded. But the code can easily be extended to instead fetch invoice data from other sources such as a database (including across the network), flat files, CSV files, tab-delimited files, or by making API calls to a server, etc.

1 comment

Vasudev Ram (author) 8 years, 5 months ago  # | flag

More details and sample output at this blog post:

http://jugad2.blogspot.in/2015/10/create-pdf-invoices-with-python-and.html