Exista in Python cateva solutii de construire a documentelor pdf, dar cel mai simplu (si care sa suporte si inserarea de imagini) este FPDF for Python.
Ieri am testat o solutie pentru un client si astazi m-am gandit ca ar fi bine sa o structurez sub forma unui utilitar de generare a documentelor pdf plecand de la o baza de date SQL si cateva sabloane.
Programul, in varianta ultra scurta, accepta ca argument un fisier-sablon si genereaza un document pdf conform sablonului.
Modulul fpdf se poate instala in Python cu comanda pip install fpdf
Daca programul se numeste main.py, el poate fi apelat:
#genereaza un test.pdf conform sablonului definit in interiorul programului
python main.py -t
#genereaza test1.pdf folosind test1.txt ca sablon
python main.py -i test1.txt -o test1.pdf
Programul main.py (varianta ultrascurta si compacta):
#
# Make PDF from template
#
import os, string, argparse
from fpdf import FPDF
def makePdf(template):
width, height = 600, 800
initFlag = False
lin = 0
fontsz = 12
fontfm = 'Arial'
fontst = 'B'
for i in template.split('\n'):
line = i.replace('\r','').lstrip()
if not line:
continue
if line.startswith(';'):
continue
L = [x for x in line.split() if x]
cmd = L[0].upper()
rest = string.join(L[1:])
if cmd == 'SZ':
#set document size
_w, _h = L[1].split(',')
width, height = int(_w), int(_h)
if not initFlag:
initFlag = True
pdf = FPDF(unit = "pt", format = [width, height])
pdf.add_page()
pdf.set_font('Arial', 'B', fontsz)
if cmd == 'NEWP':
#new page
pdf.add_page()
if cmd == 'FONTSZ':
#font size
fontsz = int(rest)
pdf.set_font(fontfm, fontst, fontsz)
if cmd == 'FONTFM':
#font family
fontfm = rest
pdf.set_font(fontfm, fontst, fontsz)
if cmd == 'FONTST':
#font style
fontst = rest
pdf.set_font(fontfm, fontst, fontsz)
if cmd == 'PR':
#insert text with left align
pdf.cell(0, fontsz, rest, align='L')
pdf.ln()
lin += fontsz
if cmd == 'PRC':
#insert centered text
pdf.cell(0, fontsz, rest, align='C')
pdf.ln()
lin += fontsz
if cmd == 'LN':
pdf.ln()
lin += fontsz
if cmd == 'COL':
#next 'pr' or 'prc' command will insert text starting from 'col' position
col = int(L[1])
pdf.cell(col)
if cmd == 'IM':
#insert image from local folder
filename, _w, _h = L[1].split(',')
width, height = int(_w), int(_h)
filepath = os.path.sep.join((os.getcwd(), filename))
pdf.image(filepath, w=width, h=height)
output = pdf.output(None, "S")
return output
template = '''
;
; Internal test template
;
sz 600,800
fontfm Arial
fontsz 32
pr Test 1 32 left
prc Test 2 32 center
pr Test 3 32 left
fontsz 16
pr Test 1 16 left
prc Test 2 16 center
pr Test 3 16 left
im 122.jpg,200,100
fontst
fontfm Times
fontsz 32
pr Test font Times 32
prc Test font Times centered
im 200.jpg,200,100
fontsz 64
pr Test font Times 64
fontfm Arial
fontsz 32
pr Test font Arial 32
fontsz 24
pr Test font Arial 24
fontsz 16
pr Test font Arial 16
newp
fontfm Times
fontsz 32
pr Test On new page Times 32
fontfm Arial
fontsz 32
pr Test On new page Arial 32
'''
if __name__ == "__main__":
try:
parser = argparse.ArgumentParser()
parser.add_argument("-t", help="demo generate test.pdf",
action="store_true", default=False)
parser.add_argument("-i", type=str, help="input filename")
parser.add_argument("-o", type=str, help="output filename")
args = parser.parse_args()
if args.t:
print 'Generate test.pdf from internal template'
with open('test.pdf', 'wb') as f:
f.write(makePdf(template))
else:
if args.i:
inputfile = args.i
outputfile = args.o or '{}.pdf'.format(inputfile)
print 'Generate {} from {}'.format(outputfile, inputfile)
with open(outputfile, 'wb') as f:
with open(inputfile, 'rb') as ff:
template = ff.read()
f.write(makePdf(template))
else:
parser.print_help()
except Exception as ex:
print ex
Sablonul de test inclus in program face referire la doua imagini jpg (122.jpg si 200.jpg) si imaginile trebuie sa existe in folderul curent.
Un alt exemplu de sablon:
;
; Sablon de test
;
sz 600,800
fontfm Arial
fontsz 32
prc Page 1
pr Test 1
fontsz 16
prc Page 1
pr Test 2
newp
fontsz 32
prc Page 2
pr Test 1
fontsz 16
prc Page 2
pr Test 2
Varianta pentru client include un server XML-RPC care stocheaza imagini si genereaza rapoarte pdf.