Tag Archives: Word

Convertisseur Word vers PDF en ligne de commande


J’ai besoin de convertir de documents docx en pdf afin d’intégrer la génération de documentations dans mes build TFS2010. Malheureusement, les outils de « conversion » word->pdf sont la plupart du temp des drivers d’impression ou nécessitent une action manuel. Voici donc deux bout de code. Le premier avec uniquement le code de sauvegarde en pdf et le second pour une application avec deux arguments in: et out:, une vérification de la validité des arguments et l’émission de logs d’erreur dans l’event log windows. (L’application allant tourner en background lors des build, c’est le seul moyen propre de savoir ou ca à merdé)
Donc on commence par ouvrir une instance Word et un document de manière classique. (Classique a l’interop office). Ensuite, il suffit de définir quelques variables, mais le principal se joue sur le WdSaveFormat à définir en temp que wdFormatPDF. Voici le code :

    object inputFilePath = @"C:\teste.docx";
    object outputFilePath = @"C:\teste.pdf";

    object typeMissing = Type.Missing;

    // Création d'une instance
    _Application application = new Microsoft.Office.Interop.Word.Application();

    // La rendre invisible
    application.Application.Visible = false;

    // Ouvrir le fichier word
    Documents documents = application.Documents;
    _Document document = documents.Open
                        (ref inputFilePath, ref typeMissing, ref typeMissing, ref typeMissing,
                        ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                        ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                        ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing);

    // Définition des arguments de sauvegarde
    object FileFormat = WdSaveFormat.wdFormatPDF;
    object LockComments = false;
    object AddToRecentFiles = false;
    object ReadOnlyRecommended = false;
    object EmbedTrueTypeFonts = true;
    object SaveNativePictureFormat = false;
    object SaveFormsData = false;
    object SaveAsAOCELetter = false;
    object InsertLineBreaks = false;
    object AllowSubstitutions = false;
    object LineEnding = WdLineEndingType.wdCRLF;
    object AddBiDiMarks = false;

    // Saauvegarde
    document.SaveAs2(ref outputFilePath,
                    ref FileFormat,
                    ref LockComments,
                    ref typeMissing,
                    ref AddToRecentFiles,
                    ref typeMissing,
                    ref ReadOnlyRecommended,
                    ref EmbedTrueTypeFonts,
                    ref SaveNativePictureFormat,
                    ref SaveFormsData,
                    ref SaveAsAOCELetter,
                    ref typeMissing,
                    ref InsertLineBreaks,
                    ref AllowSubstitutions,
                    ref LineEnding,
                    ref AddBiDiMarks);

    // Fermerture
    application.Quit();
}
catch (Exception ex)
{
    WriteLog(String.Format("Application Excepetion for files : " +
                            "\nInput : {0}\nOutput : {1}\nError : {2}",
                            inputFilePath, outputFilePath, ex.Message));
}

Et la version « directement utilisable » :

static void Main(string[] args)
{
    Program p = new Program();
    if (p.CheckInput(args))
        p.Convert();
}

private object inputFilePath = null;
private object outputFilePath = null;

// Quelques vérifications basique.
public bool CheckInput(string[] args)
{
    // Check nombre d'arguments
    if (args.Length != 2) 
       { WriteLog("Nombre d'arguments invalide"); return false; }

    // Récupèration
    foreach (string a in args)
    {
        if (a.StartsWith("in:")) inputFilePath = a.Substring(3);
        if (a.StartsWith("out:")) outputFilePath = a.Substring(4);
    }

    // Verification non null
    if (inputFilePath == null) 
        { WriteLog("Fichier d'entré non spécifié"); return false; }
    if (outputFilePath == null) 
        { WriteLog("Fichier de sortie non spécifié"); return false; }

    // Verification existence input
    if(!(File.Exists(inputFilePath.ToString()))) 
        { WriteLog("Fichier d'entré n'existe pas"); return false; }
           
    return true;
}

public void Convert()
{
    try
    {
        object typeMissing = Type.Missing;

        // Création d'une instance
        _Application application = new Microsoft.Office.Interop.Word.Application();

        // La rendre invisible
        application.Application.Visible = false;

        // Ouvrir le fichier word
        Documents documents = application.Documents;
        _Document document = documents.Open
                         (ref inputFilePath, ref typeMissing, ref typeMissing, ref typeMissing,
                            ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                            ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                            ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing);

        // Définition des arguments de sauvegarde
        object FileFormat = WdSaveFormat.wdFormatPDF;
        object LockComments = false;
        object AddToRecentFiles = false;
        object ReadOnlyRecommended = false;
        object EmbedTrueTypeFonts = true;
        object SaveNativePictureFormat = false;
        object SaveFormsData = false;
        object SaveAsAOCELetter = false;
        object InsertLineBreaks = false;
        object AllowSubstitutions = false;
        object LineEnding = WdLineEndingType.wdCRLF;
        object AddBiDiMarks = false;

        // Saauvegarde
        document.SaveAs2(ref outputFilePath,
                        ref FileFormat,
                        ref LockComments,
                        ref typeMissing,
                        ref AddToRecentFiles,
                        ref typeMissing,
                        ref ReadOnlyRecommended,
                        ref EmbedTrueTypeFonts,
                        ref SaveNativePictureFormat,
                        ref SaveFormsData,
                        ref SaveAsAOCELetter,
                        ref typeMissing,
                        ref InsertLineBreaks,
                        ref AllowSubstitutions,
                        ref LineEnding,
                        ref AddBiDiMarks);

        // Fermerture
        application.Quit();
    }
    catch (Exception ex)
    {
        WriteLog(String.Format("Application Excepetion for files : " +
                                "\nInput : {0}\nOutput : {1}\nError : {2}",
                                inputFilePath, outputFilePath, ex.Message));
    }
}

void WriteLog(string message)
{
        // Ecriture dans l'event log
        string sSource = "Word To Pdf Tool";
        string sLog = "Application";
        string sEvent = message;

        // Vérification de la source, != création
        if (!EventLog.SourceExists(sSource)) EventLog.CreateEventSource(sSource, sLog);

        // Enregitrement du log
        EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Error, 234);
        Console.WriteLine(sEvent);
}

Exécution de macro dans Word depuis du C#

Voici un petit bout de code qui vous permettra d’appeler des macro dans un document, par exemple pour remplir une template.

Tout d’abord il faut rajouter une référence vers la librairie Microsoft.Office.Interop.Word
Ensuite on ouvre le document, la méthode open prend beaucoup d’arguments mais il ne faut pas être effrayé par la quantité, en effet il s’agit entre autre des user/pwd, read-only et ce genre de chose. De plus une description dans l’IntelliSense est disponible, so don’t worry be happy.

object filePath = @"C:\Users\Manu\Documents\Visual Studio 2010\Projects\MacroCall\MacroCall\bin\Debug\mondoc.docm";
object typeMissing = Type.Missing;
_Application application = new Microsoft.Office.Interop.Word.Application();
Documents documents = application.Documents;
_Document document = documents.Open
                    (ref filePath, ref typeMissing, ref typeMissing, ref typeMissing,
                    ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                    ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                    ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing);

Le document ouvert on vas créer une copie en l’enregistrant sous, les opérations suivantes s’exécuteront sur la copie et non sur l’original. La encore, la methode SaveAs est equivalente a la méthode Open.

object newFilePath = @"C:\Users\Manu\Documents\Visual Studio 2010\Projects\MacroCall\MacroCall\bin\Debug\mondoc2.docm";

document.SaveAs2(ref newFilePath, ref typeMissing, ref typeMissing, ref typeMissing,
                    ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                    ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing,
                    ref typeMissing, ref typeMissing, ref typeMissing, ref typeMissing);

Notre documenté chargé et un copie faite, nous allons passer a l’appel de nos macros.
Voici leur code :

Sub Macro1()
    Label1.Caption = "De la macro"
End Sub

Sub Macro2(p As String)
    Label1.Caption = p
End Sub

Sub AddProducts(productName As String, quantity As String, unitPrice As String)
    Dim oTable As Table
    Dim oCell As Cell
    Dim oNewRow As Row

    Set oTable = ActiveDocument.Tables(1)
    oTable.Rows.Add
    Set oNewRow = oTable.Rows(oTable.Rows.Count)

    oNewRow.Cells(0).Range = productName
    oNewRow.Cells(1).Range = quantity
    oNewRow.Cells(2).Range = unitPrice
End Sub

La première vas juste remplir un label avec « De la macro » et la seconde vas rajouter dans un autre label le texte passé en argument, la dernière rajoute une ligne a un tableau et y insère les éléments passé en argument.

L’appel de macro s’exécute via la méthode InvokeMember. Les arguments sont le nom de la méthode à appeler suivi des BindingFlags, le binder a utiliser, la cible de l’invoke et enfin les arguments sous forme d’un tableau d’objet.
Basiquement, seul le tableau d’objet différera d’un appel de macro a l’autre.
Il suffit de mettre en première position le nom de la macro et rajouter ensuite un élément pour chaque argument nécessaire a la macro.
Voici nos 3 tableaux pour les 3 macros

Object[] Macro1 = new Object[] { "Macro1" };
Object[] Macro2 = new Object[] { "Macro2", "Mon Texte A Afficher" };
Object[] AddProducts = new Object[] { "AddProducts", "C# 4.0 - Ref Book", "1", "45€"};

Maintenant on les appels

application.GetType().InvokeMember
(
    "Run",
    System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod,
    null,
    application,
    Macro1
);
application.GetType().InvokeMember
(
    "Run",
    System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod,
    null,
    application,
    Macro2
);
            application.GetType().InvokeMember
(
    "Run",
    System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod,
    null,
    application,
    AddProducts
);

Et c’est fini, quand nous allons voir notre document, les macros se sont bien executés.

Publication sur WordPress directement depuis Microsoft Office 2010

Salut à a tous, un message pour vous présenter une fonctionnalité géniale sous MS Office 2010. La publication automatique sur son hébergeur.

La démarche est simple, créez un nouveau fichier puis rendez-vous dans Fichier->Enregistrer & Envoyer -> Publier en temps que billet de blog.

Ensuite, MS Office vous demandera quel système vous utilisez (prenez WordPress.com) et vos identifiants. Vous aurez une version adapté des outils d’édition pour publier sur WP :


Et pour ma part, ce que m’emballe le plus, c’est que si je met une image ou une ressource, elle est automatiquement uplodé et la mise en page est intacte.

Merci Microsoft ! Merci WordPress.com !

Inform@tiquement
Manu404