Our first born is about to arrive. Instead of writing out all the birth announcements by hand I decided to write a little python script that creates a PDF that matches sticker sheets (Herma 8632 format). It exactly took me one laptop battery charge to create this script. I refactored a bit later to be a bit more OO.
#!/usr/bin/env python3
from fpdf import FPDF
import sys
import os
# Very simple CSV to Herma 8632
# CSV expected in following format (comma separated , WITH header):
#
# Name, Relation, Street + number, ZIP, City, Country
# John Doe, friends, Stationstraat 12, 1234 DD, Duckcity, NL
def main():
args = InputParser(sys.argv)
addresses = CSVParser(args.inputFile)
hermaTemplate = Herma()
hermaTemplate.drawAddressesOnHerma(addresses.data)
hermaTemplate.save(args.outputFile)
# ------------------------------------------------------------------
## Class Definitions
class InputParser:
def __init__(self, args) -> None:
self.args = args
if len(args) != 3:
self.help()
exit(1)
self.input = args[1]
self.output = args[2]
if not os.path.exists(self.input):
print(f"Inputfile \"{self.input}\" does not exist!")
exit(1)
def help(self):
print(f"Use python3 {self.args[0]} input.csv output.pdf")
@property
def inputFile(self):
return self.input
@property
def outputFile(self):
return self.output
class CSVParser:
def __init__(self, filename) -> None:
self.addresses = []
self.filename = filename
self.parse()
def parse(self):
# TODO: File present checking
with open(self.filename) as f:
data = f.readlines()
for d in data[1:]:
split = d.split(',')
address = "\n".join([split[0], split[2], split[3], split[4], split[5]])
self.addresses.append(address)
@property
def data(self):
return self.addresses
class Herma:
def __init__(self) -> None:
self.pdf = FPDF()
self.pdf.add_page()
self.pdf.set_auto_page_break(False)
self.pdf.set_font("Times", size = 10)
self.CELL_WIDTH = 63.5
self.CELL_HEIGHT = 38.1
self.LEFT_PAGE_MARGIN = 7.21
self.TOP_PAGE_MARGIN = 15.15
self.BETWEEN_CELL_SPACE = 2.54
self.row = 0
self.col = 0
self.MAX_ROWS = 7
self.MAX_COLS = 3
def drawAddressesOnHerma(self, addresses):
for a in addresses:
x,y = self._selectCell(self.row, self.col)
self._drawAddress(x, y, a)
self._autoIncrement()
def _drawAddress(self, x, y, address):
self.pdf.set_xy(x, y+10)
for l in address.split('\n'):
self.pdf.set_x(x)
self.pdf.cell(w = self.CELL_WIDTH, h = 5, ln = 1, txt = l, align= "C")
def _selectCell(self, row, col):
x = self.LEFT_PAGE_MARGIN + (col % self.MAX_COLS) * (self.BETWEEN_CELL_SPACE + self.CELL_WIDTH)
y = self.TOP_PAGE_MARGIN + (row % self.MAX_ROWS * self.CELL_HEIGHT)
self.pdf.set_xy(x, y)
self.pdf.cell(w = self.CELL_WIDTH, h = self.CELL_HEIGHT, txt = "", border = 0)
return x,y
def _autoIncrement(self):
self.col += 1
if self.col % self.MAX_COLS == 0:
self.row += 1
if self.row % self.MAX_ROWS == 0:
self.pdf.add_page()
self.col = 0
self.row = 0
def save(self, filename):
self.pdf.output(filename)
print(f"Please find your file here: {filename}")
main()