Script de conversion PDF

Partager sur Facebook

Le but de ce script : convertir tous les formats supportés par Word 2007 en PDF. Tout ça en ligne de commandes of course, pour pouvoir s'en servir comme on veut. Pour info, la liste des formats pris en charge :

  • docx, docm, doc
  • dotx, dotm, dot
  • htm, html, mht, mhtml
  • rtf, odt, txt, xml
  • wpd, wps

Bon maintenant je vous préviens, vu la façon dont est fichu ce script, les performances seront assez ridicules. Ca prend des ressources et c'est lent. Donc faut pas compter l'utiliser sur des gros systèmes très sollicités !

Pré-requis

Alors commençons : pour fonctionner, la machine exécutant le script doit avoir Word 2007 installé (original non ?). En fait on va manipuler Word par code C#, et vu que Word sait enregistrer en PDF depuis la version 2007...

Principe

Voilà le principe de fonctionnement du script :

  • Le script attend deux paramètres : un fichier en entrée à convertir, et un fichier en sortie (qui a priori n'existe pas donc) qui contiendra le fichier converti en PDF
  • On va utiliser le composant COM Microsoft Word afin de manipuler Word (non non, la fenêtre de Word ne s'ouvrira pas à chaque appel du script !) pour faire les opérations suivantes :
    • Ouverture du fichier dans Word
    • Sauvegarde du fichier en PDF

C'est simple non ?

Mise en oeuvre

 Entrons dans le vif du sujet :

  • On commence par créer un projet sous Visual C# (j'utilise la version gratuite Visual C# 2008 Express qui suffit amplement !)
  • Ajoutons la référence au composant COM Microsoft Word. Pour ça, faire un clic droit sur le nom du projet dans l'explorateur de solutions de Visual C#, puis faire Ajouter une référence. Sur l'onglet COM, choisir Microsoft Word 12.0 Object Library
Microsoft Word 12.0 Object Library
Microsoft Word 12.0 Object Library
  • Notre projet va se composer d'une classe qui va s'occuper de la conversion du fichier (appelons là Word2PDF par exemple), et d'une classe avec la fonction main
  • La classe Word2PDF va comporter une unique méthode statique appelée Convert (ouais je speak english moi), qui va attendre deux paramètres : fileInPath et fileOutPath. Il s'agit des chemins absolus vers le fichier à convertir, et vers le fichier à créer (le fichier PDF final
  • Pour la méthode Convert :
    • On lance une instance de Word en arrière plan
    • On ouvre le fichier à convertir dans Word
    • On enregistre ce même fichier dans le format PDF
    • On ferme le document
    • On ferme Word

Voilà à quoi pourrait ressembler notre méthode Convert :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Word;

 

...

 

public static void Convert(String fileInPath, String fileOutPath)
{
    Object fileIn = @"" + fileInPath;   // To convert file path
    Object fileOut = @"" + fileOutPath;  // Converted file path
    Object missing = Type.Missing;   // No parameter
    Document docToConvert;
    Application msWord;

    Object format = WdSaveFormat.wdFormatPDF;

    if (System.IO.File.Exists((String)fileIn))
    {
        System.Console.WriteLine("01. Le fichier existe");
        // Opening Word in background
        try
        {
            msWord = new Application();
            msWord.Visible = false;
            System.Console.WriteLine("02. Word ouvert");
        }
        catch (Exception excep)
        {
            throw new Exception("Impossible d'ouvrir Word");
        }

        // Opening the file in word
        try
        {

            docToConvert = msWord.Documents.Open(ref fileIn, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing);
            System.Console.WriteLine("03. Document ouvert dans Word");
        }
        catch (Exception excep)
        {
            msWord.Quit(ref missing, ref missing, ref missing);
            throw new Exception("Impossible d'ouvrir le fichier dans Word");
           
        }

        // Converting file
        try
        {
            docToConvert.SaveAs(ref fileOut, ref format, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing, ref missing);
            System.Console.WriteLine("04. Document converti");
        }
        catch
        {
            msWord.Quit(ref missing, ref missing, ref missing);
            throw new Exception("Impossible de sauvegarder le fichier en PDF");
        }

        // Closing document
        docToConvert.Close(ref missing, ref missing, ref missing);

        // Closing Word
        msWord.Quit(ref missing, ref missing, ref missing);
    }
    else
    {
        throw new Exception("Le fichier spécifié n'existe pas");
    }
}

Quelques précisions :

  • Le @"" dans l'affectation des variables fileIn et fileOut sert juste à dire qu'on n'interprète pas le caractère  dans la chaîne. Du coup le n'a pas son rôle d'échappement habituel
  • Les ref missing un peu partout dans les appels de fonction servent à dire que l'argument est manquant (on peut comprendre tout seul). Un peu space comme façon de faire, mais apparemment c'est un peu vieillot ce principe
  • Le reste est compréhensible non ?

Maintenant, notre méthode main pourrait ressembler à ça :

static void Main(string[] args)
{
    if (args.Length != 2)
    {
        System.Console.WriteLine("Usage : Word2PDFexe.exe <filein> <fileout>");
    }
    else
    {
        try
        {
            Word2PDF.Convert(args[0], args[1]);
        }
        catch(Exception excep)
        {
            System.Console.WriteLine(excep.Message);
        }
    }
}

Ici on se contente de vérifier que les deux arguments sont bien passés au script, puis on exécute notre méthode Convert, tout simplement.

Conclusion

Voilà, ça marche plutôt pas mal. Alors évidemment, c'est sûr que le principe de lancer Word à chaque appel de la fonction est un peu lourd. Mais pour une utilisation personnelle pour convertir un fichier de temps en temps via un petit site web perso hébergé sur son PC, c'est plutôt sympa !

Bref, pas de miracle, si ce n'est une conversion parfaite en PDF des fichiers pris en charge par Word (beaucoup de logiciels existants perdent la mise en forme).

Une petite adaptation rapide serait de sortir l'instanciation de Word de la méthode Convert afin de pouvoir convertir plusieurs documents à la suite beaucoup plus rapidement.

Nouveau commentaire

Un peu de C#
Visual Studio
Catégories
Liens