Bonjour à tous
Peut-être certains se souviendront des temps laborieux de la programmation
sous ms-dos via des des langages tels que C, clipper ou autre.
Nous n'avions, à cette époque, pas le choix. Pour obtenir un beau rendu sur nos imprimantes laser ou jet d'encre, il fallait se taper le langage de l'imprimante. Fort heureusement, la grosse majorité de celle-ci étaient compatible avec le langage PCL (de chez HP). Ainsi, programmer l'impression d'un tableau était assez difficile à mettre en œuvre mais, néanmoins possible.
En revanche, avec le PCL, nous avions accès au contrôle de l'imprimante. Ainsi, javais eu à programmer un job complexe ou le client recevait un nombre indéterminé de pages
- Un listing en recto/verso de 1 à n pages
- Un certain nombre de fiches produit (sans recto/verso
Pour corser le tout, il fallait entre chaque client éjecter une feuille de séparation (en couleur) prise dans un autre bac.
Renversement du problème avec Python
Sous Python, nous avons un très bel outil pour faire d'impeccables mises en pages : Reportlab (il y en a d'autre mais je les connais moins). Programmer la génération d'un pdf complexe avec tableau, images etc... est presque devenu un jeu d'enfant.
En revanche, pour l' application exposée plus haut, il faudrait presque en revenir à travailler de la même façon. C'est bien la peine d'avoir des outils modernes.
Fort heureusement, il existe un produit qui s'appelle GhostScript. Mon idée
est donc de générer les pdfs avec mon outil préféré, les transformer en fichier pcl en invoquant ghostscript dans un subprocess et enfin de balancer
les fichiers pcl à l'imprimante.
J'ai mis cette solution en œuvre sous windows car c'est dans ce contexte que j'en avais besoin. En théorie, il ne doit pas être difficile de l'adapter à votre os favori.
Nous avons donc besoin d'une version de Ghoscript. Nous modifions aussi le PATH pour inclure le chemin vers l'exécutable gwin32c (sous windows 64 bit, ce serait gwin64c). Nous avons aussi besoin du package pywin32 pour balancer les données pcl à l'imprimante.
Le "cœur" du programme consiste à convertir un fichier pdf en pcl :
Ce n'est pas plus long ni plus compliqué que cela. Ceci dit, il y a certainement une manière plus élégante d'invoquer ghostscript que par subprocess. Ce qui compte c'est le principe.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 def pdftopcl(fin,fout,duplex=False): """ Utilise ghostscript pour générer un fichier pcl à partir d'un pdf Paramètres: fin : nom du fichier pdf en entrée fout : nom du fichier pcl en sortie duplex : Impression en recto/verso (côté long) Remarquons le choix du device selon le mode duplex ou pas """ duplex_print = ['gswin32c','-dBATCH','-dNOPAUSE','-dSAFER','-sDEVICE#ljet4d','-dDuplex'] simplex_print = ['gswin32c','-dBATCH','-dNOPAUSE','-dSAFER','-sDEVICE#ljet4'] cmd = [duplex_print if duplex else simplex_print] cmd.extend(['-sOutputFile#%s' % fout,fin]) subprocess.call(cmd) return fout
Une fois que nous en somme là, le reste devient trivial. On peut directement imprimer les pcl
J'espère que ce post fera le bonheur de tous ceux qui, comme moi, ont séché longtemps sur le problème.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 import win32api import win32print CMD_SEPARATOR = '\x1b'+ '&l'+ '1' + 'H' + chr(12) # Ejection d'une feuille prise dans un autre bac def chainpdfstopclprinter(pdfs,printer=None,duplex=False,separator=False): """ Imprime via pywin32 une série de fichiers pdf avec certaine option paramètres: pdfs : liste de nom de fichiers pdf en entrée printer : Nom de l'imprimante windows (si None, imprimante par défaut) duplex : Impression en recto/verso (côté long) separator : Si true, sépare les fichiers par une page prise dans un autre bac """ if printer is None: printer = win32print.GetDefaultPrinter() h=win32print.OpenPrinter(printer) win32print.StartDocPrinter(h,1,("python-pcl",None,"RAW")) for i,fpdf in enumerate(pdfs): fil = fpdf[:fpdf.index('.')]+'.pcl' pdftopcl(fpdf,fil,duplex) with open(fil,'rb') as fin: win32print.WritePrinter(h,fin.read()) if separator and i+1 < len(pdfs): win32print.WritePrinter(h,CMD_SEPARATOR) win32print.EndDocPrinter(h) win32print.ClosePrinter(h)
J'attends vos commentaires, vos critiques et vos propositions d'amélioration.
Partager