Last active
May 28, 2024 12:22
-
-
Save timrprobocom/3946aca8ab75df8267bbf892a427a1b7 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 | |
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)), | |
} | |
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() |
Public domain. I impose no requirements.
Thanks for this! works well with other companies too :D
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @timrprobocom what is the license of this snippet?