Automatiser la conversion de docx en pdf 6


Dernièrement j’ai eu le problème suivant : soit un fichier Microsoft Word en .doc ou .docx, créer un programme sous Windows qui permette de convertir ce fichier en .pdf en gardant la mise en page.

Le premier réflexe : “ben je vais utiliser LibreOffice”. Une belle API Python, et tout, et tout. Mais couac, quelques fichiers de tests prouveront rapidement que la mise en page pouvait parfois être légèrement différente, ce qui ne remplissait pas le cahier des charges.

Tentative de recherche du côté de PanDoc qui prends en charge plus de formats que je ne peux en nommer. Malheureusement, le docx n’est supporté qu’en écriture. Diantre.

Une option serait d’acheter une licence Office et son plugin PDF et de scripter ça avec l’API COM, mais là ça commence à revenir cher et c’est très lourd.

Finalement j’ai opté pour un bidouillage : utiliser Microsoft Word Viewer et son addon pour docx. Ensuite, pour la conversion en PDF, on installe CC PDF Converter, qui va nous mettre une imprimante virtuelle vers du PDF.

Enfin, il fallait trouver un moyen de scripter tout ça. J’ai tenté pywinauto. Fail. AutoHotKey, erreurs aléatoires. Et finalement, AutoIt, trouvé via Sebsauvage.

Le langage est de script n’est pas (trop) horrible, et facile à comprendre :

; Matcher le nom des fenêtre par morceau sans se
; soucier de la casse.
AutoItSetOption('WinTitleMatchMode', -2) 

; Chopper les options de la ligne de commande
$VIEWER_EXE = "C:\Program Files (x86)\Microsoft Office\OFFICE11\WORDVIEW.EXE"
$FROM = $CmdLine[1] 
$TO = $CmdLine[2]

; Fermer ou force killer tout ce qu'on a pu ouvrir précédement
Winclose('reader')
Winclose('viewer')
Winkill('reader')
Winkill('viewer')

; Ouvrir MS Word Viewer, et répondre "oui" à 
; tout pop up qui s'ouvre en appuiyant sur
; Entrée
Run($VIEWER_EXE & " " & $FROM)
WinWaitActive('viewer', '', 2)
Send('{Enter}')

; Utiliser Ctrl + P pour demander une
; impression. Les paramètres par défaut
; sont ok : couleur, 1 copie, le tout
; sur le Bureau.
Send('^p')
WinWaitActive('imprimer', '', 2)
Send('{Enter}')

; On attent qu'apparaisse la fenêtre 
; de choix de nom de fichier pour la 
; sortie en PDF. Le focus est automatiquement
; sur le champ "name"; on a juste à écrire
; le nom de fichier de dans et à faire
; Entrée.
WinWaitActive('select a filename', '', 2)
Send($TO)
Send('{Enter}')

; Si le fichier existe déjà, il va 
; demander confirmation d'écrasement
; ce qu'on fait. Si la fenêtre 
; n'apparait pas, Alt+O ne fait rien
; de bien méchant de toute façon.
WinWaitActive('confirmer', '', 2)
Send('!o')

; On attend que le lecteur PDF se lance,
; prouvant que le fichier est prêt.
WinWaitActive('reader')

; Le PDF est prêt. On va pisser un coup.
; On ferme aussi toutes les fenêtres à 
; coup de marteau.
Winclose('reader')
Winclose('viewer')
Winkill('reader')
Winkill('viewer')

Voilà c’était le code dégueulasse du jour, Max serait fier de moi. Evidement c’est très fragile : dépendant de la config, de la langue, etc.

Mais zob, j’ai mon PDF.

6 thoughts on “Automatiser la conversion de docx en pdf

Leave a comment

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.