[modif 1/11/2015: correction instruction painter.drawText: inversion de pash et pasv]
Dans le cadre d'un projet écrit en PyQt4, j'avais plusieurs impressions d'étiquettes à faire, et j'ai fini par mettre au point le code suivant.
La particularité, c'est que le programme n'imprime pas lui-même: il crée des pages .pdf. Cela permet de vérifier visuellement ce qui va être imprimé, et on laissera le visualiseur pdf utilisé (acrobat reader ou autres) imprimer lui-même.
Ce code est multiplateforme (au moins Windows-Linux)
L'impression et l'affichage des étiquettes est présenté sous forme de classe.
Les principales données à passer à l'instanciation de la classe sont:
D'autres données peuvent être modifiées (voir le code auto-documenté).
Voilà le code proposé avec son exemple d'application. Vous pouvez l'essayer avec un simple copier-coller dans idle, mais il vous faut bien sûr le module PyQt4 installé avant. Et c'est écrit en Python 2.7.
#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import division # Python 2.7 import os, sys from PyQt4 import QtCore, QtGui Apppdf = QtGui.QApplication(sys.argv) ############################################################################# class Etiquettespdf(object): """Imprime en fichier .pdf et affiche la liste d'étiquettes à imprimer""" # ======================================================================= def __init__(self, etiq, deph, pash, nbeh, depv, pasv, nbev, font=None): """Initialise toutes les variables nécessaires etiq: liste des chaines, éventuellement multilignes (avec os.linesep) deph: point de départ en mm à partir du bord gauche de la feuille pash: pas horizontal en mm entre 2 étiquettes nbeh: nombre d'étiquettes en horizontal depv: point de départ en mm à partir du bord supérieur de la feuille pasv: pas vertical entre 2 étiquettes (mm) nbev: nombre d'étiquettes en vertical font: police de caractères à utiliser (de type QFont) """ self.etiq = etiq self.deph = deph self.pash = pash self.nbeh = nbeh self.depv = depv self.pasv = pasv self.nbev = nbev self.font = font # Les var. suivantes (modifiables) ont une valeur par défaut # nom du fichier pdf à créer self.nomfichierpdf = u"etiquettes.pdf" # nom de l'application qui crée le fichier pdf self.nomapplication = u"" # nom du document pdf créé self.nomdocument = u"" # orientation de la page à imprimer self.orientation = QtGui.QPrinter.Portrait # format de la page à imprimer self.formatpage = QtGui.QPrinter.A4 # alignement de l'impression sur les étiquettes self.alignement = QtCore.Qt.AlignLeft # ======================================================================= def imprime(self): """Lance l'impression des étiquettes dans le fichier pdf donné""" # création de l'instance printer => fichier etiquettes.pdf printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution) printer.setOutputFileName(self.nomfichierpdf) printer.setCreator(self.nomapplication) printer.setDocName(self.nomdocument) printer.setPageSize(self.formatpage) printer.setOrientation(self.orientation) printer.setFullPage(True) resolution = printer.resolution() # en principe, c'est 1200dpi # conversion en pixels des distances données en mm mm2px = lambda mm: int(mm/25.4*resolution) deph = mm2px(self.deph) pash = mm2px(self.pash) depv = mm2px(self.depv) pasv = mm2px(self.pasv) # Calcul du nombre de pages: pages, sup = divmod(len(self.etiq), self.nbeh*self.nbev) if sup > 0: # dans ce cas, il y a une dernière page incomplète pages += 1 # page à créer painter = QtGui.QPainter() # impression sur le fichier pdf painter.begin(printer) if self.font!=None: painter.setFont(self.font) k = 0 # compteur du nombre d'étiquettes imprimées for page in xrange(1, pages+1): v = depv # initialisation de la coordonnée verticale de chaque étiquette for i in xrange(self.nbev): # traiter chaque ligne d'étiquette de la page h = deph# initialisation de la coordonnée horizontale de chaque étiquette for j in xrange(self.nbeh): # traiter chaque étiquette de la ligne if k < len(etiq): # écrire l'étiquette k de coordonnées [h, v] en pixels painter.drawText(h, v, pash-1, pasv-1, self.alignement, etiq[k]) k += 1 h += pash v += pasv if page < pages: # faire un 'newPage' à la fin de chaque page, sauf pour la dernière printer.newPage() painter.end() # ======================================================================= def affiche(self): """affiche le pdf créé, dans le visualiseur pdf par défaut de l'OS""" if os.path.exists(self.nomfichierpdf): try: # solution pour Windows os.startfile(self.nomfichierpdf) except: # solution pour les Linux récents os.system('xdg-open ' + self.nomfichierpdf) ############################################################################# if __name__ == "__main__": #======================================================================== # test pour les étiquettes etiq = [] for i in xrange(32): etiq.append((u"Etiquette%d" % (i+1)) + os.linesep + u"2ème ligne" + os.linesep + u"3ème ligne" + os.linesep + u"4ème ligne") deph = 26.0 # mm pash = 60.0 # mm nbeh = 3 depv = 32.0 # mm pasv = 30.0 # mm nbev = 8 font = QtGui.QFont() #font.setFamily(u"Courier New") font.setPointSize(8) #font.setItalic(True) #font.setBold(True) #font.setUnderline(True) etiquettes = Etiquettespdf(etiq, deph, pash, nbeh, depv, pasv, nbev, font) etiquettes.imprime() etiquettes.affiche()
Après impression d'une des pages, vous avez peut-être un écart de positionnement dû à un manque de précision de l'imprimante. La correction est simple. Par exemple, si vous mesurez un pas horizontal de 58 au lieu des 60 voulus, il vous suffit de multiplier les valeurs initiales par 60/58 = 1.034.
Amusez-vous bien!