Développement d'un add-in pour Microsoft Office avec .Net

MORAND Louis-Guillaume

Tutoriel pas à pas expliquant le principe, le développement et l'intégration d'un add-in dans Microsoft Office.

N'hésitez pas à commenter cet article ! Commentez ♪

- Titre : Développement d'un add-in pour Microsoft Office avec .Net

- Auteur : MORAND Louis-Guillaume

- Parution : 15 avril 2005

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2005 MORAND Louis-Guillaume. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Avant-propos

- I. Création du projet

- I-A. Introduction

- I-B. Le projet de complément Office

- II. Fonctionnement d'un add-in

- II-A. Structure d'un add-in

- II-B. Intégration dans Microsoft Office

- II-C. Interaction avec Microsoft Office

- III. Exemples concrets d'interactions

- III-A. L'environnement

- III-B. Les documents

- III-C. Le contenu

- IV. Implémentation avancée

- IV-A. La barre d'outils

- IV-B. Le bouton standard

- IV-C. La combobox

- IV-D. Le bouton menu

- V. Déploiement de l'add-in

- V-A. Préparation du setup

- V-B. Configuration du setup

- V-C. Déploiement manuel

- Conclusion

- Remerciements

Avant-propos

Cet article a été réalisé à l'aide de Microsoft Visual Studio .Net 2003, framework 1.1 et Microsoft Office 2003.

Cet article s'adresse aux personnes souhaitant ajouter des fonctionnalités à leurs applications Microsoft Office. Il est donc préférable d'avoir des bonnes bases en C# pour développer le code « fonctionnel ».

I - Création du projet

I-A - Introduction

Un add-in est une partie complémentaire d'un logiciel de base, il peut être sous la forme d'un menu principal, un menu contextuel ou même une fonction d'arrière-plan. Ici, nous verrons le fonctionnement et la création d'un complément s'intégrant à Microsoft Office, puis nous verrons plus exemples concrets d'interactions avec des applications Office.
Vous saurez donc à la fin de ce cours, comment intégrer un add-in et interagir avec les produits Microsoft Office.

I-B - Le projet de complément Office

Lancez Visual Studio .Net puis cliquez sur le menu Fichier > Nouveau > Projet.
Dans la fenêtre qui s'ouvre, choisissez alors Autres Projets > Projets d'Extensibilité puis un complément partagé

Une fenêtre de présentation rapide apparaît, suivie d'une fenêtre vous demandant le langage à utiliser. Dans notre cas, nous utiliserons du C#.

Sur la fenêtre suivante, vous devez choisir les applications dans lesquelles sera intégré votre add-in. Pour des soucis de compatibilité (fonctions de votre code spécifiques à telle ou telle application), veillez bien à ne choisir que les applications désirées. Dans cet article, nous verrons comme exemple la création d'un add-in pour Microsoft Word. Nous ne cochons donc que Microsoft Word dans la liste.

La fenêtre suivante vous demande de renseigner un nom pour votre add-in ainsi qu'une description succincte de celui-ci. Ce n'est pas forcément le nom sous lequel il apparaîtra en fonction du type d'implémentation que vous ferez, mais essayez que choisir un nom correct, qui convienne à votre add-in dans le cas où ce nom serait visible. Faites de même pour la description.

La fenêtre suivante propose deux options de votre add-in :
- la première sert à charger votre add-in automatiquement au chargement de l'application hôte (Word, Excel, Outlook, etc.). C'est l'option que vous cocherez dans la plupart des cas ;
- la deuxième option permet de définir l'accessibilité de votre add-in : soit il ne sera utilisable que par l'utilisateur l'installant, soit par tous les utilisateurs de l'ordinateur sur lequel il est installé.

Apparaît enfin la fenêtre finale, résumant les options choisies pour votre add-in. Si les options vous conviennent, cliquez sur « Terminer » pour que Visual Studio .Net autogénère le projet d'add-in.

Si vous regardez l'explorateur de solutions, vous remarquerez que Visual Studio s'est chargé de générer le projet de votre add-in, ainsi que les classes nécessaires à son fonctionnement, mais également un projet de déploiement préconfiguré pour votre add-in, ce qui vous permettra de redistribuer rapidement et facilement votre add-in sur d'autres ordinateurs.

II - Fonctionnement d'un add-in

Avant d'aller plus loin dans le développement de notre add-in, il est important de comprendre sa structure, tant au niveau de l'arborescence des fichiers et de la nomenclature de ceux-ci, que du code structuré (lui aussi possédant une nomenclature).

II-A - Structure d'un add-in

Regardons tout d'abord la structure du projet :

Notons tout d'abord le fichier assembly.cs qui contient l'assembly de notre projet et qu'il nous faudra remplir (nom, description, version) par la suite. Notons ensuite le très important fichier connect.cs. Ce fichier est obligatoire, il sert en quelque sorte de super constructeur : c'est la classe qui est appelée en premier lieu lors du chargement de l'add-in. Il est indispensable de ne pas renommer la classe qu'il contient et c'est dans cette dernière que ce retrouvera une grosse partie du code fonctionnel, à moins que vous ne préfériez (en fonction de la taille de l'add-in), séparer les fonctions, dans diverses classes.
Quant au projet de déploiement autogénéré par Visual Studio Projet, il inclut les dépendances nécessaires d'extensibilité (add-in) ainsi que les dépendances nécéssaires pour fonctionner avec Office.

Ouvrons maintenant le fichier connect.cs.
Tout d'abord, le namespace. Même s'il est créé automatiquement, il est important de ne pas le modifier : le modifier risquerait d'entraîner des problèmes d'accessibilité avec d'autres classes.

namespace MonAddinOffice

Puis l'utilisation d'autres namespaces permettant d'appeler des fonctions.

using System;
using Microsoft.Office.Core;
using Extensibility;
using System.Runtime.InteropServices;

Puis vient un minireadme qui explique que pour de certains cas, l'intégration de l'add-in dans l'application hôte peut ne plus se faire correctement (bug reconnu :D). Le premier réflexe serait de le supprimer, néanmoins je vous conseille de le garder, au moins pour vous rappeler qu'il vous suffit d'exécuter le fichier .reg qui se trouve dans le dossier du projet pour « réparer » l'add-in.

#region Read me for add-in installation and setup information.
// When run, the add-in wizard prepared the registry for the add-in.
// At a later time, if the add-in becomes unavailable for reasons such as:
// 1) You moved this project to a computer other than which is was originally created on.
// 2) You chose 'Yes' when presented with a message asking if you wish to remove the add-in.
// 3) Registry corruption.
// you will need to re-register the add-in by building the MyAddin21Setup project
// by right clicking the project in the Solution Explorer, then choosing install.
#endregion

Voici ensuite notre classe principale intégrant des interfaces spécifiques à l'interaction : Extensibility.IDTExtensibility2, IDTCommandTarget. Notez aussi l'attribution automatique d'un GUID (unique) à notre add-in.

[GuidAttribute("66CC1D78-2502-4794-A789-2238BD7586D7"), ProgId("MonAddinOffice.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2, IDTCommandTarget

Nous avons ensuite le constructeur. C'est dans celui-ci que nous pouvons mettre notre code d'initialisation (que nous verrons par la suite)

constructeur

public Connect()
{
}

Celui-ci est vide, mais comme tout constructeur il est forcément appelé et sert à mettre votre code d'initialisation.
Nous allons maintenant voir ce qu'il lui permet de s'intégrer dans une application Office.

Un add-in utilise l'interface IDTExtensibility2 qui fournit cinq évènements de base et qui correspondent aux évènements courants d'un add-in. Ces méthodes permettent à un programme de jouer le rôle de complément en répondant à des conditions de démarrage et d'arrêt de l'environnement, des évènements de connexion de complément, etc.

L'évènement OnConnection est déclenché lorsque l'add-in est chargé (connecté). Un add-in se charge dans différents cas:
- l'utilisateur charge l'add-in via la boite de dialogue des add-ins ;
- l'add-in est chargé en même temps que l'application hôte, lorsqu'il a été configuré pour démarrer avec celle-ci ;
- la propriété Connect d'un objet COMAddIn correspondant est réglée sur : True. L'objet COMAddIn représente un add-in COM dans l'application Office.

méthode OnConnection

public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst,
ref System.Array custom)
{
}

L'évènement OnDisconnection est déclenché lorsque l'add-in est déchargé. Il peut l'être de deux manières.
- l'utilisateur le décharge via la fenêtre des add-ins ;
- l'application hôte est fermée, donc l'add-in aussi par la même occasion.
Astuce : si vous souhaitez que les actions, exécutées par l'add-in dans l'application hôte, soient annulées pour le prochain démarrage (recherche, autre), vous pouvez mettre le code de nettoyage dans cette méthode.

méthode OnDisconnection

public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom)
{
}

L'évènement OnAddinsUpdate est déclenché lorsque la liste du Gestionnaire de compléments est modifiée; lorsqu'un add-in est chargé ou déchargé.

méthode OnAddInsUpdate

public void OnAddInsUpdate(ref System.Array custom)
{
}

L'évènement OnStartupComplete est déclenché lorsque l'add-in et l'application hôte ont fini de charger toutes leurs routines de démarrage. Si l'application est chargée complètement, mais si l'add-in n'est pas chargé au démarrage alors cet évènement ne s'effectue pas, même si par la suite, l'add-in est chargé via la boite de dialogue des add-ins.
Vous pouvez utiliser l'évènement OnStartupComplete pour interagir avec l'application. Par exemple, proposez des choix à l'utilisateur au démarrage de l'application hôte pour créer différents documents.

méthode OnStartupComplete

public void OnStartupComplete(ref System.Array custom)
{
}

L'évènement OnBeginShutdown est déclenché lorsque l'application hôte lance sa routine d'extinction. Cet évènement est utile pour agir avant que l'application ne se ferme (autosave par exemple).

méthode OnBeginShutdown

public void OnBeginShutdown(ref System.Array custom)
{
}

II-B - Intégration dans Microsoft Office

Un add-in est un petit programme intégré dans une application hôte dans laquelle il peut s'intégrer de deux manières.
La première, invisible, peut-être une méthode qui se lance en arrière-plan et à chaque démarrage de l'application hôte.
La deuxième, visible, peut se faire en ajoutant un menu, un menu contextuel, un bouton ou une barre d'outils.

Pour un add-in qui tourne en arrière-plan, il suffit d'ajouter le code fonctionnel dans la méthode OnConnection et ainsi l'add-in sera lancé (selon vos options) avec l'application hôte et débutera directement son fonctionnement.
Mais pour des raisons fonctionnelles et comme nous le verrons les chapitres suivants, il peut être intéressant ou tout simplement nécessaire d'ajouter des menus (ou boutons) dans l'environnement de l'application hôte afin de récupérer les choix de l'utilisateur.

Nous allons maintenant voir comment appeler notre add-in depuis l'application hôte. Pour notre exemple, nous créerons un bouton dans la barre d'outils de Microsoft Word qui nous permettra d'appeler nos méthodes. Tout d'abord, déclarons le bouton sur lequel nous baserons notre add-in.

private CommandBarButton MonBouton;

Déclarons ensuite deux variables, l'une représentant les barres d'outils de l'application hôte, la seconde représentant la barre d'outils dans laquelle nous insérerons notre bouton.

CommandBars oCommandBars;
CommandBar oStandardBar;

Puis nous les instancions :

// récupère toutes les barres d'outils de l'application
oCommandBars = (CommandBars)applicationObject.GetType().InvokeMember("CommandBars",
BindingFlags.GetProperty ,
null,
applicationObject,
null);
// récupère la barre d'outils standard
oStandardBar = oCommandBars["Standard"];
// Attention, pour Microsoft Access la barre d'outils standard se nomme "Database"

Maintenant que nous avons notre barre d'outils, nous allons y ajouter notre bouton. Pour éviter d'avoir une multitude de boutons, nous tenterons de récupérer notre bouton et s'il n'est pas présent (première utilisation, supprimé par l'utilisateur,etc.) alors nous en créerons un nouveau.

// Si le bouton n'a pas été supprimé
try
{
// texte correspondant au "caption" du bouton précédemment ajouté
MonBouton = (CommandBarButton)oStandardBar.Controls["Code Coloration"];
}
catch(Exception)
{
object omissing = Missing.Value ;
MonBouton = (CommandBarButton) oStandardBar.Controls.Add(1, omissing , omissing , omissing , omissing);
// Texte du bouton
MonBouton.Caption = "Code Coloration";
// Style du bouton. Ce sont des constantes prédéfinies
// msoButtonAutomatic, msoButtonIcon, msoButtonCaption, msoButtonIconAndCaption,
// msoButtonIconAndCaptionBelow, msoButtonIconAndWrapCaption,
// msoButtonIconAndWrapCaptionBelow, ou msoButtonWrapCaption.
MonBouton.Style = MsoButtonStyle.msoButtonCaption;
// Les éléments suivants sont facultatifs, mais recommandés.
// La propriété Tag vous permet de prendre le contrôle rapidement
// et d'aider la société à réseaux multiples à en garder une trace lorsque plusieurs
// fenêtres d'application sont visibles. Cette propriété est requise
// par certaines applications Office et doit être fournie.
MonBouton.Tag = "Coloration syntaxique du code";
// La propriété OnAction est facultative, mais recommandée.
// Elle doit être définie sur le ProgID du complément pour que,
// si le complément n'est pas chargé lorsqu'un utilisateur appuie sur le bouton,
// la société à réseaux multiples le charge automatiquement, puis déclenche
// l'évènement Click pour le complément à gérer.
MonBouton.OnAction = "!<MyCOMAddin.Connect>";
MonBouton.Visible = true;
// on ajoute une méthode à l'évènement Click de notre bouton
MonBouton.Click += new _CommandBarButtonEvents_ClickEventHandler(this.MyButton_Click);
}

Néanmoins cette méthode, propre, peut entraîner des problèmes, notamment pendant le développement de l'add-in. Il est en effet conseillé de supprimer le bouton existant et de le recréer à l'identique. En effet, si le bouton était présent, il en serait encore à la première version (installée) et chaque nouvelle version de l'add-in ne s'installerait pas correctement.

Il est maintenant nécessaire d'attacher une méthode à notre bouton, mais ne pouvant utiliser le générateur automatique de méthodes de Visual Studio, il nous faut l'écrire nous même avec les bons paramètres.

Méthode MyButton_Click

private void MyButton_Click(CommandBarButton cmdBarbutton,ref bool cancel)
{
}

C'est dans cette dernière méthode que vous devrez mettre votre code fonctionnel. Soit l'ouverture d'une fenêtre, soit une action sur l'environnement de l'application hôte (créer un document, éditer le texte, etc.).

II-C - Interaction avec Microsoft Office

Un add-in est une application qui peut agir en autonome comme n'importe quelle application .Net ou alors, elle peut interagir avec son application hôte: but premier d'un add-in :)
Pour cela, l'add-in peut « travailler » sur des instances représentant l'add-in lui-même et l'application hôte. Cette interaction nécessite une et une seule ligne de code :

Word._Application app=(Word._Application)applicationObject;

Cette ligne de code récupère une instance de l'application dans laquelle notre add-in est lancé. Pour obtenir des méthodes spécifiques à chaque application Office possible, il est nécessaire de convertir (cast) explicitement le type d'application hôte. Il est alors possible à partir de cet objet, de piloter l'application hôte. Vous pouvez entre autres, ouvrir un nouveau document, éditer le ou les documents ouverts, ouvrir de nouvelles fenêtres, quitter l'application, modifier les options de l'application, etc.

Note importante: si vous cherchez sur le net (MSDN ou forums), vous trouvez régulièrement des personnes utilisant une autre ligne de code :

Word.ApplicationClass applicationObject = (Word.ApplicationClass)application;

Cette ligne récupère également une instance de l'application hôte et permet d'appeler chaque méthode de cette instance, néanmoins aucune de ses méthodes ne marchera. Cela viendrait du fait que ApplicationClass crée une instance « neuve », utilisée pour faire de l'automation classique.

III - Exemples concrets d'interactions

Il n'est pas possible pour moi de montrer toutes les actions et/ou interactions qu'il est possible d'exécuter dans le cadre d'un add-in Office, c'est pourquoi je présenterai dans cette partie, différents cas pratiques que vous pourriez rencontrer durant vos développements.

III-A - L'environnement

Il est tout d'abord possible de modifier l'environnement de travail de différentes manières. La première façon est de modifier les options comme le montre le code suivant. Celui-ci modifie les options d'impression :

Réglage des paramètres d'application

app.Options.CommentsColor=Word.WdColorIndex.wdBlue;  // Les annotations seront dorénavant en bleu
app.Options.PrintBackground=true;                    // à l'impression, imprimer l'arrière-plan
app.Options.PrintProperties=true;                    // et inclure les propriétés du document

Il est également possible d'ouvrir les fenêtres de notre choix puis laisser l'utilisateur modifier les paramètres :

Ouverture de la fenêtre des options d'impression

object hop=10000000; // timeout
app.Dialogs[Word.WdWordDialog.wdDialogToolsOptionsPrint].Show(ref hop);

Ou encore, ouvrir une deuxième instance de l'application hôte

Nouvelle fenêtre

app.NewWindow();

III-B - Les documents

Depuis notre add-in, il est également possible de piloter les documents inclus dans l'application hôte. Vous pouvez par exemple ouvrir un nouveau document

Nouveau document

app.Documents.Add(ref missingValue, ref missingValue,ref missingValue, ref missingValue);

Ou ouvrir un document existant :

Ouverture d'un document

object fileName=@"c:\monfichier.doc";
pp.Documents.Open(ref fileName, ref missingValue, ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue, ref missingValue, ref missingValue);

Vous pouvez alors, via votre add-in, travailler sur ce document et y sauvegarder les changements :

Sauvegarde du document

app.ActiveDocument.Save();

III-C - Le contenu

Il peut être intéressant d'ouvrir des documents, les sauvegarder ou autre, mais à la seule condition que l'on puisse également les modifier.
Voyons tout d'abord comment insérer du texte dans un document.

insertion de statistiques sur le document

object missing = Missing.Value; // object "vide"
app.Selection.TypeText("il y a "+monDoc.ComputeStatistics(Word.WdStatistic.wdStatisticPages,ref missing)
+" pages dans votre document"
+ " contenant "+monDoc.ComputeStatistics(Word.WdStatistic.wdStatisticWords,ref missing)+ " mots faits de "
+ monDoc.ComputeStatistics(Word.WdStatistic.wdStatisticCharacters,ref missing)+" caractères");

Il est également possible de faire des insertions évoluées comme des paragraphes contenant un formatage spécifique (taille, couleur) :

Insertion d'un paragraphe

object missing = Missing.Value;                                   // object "vide"
Word.Document monDoc= app.ActiveDocument;                         // récupère l'instance du document Word
Word.Paragraph monPara = monDoc.Content.Paragraphs.Add(ref missing);
monPara.Range.Text="J'insère un paragraphe contenant deux lignes";// texte de mon paragraphe
monPara.Range.Font.Size=20;                                       // de taille 20
monPara.Range.Font.Color= Word.WdColor.wdColorBlue;               // couleur bleue
monPara.Range.InsertParagraphAfter();// nécessaire où le dernier paragraphe sera remplacé par celui-ci

Voyons pour finir le cas d'un mini colorateur syntaxique :

Mini colorateur syntaxique

// coloration syntaxique du code
// préparation de la sélection
object missingValue = Missing.Value; // object "vide"
Word.Document monDoc= app.ActiveDocument; // récupère l'instance du document Word

// préparation des mots clés
string[] keyword={"string","=","(",")"};
for(int i=0;i < keyword.Length;i++)
{
Word.Range monRange = app.Selection.Range;
monRange.Find.Text = keyword[i];
monRange.Find.ClearFormatting();
monRange.Find.Forward=true;
monRange.Find.Execute(ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue);
while (monRange.Find.Found)
{
if(monRange.Find.Text=="string")
{
monRange.Font.Bold=1;
monRange.Font.Color=Word.WdColor.wdColorBlue;
}
if(monRange.Find.Text=="=" ||monRange.Find.Text=="(" || monRange.Find.Text==")")
{
monRange.Font.Color=Word.WdColor.wdColorRed;
}

monRange.Find.Execute(ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue, ref missingValue, ref missingValue,
ref missingValue);
}
}

Ce dernier prend chaque mot clé de la liste et recherche dans la sélection, chaque occurrence de celui-ci et le retrouve. Le « finder » de mon range, originellement égal à ma sélection, correspond maintenant aux « coordonnées » du mot trouvé. Il est alors possible d'éditer la police de notre range.

IV - Implémentation avancée

IV-A - La barre d'outils

Comme nous l'avons vu précédemment (chapitre 2.2), la manière la plus simple de s'intégrer dans l'application hôte est d'ajouter un bouton dans l'une des barres d'outils existantes. Néanmoins, pour une meilleure visibilité et aussi pour des raisons fonctionnelles si votre add-in nécessite plusieurs boutons, il est possible de créer votre propre barre d'outils. Il est également possible d'y ajouter toutes sortes de contrôles, ce que nous verrons dans les prochains chapitres.
Il est préconisé de créer vos barres d'outils et boutons dans la méthode Connect() ou dans la méthode OnStartupComplete(). Définissez tout d'abord les objets dont vous avez besoin :

CommandBars oCommandBars; // Collection des commandbars de l'application hôte
CommandBar oStandardBar;  // Notre barre d'outils

Puis initialisons notre collection de barres d'outils puis ajoutons-lui notre barre personnelle :

oCommandBars = (CommandBars)applicationObject.GetType().InvokeMember("CommandBars",
BindingFlags.GetProperty ,
null,
applicationObject,
null);
oStandardBar = oCommandBars.Add("Ma barre d'outils", Microsoft.Office.Core.MsoBarPosition.msoBarTop, omissing, true);
oStandardBar.Visible=true; // rend la barre d'outils visible

Dans l'application hôte, votre barre d'outils sera visible par défaut et apparaîtra avec toutes les autres barres d'outils :

IV-B - Le bouton standard

Revoyons maintenant comment ajouter un bouton à cette barre d'outils. Nous déclarons tout d'abord notre bouton :

CommandBarButton MonBouton;

puis nous l'instancions en l'ajoutant directement à notre barre d'outils

MonBouton = (CommandBarButton) oStandardBar.Controls.Add(1, omissing , omissing , omissing , omissing);

et le paramétrons :

MonBouton.Caption = "Texte affiché";
// Style du bouton. Ce sont des constantes prédéfinies
// msoButtonAutomatic, msoButtonIcon (image), msoButtonCaption (texte), msoButtonIconAndCaption(image et texte),
// msoButtonIconAndCaptionBelow, msoButtonIconAndWrapCaption,
// msoButtonIconAndWrapCaptionBelow, ou msoButtonWrapCaption.
MonBouton.Style = MsoButtonStyle.msoButtonCaption;
// Les éléments suivants sont facultatifs, mais recommandés.
// La propriété Tag vous permet de prendre le contrôle rapidement
// et d'aider la société à réseaux multiples à en garder une trace lorsque plusieurs
// fenêtres d'application sont visibles. Cette propriété est requise
// par certaines applications Office et doit être fournie.
MonBouton.Tag = "Coloration syntaxique du code";
// La propriété OnAction est facultative, mais recommandée.
// Elle doit être définie sur le ProgID du complément pour que,
// si le complément n'est pas chargé lorsqu'un utilisateur appuie sur le bouton,
// la société à réseaux multiples le charge automatiquement, puis déclenche
// l'évènement Click pour le complément à gérer.
MonBouton.OnAction = "!<MyCOMAddin.Connect>";
MonBouton.Visible = true;
// configuration de la méthode
MonBouton.Click += new _CommandBarButtonEvents_ClickEventHandler(this.MonBouton_Click);

IV-C - La combobox

Il est également possible d'insérer des contrôles un petit peu plus évolués comme la combobox. Son insertion se fait de la même manière que pour le bouton. Nous créons tout d'abord notre composant :

object objType = MsoControlType.msoControlDropdown;
Macombo = (CommandBarComboBox)oStandardBar.Controls.Add(objType, omissing, omissing, omissing, (object)true);

Puis nous configurons notre combobox :

Macombo.Caption = "MonTexte";          // Texte affiché devant la combobox
Macombo = MsoComboStyle.msoComboLabel; // ou msoComboNormal;
// La propriété Caption n'est prise en compte qu'avec msoComboLabel et pas avec msoComboNormal
Macombo.BeginGroup=true;
Macombo.AddItem("item1",1);            // j'ajoute un item
Macombo.AddItem("item2",2);            // j'ajoute un autre item
Macombo.AddItem("item3",3);            // ""        ""         ""
Macombo.AddItem("item4",4);            // ""        ""         ""
Macombo.ListIndex = 1;                 // Item sélectionné
Macombo.Width = 120;                   // largeur de la combobox (label compris)

Vous pouvez y ajouter un évènement qui correspond au changement d'item sélectionné :

MaCombo.Change += new _CommandBarComboBoxEvents_ChangeEventHandler(cb_Change);

Ainsi que la méthode correspondante à l'évènement :

private void cb_Change(CommandBarComboBox cmdCbox)
{
MessageBox.Show(cmdCbox.Text);
}

La combobox permet d'avoir en premier lieu un contenu statique ou dynamique, et surtout de proposer plusieurs choix à l'utilisateur. Nous allons voir dans le chapitre suivant qu'il existe un autre moyen de proposer différents choix.

IV-D - Le bouton menu

La première chose à laquelle vous devez penser lorsque vous développez un add-in, c'est son intégration dans l'interface. Vous devez alors veiller alors à ce qu'il ne prenne pas trop de place. Le « bouton menu » peut alors vous aider. Le principe: attacher un menu sur un bouton.
Créez tout d'abord le composant :

private CommandBarPopup MonMenu; // mon controle
...
...
MonMenu = (CommandBarPopup)oStandardBar.Controls.Add(MsoControlType.msoControlPopup,
omissing,
omissing,
omissing,
true);
MonMenu.Caption="&More...";  // texte affiché
MonMenu.Tag = MonMenu.Caption;   // tooltip du controle

Maintenant, nous allons ajouter des boutons à notre bouton d'origine. Oui, nous allons créer différents boutons que nous allons ajouter à la collection de contrôles de notre bouton :

MonBoutonMenu1=(CommandBarButton)MonMenu.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton,
omissing,
omissing,
omissing,
omissing);
MonBoutonMenu1.Style = MsoButtonStyle.msoButtonCaption;
MonBoutonMenu1.Caption = "menu1";
MonBoutonMenu1.Click += new _CommandBarButtonEvents_ClickEventHandler(Bouton_Click);

...
[pour chaque menu]
...

Vous pouvez alors pour chaque « menu » définir son texte, et surtout son évènement. Vous obtenez alors un menu complètement fonctionnel :

V - Déploiement de l'add-in

V-A - Préparation du setup

Comme vous avez dû le remarquer, lors de la création de la solution pour votre add-in, Visual Studio .Net a automatiquement généré un projet de déploiement permettant de redistribuer votre add-in sous forme d'un setup. Lorsque vous compiliez votre projet, une instance de l'application hôte était lancée intégrant votre add-in. Néanmoins, à la fermeture de celle-ci, l'add-in était retiré. Plus précisément, il n'était que temporairement chargé dans l'application. Pour qu'il soit intégré définitivement, il faut qu'il soit enregistré et notre setup est là pour nous faciliter la vie, car il le fait automatiquement. Une fois, votre projet terminé, vous devez donc générer votre setup :

Puis une fois la génération terminée, vous pouvez l'installer.

Ouvrez maintenant une nouvelle instance de Visual Studio .Net et selon votre choix d'intégration, vous verrez peut-être dans le menu outils (ou autre) un menu correspondant à votre add-in.
Maintenant, tout est fonctionnel comme dans la plupart des cas, mais pour des déploiements plus professionnels, vous serez amené à modifier le fichier setup et ses actions sur le système.

V-B - Configuration du setup

Il est maintenant temps de configurer le fichier setup afin que l'installation corresponde à vos attentes. Vous noterez que le projet de déploiement ne contient aucun fichier de configuration (à part le fichier tlb que je vous déconseille d'ouvrir, car il vous sera inutile (=illisible)). Pour configurer votre setup, il vous faut remarquer les nouveaux boutons apparus au-dessus de l'explorateur de ressources

Détailler toutes les actions possibles d'un déploiement prendrait un article tout entier donc nous ne verrons ici que les fonctions les plus utilisées.
Tout d'abord, l'éditeur de registre, c'est ici que vous pouvez indiquer les clés de registre à créer. Si vous développez un add-in « mémorisant » les préférences utilisateurs il est plus simple dans ce cas de le faire via le registre. Vous pouvez donc grâce à cet onglet créer les clés qui pourront servir à la configuration de base de votre add-in.

L'éditeur de l'interface utilisateur. Cette partie va vous permettre de désigner votre fichier d'installation, aussi bien les images que les différents textes (CLUF, etc.). Il vous est également possible d'ajouter de nouvelles fenêtres avec des choix multiples permettant des installations différentes.

L'éditeur de condition de lancement. Il peut par exemple servir pour vérifier qu'un ancien add-in est dejà présent ou autre, car il vous permet de vérifier la présence de clé de registre ou de fichiers sur le disque.

L'éditeur de fichiers, permet de voir le répertoire d'installation de votre add-in et d'y placer des fichiers complémentaires (des fichiers ressources) qui pourront être appelés par votre add-in durant son fonctionnement.

Les deux onglets que je ne décris pas ici sont l'éditeur des types de fichiers, car avec un add-in, du fait de son intégration dans VS.Net ayant lui même ses propres fichiers, vous risquez d'avoir des comportements non voulus. J'ai également omis l'éditeur d'actions personnalisées, car pour la plupart des compléments qui restent simples, il n'y a pas besoin d'interagir sur le système.

Tout ceci reste une description très rapide du déploiement d'un setup, il est possible de créer des setup bien plus poussés.

V-C - Déploiement manuel

Il est également possible d'installer son add-in comme une application Office manuellement.
Ouvrez tout d'abord l'application Office de votre choix puis cliquez avec le bouton droit sur l'une des barres d'outils dans un endroit vide ou tout au bout de celles-ci puis cliquez sur le menu « personnaliser ». Cliquez alors sur l'onglet « commandes » puis choisissez « outils » dans la liste des catégories. La liste des commandes de droite de se met alors à jour. Choisissez alors « Modèles complémentaires COM » que vous ferez glisser où vous souhaitez dans l'une des barres d'outils.

Vous obtenez un nouveau bouton. Fermez alors la fenêtre de personnalisation et cliquez sur le bouton.

Cela ouvre alors une nouvelle fenêtre qui vous permet de charger l'add-in de votre choix depuis sa dll ou son exécutable.

Conclusion

Vous avez donc vu avec quelle « simplicité » il est possible de développer son propre add-in. Et plus encore, de piloter ou automatiser des actions avec des applications office.
Pour toute information complémentaire ou remarque constructive sur l'article, n'hésitez pas à me contacter par mp ou posez votre question sur le forum.

Remerciements

Je tiens à remercier François LALOUX qui m'a aidé tout au long de la rédaction de cet article ainsi que Freegreg pour ses corrections et améliorations apportées à cet article.