-
-
Save Friedjof/5e2681b2969b2680bae88035bd39c35d to your computer and use it in GitHub Desktop.
A class to manage printing on Avery labels with ReportLab
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from collections.abc import Iterator | |
from reportlab.pdfgen import canvas | |
from reportlab.lib.pagesizes import LETTER, landscape | |
from reportlab.lib.units import inch, mm, cm | |
from reportlab.pdfbase import pdfmetrics | |
from reportlab.pdfbase.ttfonts import TTFont | |
# Usage: | |
# label = AveryLabels.AveryLabel(5160) | |
# label.open( "labels5160.pdf" ) | |
# label.render( RenderAddress, 30 ) | |
# label.close() | |
# | |
# 'render' can either pass a callable, which receives the canvas object | |
# (with X,Y=0,0 at the lower right) or a string "form" name of a form | |
# previously created with canv.beginForm(). | |
# labels across | |
# labels down | |
# label size w/h | |
# label gutter across/down | |
# page margins left/top | |
labelInfo = { | |
# 2.6 x 1 address labels | |
5160: ( 3, 10, (187, 72), (11, 0), (14, 36)), | |
5161: ( 2, 10, (288, 72), (0, 0), (18, 36)), | |
# 4 x 2 address labels | |
5163: ( 2, 5, (288, 144), (0, 0), (18, 36)), | |
# 1.75 x 0.5 return address labels | |
5167: ( 4, 20, (126, 36), (0, 0), (54, 36)), | |
# 3.5 x 2 business cards | |
5371: ( 2, 5, (252, 144), (0, 0), (54, 36)), | |
# Din A4 2.6 x 1 address labels | |
4731: (7, 20, (25.4*mm, 13.5*mm), (0.25*cm, 0.0*cm), (0.85*cm, 0.35*cm) ) | |
} | |
RETURN_ADDRESS = 5167 | |
BUSINESS_CARDS = 5371 | |
class AveryLabel: | |
def __init__(self, label, **kwargs): | |
data = labelInfo[label] | |
self.across = data[0] | |
self.down = data[1] | |
self.size = data[2] | |
self.labelsep = self.size[0]+data[3][0], self.size[1]+data[3][1] | |
self.margins = data[4] | |
self.topDown = True | |
self.debug = False | |
self.pagesize = LETTER | |
self.position = 0 | |
self.__dict__.update(kwargs) | |
def open(self, filename): | |
self.canvas = canvas.Canvas( filename, pagesize=self.pagesize ) | |
if self.debug: | |
self.canvas.setPageCompression( 0 ) | |
self.canvas.setLineJoin(1) | |
self.canvas.setLineCap(1) | |
def topLeft(self, x=None, y=None): | |
if x == None: | |
x = self.position | |
if y == None: | |
if self.topDown: | |
x,y = divmod(x, self.down) | |
else: | |
y,x = divmod(x, self.across) | |
return ( | |
self.margins[0]+x*self.labelsep[0], | |
self.pagesize[1] - self.margins[1] - (y+1)*self.labelsep[1] | |
) | |
def advance(self): | |
self.position += 1 | |
if self.position == self.across * self.down: | |
self.canvas.showPage() | |
self.position = 0 | |
def close(self): | |
if self.position: | |
self.canvas.showPage() | |
self.canvas.save() | |
self.canvas = None | |
# To render, you can either create a template and tell me | |
# "go draw N of these templates" or provide a callback. | |
# Callback receives canvas, width, height. | |
# | |
# Or, pass a callable and an iterator. We'll do one label | |
# per iteration of the iterator. | |
def render( self, thing, count, *args ): | |
assert callable(thing) or isinstance(thing, str) | |
if isinstance(count, Iterator): | |
return self.render_iterator( thing, count ) | |
canv = self.canvas | |
for i in range(count): | |
canv.saveState() | |
canv.translate( *self.topLeft() ) | |
if self.debug: | |
canv.setLineWidth( 0.25 ) | |
canv.rect( 0, 0, self.size[0], self.size[1] ) | |
if callable(thing): | |
thing( canv, self.size[0], self.size[1], *args ) | |
elif isinstance(thing, str): | |
canv.doForm(thing) | |
canv.restoreState() | |
self.advance() | |
def render_iterator( self, func, iterator ): | |
canv = self.canvas | |
for chunk in iterator: | |
canv.saveState() | |
canv.translate( *self.topLeft() ) | |
if self.debug: | |
canv.setLineWidth( 0.25 ) | |
canv.rect( 0, 0, self.size[0], self.size[1] ) | |
func( canv, self.size[0], self.size[1], chunk ) | |
canv.restoreState() | |
self.advance() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment