Les VSTO 2 (Visual Studio 2005 Tools For Office) représentent la nouvelle génération d'outils de développement d'applications Microsoft Office.
Cet article vous présentera ces outils ainsi que leurs fonctionnalités.
Les VSTO 2 (acronyme de Visual Studio 2005 Tools For Office) vous permettent de réaliser rapidement des applications Microsoft Office complexes.
En effet, cette nouvelle version, tout comme la précédente, vous permet d'utiliser toute la puissance de .NET pour la réalisation de vos applications.
Cette version des VSTO apporte beaucoup de nouvelles fonctionnalités, dont les plus intéressantes sont sans doutes:
une intégration complète d'Office (Word/Excel) dans l'IDE Visual Studio 2005
une facilité de développement (drag & drop, etc...)
Cette intégration dans Visual Studio vous permet d'utiliser toutes les possibilités de l'IDE (assistants, etc...) pour la réalisation de vos applications.
De plus, de part l'utilisation du glisser-déposer, vous avez une rapidité de développement accrue par rapport au développement VBA (Visual Basic for Application).
Pour bien comprendre cette intégration, je vous propose de voir cela en images.
Voici une images des VSTO 1:
Maintenant, voici un aperçu des VSTO 2:
Non non, vous ne rêvez pas : dans la version 2, votre application Microsoft Office est complètement intégrée dans Visual Studio: vous pouvez alors tout aussi bien glisser/déposer des composants, qu'utiliser les menus d'Office.
Voila qui simplifie bien la vie n'est-ce pas ;)
I-B. Comment ça marche ?
Les applications Microsoft Office sont des serveurs COM. Par conséquent, l'intéraction entre une application Microsoft Office et du code .NET se nomme "Interop COM".
Lorsque vous développez, vous écrivez votre code managé (votre code .NET) dans une "Interop Assembly" (IA), qui est l'équivalent managé .NET de la librairie COM.
Avec Microsoft Office 97 et Microsoft Office 2000, ces IAs sont auto-générées avec l'outil TlbImp: cet outil, livré avec le Framework .NET, sert à lire une librairie COM et à générer l'IA correspondante permettant son utilisation par du code .NET.
De son coté, Microsoft Office XP inclut, quant à lui, des IAs prégénérées (et optimisées) que vous devez utiliser plutôt que les IAs auto-générées par TlbImp.
Une IA distribuée par le propriétaire original d'un serveur COM est appellée "Primary Interop Assembly" (PIA) et Microsoft met à disposition des développeurs les PIAs d'Microsoft Office XP et d'Microsoft Office 2003 (consultez ce lien si vous désirez plus d'informations sur les PIAs et les IAs).
Vous devez penser à toujours utiliser la version spécifique de l'IA qui correspond à la version d'Office que vous voulez manipuler.
Exemple pour Microsoft Word:
Microsoft Office 97: Microsoft Word 8.0 Object Library
Microsoft Office 2000: Microsoft Word 9.0 Object Library
Microsoft Office XP: Microsoft Word 10.0 Object Library
Microsoft Office 2003: Microsoft Word 11.0 Object Library
Lorsque vous déployez une application qui utilises les PIAs d'Office XP, vous pouvez les déployer dans le même répertoire que votre application Microsoft Office. Mais une meilleur approche est d'installer ces PIAs dans la GAC de la machine cible.
Pour le déploiement d'applications Microsoft Office 2003, les PIAs ne doivent pas être déployées en même temps que l'application: Microsoft recommande que seul l'installation d'Office doit être le seul mécanisme pour installer ces PIAs (lors de l'installation d'Office, vous devez être sur d'avoir coché "Support de la programmation .NET", uniquement possible si vous avez installez le Framework .NET 1.1/2.0 et que vous êtes en mode "Installation Personnalisée" et non pas "Installation Typique").
II. Possibilités des VSTO 2
Cette nouvelle version des VSTO vous permet une intéraction complète avec Word, Excel ou Outlook.
En effet, vous avez la possibilité de:
Gérer et créer des tableaux : vous pouvez ainsi ajouter un nouveau tableau, ajouter ou supprimer des lignes à un tableau déjà existant, etc.
Gérer des graphiques : là encore, vous êtes entièrement libre d'ajouter ou supprimer des graphiques à votre documents, etc.
Créer des barres de menus personnalisées: si votre application nécessite sa propre barre de menu, intégrée directement dans votre document Word et/ou Excel, rien de plus facile.
Voici d'ailleurs un exemple de code vous montrant comment ajouter un graphique à une feuille Excel:
Ajout d'un graphique
// On cherche la feuille qui nous intèresse
Worksheet xlSheet = (Worksheet)this.Worksheets[1];
// On définit la plage de donnée à utiliser. // Dans notre cas, on utilise le tableau ListObjects (objet de type ListObject déclaré plus haut)
Excel.Range cellRange = (Excel.Range)xlSheet.ListObjects[1].Range;
// On ajoute un nouveau graphique
Excel._Chart xlChart = (Excel.Chart)this.Charts.Add(missing, missing, missing, missing);
// On définit le type de graphique
xlChart.ChartType = Excel.XlChartType.xl3DColumn;
// On indique la source de données du graphique // Dans notre cas, on utilise la colonne prix du tableau ListObject
xlChart.SetSourceData(cellRange.Columns.get_Range("C1", "C2"), Type.Missing);
// On donne un nom au graphique
xlChart.HasTitle = true;
xlChart.ChartTitle.Font.Size = 16;
xlChart.ChartTitle.Font.Bold = true;
xlChart.ChartTitle.Text = "Graphique du prix des produits";
// On définit les 2 axes du graphique, et leur propriétés
Excel.Axis axis;
axis = (Excel.Axis) xlChart.Axes(Excel.XlAxisType.xlCategory, Excel.XlAxisGroup.xlPrimary);
axis.HasTitle = true;
axis.AxisTitle.Text = "Produit";
axis.HasMajorGridlines = true;
axis.HasMinorGridlines = false;
axis = (Excel.Axis) xlChart.Axes(Excel.XlAxisType.xlValue, Excel.XlAxisGroup.xlPrimary);
axis.HasTitle = true;
axis.AxisTitle.Text = "Prix";
axis.HasMajorGridlines = true;
axis.HasMinorGridlines = false;
// On s'occupe de la légende
xlChart.WallsAndGridlines2D = false;
xlChart.HasLegend = true;
// On sélectionne la légende et on indique sa postion
xlChart.Legend.Select();
xlChart.Legend.Position = Excel.XlLegendPosition.xlLegendPositionRight;
// Et enfin, on indique la position du graphique: si c'est un nouvelle feuille
// ou si on incorpore le graphique dans notre feuille
xlChart.Location(XlChartLocation.xlLocationAsObject, xlSheet.Name);
Ce qui donne ceci dans notre application
Bien sûr, il vous est toujours possible de rajouter, directement depuis la feuille Excel, un ligne à votre tableau Excel, ce qui aura pour résultat de rajouter une colonne à votre graphique.
Comme vous l'aurez compris, le tableau représente la source de données de votre graphique, c'est pourquoi ajouter une ligne à ce tableau ajoute une ligne à votre graphique.
Si vous désirez ajouter une barre de menu personnalisée, rien de plus simple:
Ajout d'une barre de menu
// La barre de menuprivate Office.CommandBar cbar = null;
// Les items de la barreprivate Office.CommandBarButton cbPrintPreview = null;
private Office.CommandBarButton cbSaveAs = null;
// Les évènements qui se produisent lors du clic sur les items de la barreprivate Office._CommandBarButtonEvents_ClickEventHandler cbPrintPreviewClickEvent;
private Office._CommandBarButtonEvents_ClickEventHandler cbSaveAsClickEvent;
// On peut omettre les paramètres optionnelsobject oMissing = System.Reflection.Missing.Value;
// Texte de la barre de menu + position
cbar = this.Application.CommandBars.Add("Menu .NET Solutions", oMissing, oMissing, (object)true);
// Ajout d'un nouveau bouton pour Aperçu avant Impression
cbPrintPreview = (Office.CommandBarButton)(cbar.Controls.Add((object)1, oMissing, oMissing, oMissing, oMissing));
// Type de bouton
cbPrintPreview.Style = Office.MsoButtonStyle.msoButtonCaption;
// Texte du Bouton
cbPrintPreview.Caption = "Aperçu Avant Impression";
// Méthode à appeller lors du clic sur l'item
cbPrintPreviewClickEvent = new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(
cbPrintPreviewClickEvent_Click);
cbPrintPreview.Click += cbPrintPreviewClickEvent;
// Ajout d'un nouveau bouton pour Sauvegarder la fiche
cbSaveAs = (Office.CommandBarButton)(cbar.Controls.Add((object)1, oMissing, oMissing, oMissing, oMissing));
// Type de bouton
cbSaveAs.Style = Office.MsoButtonStyle.msoButtonCaption;
// Texte du Bouton
cbSaveAs.Caption = "Sauvegarder la fiche";
// Méthode à appeller lors du clic sur l'item
cbSaveAsClickEvent = new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(
cbSaveAsClickEvent_Click);
cbSaveAs.Click += cbSaveAsClickEvent;
// On insère un séparateur entre les éléments du menu
cbSaveAs.BeginGroup = true;
// On affiche la barre de menu
cbar.Visible = true;
privatevoid cbPrintPreviewClickEvent_Click(Office.CommandBarButton btn, refbool Cancel)
{
// Lancement de l'aperçu avant impressionthis.PrintPreview((object)true);
}
privatevoid cbSaveAsClickEvent_Click(Office.CommandBarButton btn, refbool Cancel)
{
// On demande le nom du fichierif (this.sfdSaveAs.ShowDialog() == DialogResult.OK)
{
// On peut omettre les paramètres optionnelsobject oMissing = System.Reflection.Missing.Value;
string filename = this.sfdSaveAs.FileName;
// Enregistrement du fichierthis.SaveAs(filename, oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing);
}
}
Notez que vous avez la possibilité de changer l'apparence de votre bouton (dans la barre d'outils) au moyen de la propriété Style, qui prend ses valeurs dans l'énumération Office.MsoButtonStyle:
Voici un aperçu de ce que donne le code d'ajout d'une barre de menu personnalisée:
Comme vous le voyez, cela s'avère relativement simple: il vous suffit juste d'un peu de pratique.
Bien sur, les VSTO 2 vous permettent également pas mal d'autres choses. En effet, vous avez la possibilité d'intéragir complètement avec l'ActionsPane (le panneau d'actions des documents Microsoft Office): nous verrons cela dans le chapitre suivant.
Sachez qu'il vous est aussi possible, grâce à cette technologie, d'utiliser des Datasets, des Web Services, etc. au sein de votre application.
Pour faire simple, retenez une chose sur les possibilités des VSTO: Toutes les possibilités offertes par le Framework .NET peuventêtre utilisées pour le développement de votre application !
III. L'ActionsPane
Comme dit un peu plus haut, l'ActionsPane est le panneau d'actions des documents Microsoft Office, disponible depuis Microsoft Office 2003. Si vous ne voyez pas de quoi je veux parler, ouvrez Word ou Excel et appuyez sur Control + F1: sur la droite de votre document apparaît un volet.
Avec les VSTO 2, vous avez la possibilité de modifier, de manipuler complètement ce volet pour pouvoir l'utiliser dans votre application (on peut par exemple imaginer une application utilisant des Web Services pour afficher dans ce volet, le prix de produits, etc.)
Avec les VSTO 2, vous devez savoir que tout est objet ! Par conséquent, même cet ActionsPane est un objet. Et qui dit objet dit propriétés, méthodes, etc.
Voyons cela en exemple:
Ajout de contrôles au panneau d'actions
// Au démarrage de l'application// on ajoute notre TextBox au panneau d'actionsthis.ActionsPane.Controls.Add(new TextBox());
Comme vous pouvez le voir, il est très simple d'ajouter un contrôle à notre panneau d'actions. Voyons un peu plus d'explications ce bout de code:
this: Représente l'instance de notre objet courant (notre feuille Excel ou notre document Word par exemple)
ActionsPane: Représente notre objet ActionsPane
Controls: C'est la collection qui regroupe tous les contrôles enfants contenus dans l'objet ActionsPane
Add: Il s'agit de la méthode à utiliser pour ajouter un contrôle à la collection de contrôle déjà existante. Cette méthode prend en paramètre un objet de type Control.
Bien sur, pour notre exemple, l'ActionsPane est utilisé de façon très simple. Mais sachez que vous avez la possibilité de vous connecter à un Web Service, d'utiliser des Dataset, des UserControls, etc. Bref, cet ActionsPane est entièrement personnalisable !
Lorsque vous ajoutez un contrôle à l'ActionsPane, celui-ci est automatiquement affiché. Mais vous pouvez facilement le cacher/faire apparaitre, en utilisant les méthodes Show() et Hide() de votre objet ActionsPane.
IV. Les autres objets particuliers
L'ActionsPane n'est pas le seul objet intéressant qu'il vous est possible d'utiliser dans vos développements. En effet, Word et Excel possèdent leur propres objets "particuliers" que nous allons voir tout de suite.
IV-A. Word
IV-A-1. Bookmark
L'objet Bookmark, disponible dans Word, vous permet la gestion des signets. Un bookmark est un signet, un marqueur de position, qui vous permet de retrouver ou d'insérer du texte, des tableaux, des objets OLE, etc... à une position donnée.
Il est alors possible d'ajouter, de modifier ou bien même de supprimer des bookmarks de votre document.
Cette manipulation des signets s'applique aux bookmarks que vous avez manipulé depuis votre application, mais également aux bookmarks déjà existants dans votre document Word.
Voyons un petit exemple:
Utilisation des Bookmarks
// On Accède aux champs/propriétés du document principal, au moyen de la classe Globals.// On change la valeur des Bookmarks, en fonction du choix de l'utilisateur
Globals.ThisDocument.bkmClientName.Text = this.cbClient.SelectedValue.ToString();
Globals.ThisDocument.bkmClientAdress.Text = this.tbAdress.Text;
Globals.ThisDocument.bkmClientCP.Text = this.tbCP.Text;
Globals.ThisDocument.bkmClientCity.Text = this.tbCity.Text;
Ainsi, manipuler les signets de Word s'avère d'une simplicité extrême.
Voyons à présent les objets disponibles dans Excel.
IV-B. Excel
IV-B-1. NamedRanged
L'objet NamedRanged dans Excel pourrait être comparé à l'objet Bookmark de Word. En effet, il s'agit d'une collection nommée de cellules au sein de votre feuille Excel.
Il est alors possible de modifier la taille du texte, la police utilisée, etc. des cellules contenues dans ce NamedRanged.
Voyons cela un peu mieux:
Utilisation d'une NamedRanged
// On remplit les valeurs à afficher dans les NamedRangedthis.namedProductId.Value2 = String.Format("ID du produit");
this.namedProductName.Value2 = String.Format("Nom du produit");
this.namedProductPrice.Value2 = String.Format("Prix du produit");
// On passe le texte de cette NameRanged en grasthis.namedProductPrice.Font.Bold = true;
// On change la couleur du texte// Voir ici pour la liste des codes couleur: http://www.geocities.com/davemcritchie/excel/colors.htmthis.namedProductPrice.Font.ColorIndex = 30;
// On change la taille du texte.this.namedProductPrice.Font.Size = 20;
IV-B-2. ListObject
Le ListObject est l'objet que vous devez utiliser si vous devez afficher des données de façon structurée. En effet, cet objet vous permet d'afficher, sous forme de tableau, un ensemble de données.
Vous avez la possibilité, très pratique, de trier les données: cette fonctionnalité étant implémentée automatiquement par votre objet, vous n'avez rien à faire.
Le tableau généré est en lecture/écriture: par conséquent, dans le cas où la source de données de votre objet ListObject est une base de données, il est possible de faire des modifications sur celle-ci directement depuis votre ListObject.
Pour faire un tableau en lecture seule, vous avez 2 possibilités:
ne pas appeler la méthode Update de votre DataAdapter. Bien que cela fonctionne, je trouve que cela n'est pas très... "propre", c'est pourquoi il existe la deuxième solution
appeler la méthode Disconnect de votre objet ListObject, et cela juste après l'avoir remplit.
Attention, la méthode Disconnect n'est disponible que depuis la CTP de Juin de Visual Studio 2005 (source). Ainsi, la BETA 2 de Visual Studio 2005 ne prend pas en compte cette méthode.
Pour définir la source de données de votre ListObject, il vous suffit de définir sa propriété DataSource, soit en passant par le Designer, soit avec une ligne de code:
Ainsi, l'utilisation (et la manipulation) de cet objet se révèle efficace, simple et surtout extrêment rapide.
V. Les SmartTags
Les SmartTags permettent la reconnaissance de texte dans votre document Microsoft Office. Vous avez la possibilité d'exécuter une ou plusieurs actions (c'est à vous de choisir, selon vos besoins) lorsque la reconnaissance de texte est effectuée.
Les SmartTags existent dans Microsoft Office depuis Microsoft Office XP et ont été améliorés dans Microsoft Office 2003 (source).
Voici une image vous montrant comment voir qu'un texte a été reconnu:
Et voici ce qui se passe lorsque l'on clique sur le SmartTag:
Voici un exemple de code vous montrant comment implémenter les SmartTags dans votre application VSTO:
Mise en place des SmartTags
// Action à exécuter pour le click sur le SmartTagprivate Action myAction;
// On définit le SmartTag: on spécifie un nom unique pour le SmartTag// L'URI ne doit pas contenir d'espace
SmartTag mySmartTag = new SmartTag("http://smarttags.vsto.com#NETSolutionsSmartTag", "NET Solution SmartTag");
// On indique le terme à reconnaitre
mySmartTag.Terms.Add("VSTO");
// On donne un nom à l'action qui sera affichée dans le menu du SmarTag
myAction = new Action("SmartTag NET Solutions - Cliquez moi");
// On indique quelle est l'action à exécuter pour ce SmartTag
mySmartTag.Actions = new Action[] { myAction };
// Et sur quelle action (Dans notre cas, un Click)
myAction.Click += new ActionClickEventHandler(myAction_Click);
// On ajoute le SmartTag au document
Globals.ThisWorkbook.VstoSmartTags.Add(mySmartTag);
// Méthode à exécuter lors du click sur le SmartTagprivatevoid myAction_Click(object sender, ActionEventArgs e)
{
MessageBox.Show("SmartTag NET Solutions Activé");
}
Ainsi, il vous suffit de définir un SmartTag, une action associée à ce SmartTag et la méthode à exécuter pour que le tout soit opérationnel rapidement et efficacement.
Sachez que les SmartTags supportent les espaces et la ponctuation: pour cela, il vous faut utiliser les expressions régulières pour parser la chaîne à analyser.
VI. Un peu plus loin...
Cette partie abordera quelques points plus poussés à propos des VSTO. Elle sera principalement composée d'exemples que je n'ai, malgré mes recherches intensives, pas pu trouvé sur Internet.
C'est pourquoi je vous en fait profiter.
VI-A. Excel
VI-A-1. Cache des données
Une autre fonctionnalité intéressante des VSTO concerne le Cache des données. En effet, il est possible de mettre, dans un Dataset, des données en cache pour pouvoir les réutiliser ultérieurement.
Ainsi, on peut imaginer un scénario dans lequel votre application se connecte, au démarrage, à une base de données. A la fermeture, elle enregistre les données dans la base et dans un Dataset de cache. Si, lors de la réouverture de l'application, la connexion au serveur SQL n'est pas possible (coupure réseau, etc...), vous pouvez tout à fait recharger les données depuis votre Dataset.
Ainsi, l'utilisateur peut continuer à travailler sans interruption.
Attention tout de même: dans le cas où vous utilisez la mise en cache, pensez à prévenir l'utilisateur qu'il est en mode déconnecté car il est possible que les données de la base aient été modifiées: l'utilisateur pourrait trouver surprenant de ne pas avoir les bonnes valeurs mais les anciennes (issues de son Dataset de cache).
Pour mettre en place ce système de cache, c'est très simple: vous devez utiliser un Dataset, le déclarer comme public et le faire précéder de l'attribut Microsoft.VisualStudio.Tools.Applications.Runtime.Cached.
Voici ce que cela donne par le code:
Implémentation du cache avec les VSTO
// Dataset de cache
[Microsoft.VisualStudio.Tools.Applications.Runtime.Cached]
public Dataset CachedDs;
A la fermeture de votre application, stockez vos données dans le Dataset CachedDs. Ensuite, dans le Form_Load, testez si CachedDs est différent de null et travaillez avec.
Utilisation d'un Dataset de Cache
privatevoid Form1_Load(object sender, System.EventArgs e)
{
// On teste si on arrive à se connecter à la base de donnéesif ( !Connected )
{
// Si le Dataset de cache n'est pas videif ( this.CachedDs != null )
{
// On fait notre traitement mais avec les données du Dataset,
// donc des données potentiellement différentes des données de la base !
Traitement();
// Et on prévient l'utilisateur qu'il est en mode déconnecté
}
else
{
//
}
}
else
{
// On est connecté directement à la base
Traitement();
}
}
Ainsi, l'application d'un système de cache, dans les applications VSTO se révèle très simple à mettre en place mais peut présenter un risque dans l'éventualité où les données présentes dans la base on pu être modifiées depuis le dernier lancement de l'application.
A utiliser avec précaution donc, ou alors si vous êtes sûr de ce que vous faîtes ;)
VI-B. Outlook
Même si je n'en ai pas beaucoup parlé dans cet article, sachez que les VSTO vous permettent de manipuler Word, Excel mais également Outlook.
Je vais donc vous montrer quelques unes des possibilités qui sont à votre disposition, dans le cas où vous auriez la nécessité de travailler avec Outlook et les VSTO.
VI-B-1. Création d'une barre de menu
Comme Word et Excel, vous avez la possibilité d'ajouter une barre d'outils directement dans Outlook. Pour cela, rien de plus simple: la méthode est quasi-identique que les autres fois.
Création d'une barre d'outils dans Outlook
// La bar de menuprivate Office.CommandBar cbar = null;
// Les items de la barreprivate Office.CommandBarButton cbShowConnectionForm = null;
// Les évènements qui se produisent lors du clic sur les items de la barreprivate Office._CommandBarButtonEvents_ClickEventHandler cbShowConnectionFormClickEvent;
privatevoid ThisApplication_Startup(object sender, System.EventArgs e)
{
// Chargement de la barre de menu
LoadCommandBar();
}
privatevoid LoadCommandBar()
{
// On peut omettre les paramètres optionnelsobject oMissing = System.Reflection.Missing.Value;
// Texte de la barre de menu + position
cbar = this.ActiveExplorer().CommandBars.Add("Menu .NET Solutions - Outlook", oMissing, oMissing, (object)true);
// Ajout d'un nouveau bouton
cbShowConnectionForm = (Office.CommandBarButton)(cbar.Controls.Add((object)1, oMissing, oMissing, oMissing, oMissing));
// Définition du style de bouton
cbShowConnectionForm.Style = Office.MsoButtonStyle.msoButtonCaption;
// Définition de sa propriété Caption (Texte à afficher)
cbShowConnectionForm.Caption = String.Format("Activer l'Addin NET Solutions pour Outlook");
// Méthode à appeller lors du clic sur l'item
cbShowConnectionFormClickEvent = new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(
cbShowConnectionFormClickEvent_Click);
cbShowConnectionForm.Click += cbShowConnectionFormClickEvent;
// On affiche la barre de menu
cbar.Visible = true;
}
La différence avec les autres créations de barre de menu se situe sur la ligne:
Ici, on utilise ActiveExplorer() pour récupérer l'objet Explorer courant. Un Explorer est l'objet représentant la fenêtre dans laquelle le contenu d'un répertoire est affiché.
Ainsi, la ligne de code ci-dessus sert à ajouter une barre de menu qui sera, par défaut, placée au milieu de la fenêtre de visualisation des emails. Pour que cela soit plus clair, voici une capture d'écran:
Comme on peut le voir, ActiveExplorer() nous a permis de récupérer un handle sur la fenêtre droite d'Outlook et d'y insérer notre menu.
Maintenant que nous avons vu cette partie, voyons comment il nous est possible de créer, directement par programmation, un nouveau mail, d'y ajouter un pièce jointe, etc....
VI-B-2. Création d'un nouveau mail
Pour créer un nouveau mail, rien de plus simple: il vous suffit d'instancier un nouvel objet de type MailItem.
Pour cela, appeller la méthode CreateItem de l'objet Application (qui représente votre application Outlook). Cette méthode prend en paramètre une des valeurs de l'énumération Microsoft.Office.Interop.Outlook.OlItemType, qui indique le type d'item à créer:
olAppointmentItem: Pour un item de type Rendez-vous, dans le calendrier
olContactItem: Pour un item de type Contact
olDistributionListItem: Pour une liste de distribution
olJournalItem: Pour une nouvelle entrée dans le journal Outlook
olMailItem: Pour un nouveau mail
olNoteItem: Pour une nouvelle note
olTaskItem: Pour une nouvelle tâche
Ainsi, pour créer un nouveau mail, utilisez ce bout de code:
Instanciation et initialisation d'un nouveau item pour le mail
// On instancie un nouveau mail// C'est un objet de type MailItem
Outlook.MailItem mail = (Outlook.MailItem)
Globals.ThisApplication.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
A partir de maintenant, il ne vous reste plus qu'à appeller les méthodes et à définir les propriétés de votre objet. Voici un exemple:
Préparation et envoi d'un mail
// On renseigne l'adresse email du client dans le mail
mail.Recipients.Add(this.textBox2.Text);
// On formatte le sujet et le corp du message.
mail.Subject = String.Format("Envoi de facture");
mail.Body = String.Format("A l'attention de {0}:{1}{1}Veillez trouver ci-joint la copie de votre facture.{1}{1}",
textBox1.Text, Environment.NewLine);
// On attache la pièce jointe.// Paramètres de la méthode Add: // - Fichier à attacher// - Méthode d'attachement au message// - Position de la pièce jointe// - Nom affiché de la pièce jointe
mail.Attachments.Add(textBox3.Text, Outlook.OlAttachmentType.olByValue, 1, String.Concat("Facture ", this.textBox2.Text));
// On met le mail au format HTML
mail.BodyFormat = Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatHTML;
// On affiche la fenêtre du mail
mail.Display(false);
// Envoi du mail
mail.Send();
Ainsi, on s'aperçoit qu'envoyer un mail est un chose aisée qui peut se faire très très rapidement. Voyons alors comment récupérer la liste de vos contacts.
VI-B-3. Récupération des contacts Outlook
Les VSTO vous permettent aussi bien de créer des contacts Outlook que de les récupérer, avec leurs informations (nom, prénom, etc.). Voyons cela avec un simple bout de code:
Récupération des contacts Outlook
// On récupère le répertoire des contacts
Outlook.MAPIFolder contactFolder = null;
contactFolder = Globals.ThisApplication.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
// On applique un filtre pour ne rechercher que les objets de type Contat, et pas les listes de distribution/diffusionstring strFind = "[MessageClass] = 'IPM.Contact'";
Outlook.Items items = contactFolder.Items.Restrict(strFind);
// Pour chaque contact du répertoirefor(int i = 1; i < items.Count; i++)
{
// On récupère le contact en cours
Outlook.ContactItem ContactItem = (Outlook.ContactItem)items[i];
// Affichage des informations (Nom, prénom, Email, etc...) dans la Treeview.this.treeView1.Nodes[0].Nodes.Add(ContactItem.LastName + " " + ContactItem.FirstName);
// Affichage de l'email si elle existeif (ContactItem.Email1Address != null && ContactItem.Email1Address.Length > 0)
{
this.treeView1.Nodes[0].Nodes[i - 1].Nodes.Add("Email : " + ContactItem.Email1Address);
}
// Affichage du téléphone Domicile s'il existeif (ContactItem.HomeTelephoneNumber != null && ContactItem.HomeTelephoneNumber.Length > 0)
{
this.treeView1.Nodes[0].Nodes[i - 1].Nodes.Add("Téléphone Domicile: " + ContactItem.HomeTelephoneNumber);
}
// Affichage du téléphone professionnel s'il existeif (ContactItem.BusinessTelephoneNumber != null && ContactItem.BusinessTelephoneNumber.Length > 0)
{
this.treeView1.Nodes[0].Nodes[i - 1].Nodes.Add("Téléphone Bureau: " + ContactItem.BusinessTelephoneNumber);
}
// Affichage du téléphone Mobile s'il existeif (ContactItem.MobileTelephoneNumber != null && ContactItem.MobileTelephoneNumber.Length > 0)
{
this.treeView1.Nodes[0].Nodes[i - 1].Nodes.Add("Téléphone Portable: " + ContactItem.MobileTelephoneNumber);
}
// On déplie la node racinethis.treeView1.Nodes[0].Expand();
}
Avec ce bout de code, nous parcourons le répertoire Contact d'Outlook puis, pour chaque entrée contenue dans ce répertoire, nous affichons, dans une listview, certaines de ces informations.
La liste complète des propriétés de l'objet ContactItem peut-être retrouvée ici.
Voici un aperçu, en image, du résultat produit par ce code:
Comme vous pouvez le voir, recréez un simple explorateur de contacts Outlook s'avère donc très simple à mettre en oeuvre.
VI-B-4. Création d'un rendez-vous dans le Calendrier Outlook
Vous avez également la possibilité de créer, via votre application VSTO, un rendez-vous dans le calendrier Outlook de l'utilisateur exécutant votre application.
Pour cela, il vous suffit de déclarer et d'instancier un nouvel objet de type Outlook.AppointmentItem, de définir quelques unes de ses propriétés (telles que le sujet, le corp, l'heure, etc.) puis d'enregistrer le rendez-vous au moyen de la méthode Save de votre objet.
Voyons tout cela par le code:
Création d'un rendez-vous dans le calendrier Outlook
// Méthode de création des RDV dans le calendrierprivatevoid CreateAppointment()
{
// On instancie notre nouvel objet de type RDV // On créé un nouvel item RDV
Outlook.AppointmentItem rdv = (Outlook.AppointmentItem)
Globals.ThisApplication.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olAppointmentItem);
// On définit la date de début
rdv.Start = monthCalendar1.SelectionStart;
// On définit alors la durée du RDV est: Toute la journée
rdv.AllDayEvent = true;
// On indique un sujet
rdv.Subject = String.Format(String.Concat("Rendez-vous avec ", textBox1.Text));
// Puis le corp du message du RDV
rdv.Body = String.Format("Rendez-vous prévu toute la journée dans les locaux de {0}", textBox1.Text);
// On change le statut
rdv.BusyStatus = Microsoft.Office.Interop.Outlook.OlBusyStatus.olOutOfOffice;
// On active la notification de rappel
rdv.ReminderSet = true;
// Avec un rappel commencant 5h00 avant le début du RDV
rdv.ReminderMinutesBeforeStart = 300;
// On sauvegarde le RDV dans le calendrier Outlool
rdv.Save();
}
Cet exemple étant suffisant parlant de lui-même, je ne prend pas la peine de vous l'expliquer en détails et je préfère vous montrer le résultat ;)
VI-B-5. Création d'une tâche
Pour créer une tâche, ce n'est pas plus compliqué que pour créer un rendez-vous :)
Création d'une tâche
privatevoid CreateTask()
{
// Instanciation de notre objet tache
Outlook.TaskItem task = (Outlook.TaskItem)
Globals.ThisApplication.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olTaskItem);
// Date de début de la tache
task.StartDate = monthCalendar1.SelectionStart;
// Le statut de la tache: Fini, En cours, Non commenté, etc...
task.Status = Microsoft.Office.Interop.Outlook.OlTaskStatus.olTaskNotStarted;
// Le sujet de la tache
task.Subject = String.Format(String.Concat("Rendez-vous avec ", textBox1.Text));
// Le corp du message de la tache
task.Body = String.Format(String.Concat("Rendez-vous avec ", textBox1.Text));
// On active la notification de rappel
task.ReminderSet = true;
// Avec un rappel commencant 24h avant le début de la tache
task.ReminderTime = monthCalendar1.SelectionStart.AddHours(-24);
// On sauvegarde la tache
task.Save();
}
Si vous observez ce code, vous pourrez juger par vous-même qu'il n'est guère différent du code de création d'un rendez-vous, hormis l'objet de création de tâche: Outlook.TaskItem.
Sur cette dernière capture d'écran, on voit distinctement qu'il y a 2 rappels. Pensant au départ qu'il s'agissait d'un bug d'Outlook (on se sait jamais...), je me suis vite rendu compte qu'il s'agissait:
du rappel de ma tâche
du rappel de mon rendez-vous
D'ailleurs, si vous observez bien la fenêtre de rappel de votre Outlook (ou de l'image située plus haut), vous pouvez voir, à gauche du sujet du rappel, l'icône de "l'application" (calendrier ou tâches) qui a provoqué le rappel.
VI-C. PowerPoint
Vous avez la possibilité de développer pour PowerPoint (et même Access ou encore InfoPath), en faisant de l'automation COM (bien sûr, vous pouvez toujours utiliser VBA).
Cette technique peut être utilisée par n'importe quel langage de développement pouvant manipuler des objets COM (donc, cela fonctionne très bien à partir de Visual Studio .NET).
Imaginez par exemple le scénario suivant: votre employeur vous demande de réaliser une application qui, après avoir extrait des informations d'une base de données, les affiche dans une présentation PowerPoint, en faisant défiler les slides une à une. C'est dans un cas comme celui-ci que les VSTO 2 trouvent toute leur utilité.
Avant toute chose, vous devez:
Ajouter la référence COM de PowerPoint à votre projet: dans l'explorateur de solutions, faîtes un clic droit sur References et choisissez "Add Reference". Sélectionnez l'onglet COM et ajouter la référence suivante: Microsoft PowerPoint 11.0 Object Library
Déclarez votre objet de type Microsoft.Office.Interop.PowerPoint.Application: c'est grâce à lui que vous pourrez manipuler PowerPoint
Déclaration et instanciation de l'objet Application
// Déclaration de l'objet PowerPointprivate PowerPoint.Application powerPoint;
// Instanciation de l'objet
powerPoint = new Microsoft.Office.Interop.PowerPoint.Application();
Et là, vous n'avez plus qu'à manipuler votre document PowerPoint. Voyons cela avec des exemples...
VI-C-1. Changement du fond
Pour changer l'image de fond d'une présentation PowerPoint, voici la marche à suivre:
Changement du fond de la présentation
// Instanciation de l'objet
powerPoint = new Microsoft.Office.Interop.PowerPoint.Application();
// On récupère la liste des présentations de l'application PowerPoint// On créé un nouveau document donc normalement, cela doit être vide
PowerPoint.Presentations ppts = powerPoint.Presentations;
// On ajoute une nouvelle présentation à cette collection
PowerPoint.Presentation ppt = ppts.Add(Microsoft.Office.Core.MsoTriState.msoTrue);
// Pour modifier le fond de tous les slides
ppt.SlideMaster.Background.Fill.UserTextured(Application.StartupPath +
@"\" + @"Resources\Arrière_plan_PPT_TechEd_2005.jpg");
Sachez que vous avez la possibilité de ne changer le fond que d'un seul slide. Pour cela, récupérer la collection de slides de votre présentation, puis modifiez la propriété BackGround du slide dont vous voulez changer le fond.
Changement du fond d'un seul slide
// On récupère la collection de slides de cette présentation
PowerPoint.Slides slides = ppt.Slides;
slides[1].Background.Fill.UserTextured(Application.StartupPath + @"\"
+ @"Resources\Arrière_plan_PPT_TechEd_2005.jpg");
Voici le résultat que vous obtenez (en fonction de l'image de fond que vous avez choisit):
VI-C-2. Ajouter un slide
Pour ajouter un slide, rien de plus simple: récupérer la collection de slides de votre présentation et ajoutez en un en appellant la méthode Add, qui prend en paramètre:
la position du slide dans la présentation
le type de slide à ajouter
Le type de slide doit être choisit dans l'énumération Microsoft.Office.Interop.PowerPoint.PpSlideLayout, dont voici certaines valeurs que vous utiliserez (à mon avis) le plus souvent:
ppLayoutBlank: Insère une diapositive vide
ppLayoutTitle: Insère une diapositive de présentation
ppLayoutText: Diapositive permettant de saisir un titre et du texte
Bien sûr, il en existe beaucoup d'autres, et je vous laisse consulter la MSDN pour avoir de plus ample détails.
Voyons cela par le code:
Ajout d'un slide
// On récupère la collection de slides de cette présentation
PowerPoint.Slides slides = ppt.Slides;
// Et on ajoute un nouveau slide à cette collection// Prend en paramètre la position à laquelle ajouter le slide// Et le type de modèle de slides que l'on veut: Dans notre cas, on veut un slide de présentation.
PowerPoint.Slide slideIntro = slides.Add(1, Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutTitle);
Ainsi, vous avez réussit à ajouter, avec succès, un slide à votre présentation. Si nous avions utilisé un slide de type ppLayoutText, celui-ci aurait comporté deux zones de texte: une (en haut) pour écrire un titre, et une autre (dans le centre de la page), pour saisir du texte.
La prochaine partie vous apprendra à accéder à ces éléments, et à les modifier pour vos besoins.
VI-C-3. Accéder aux éléments d'un slide
Chaque slide de votre présentation possède une collection de Shapes, qui représente l'ensemble des éléments de votre diapositive.
Ainsi, pour pouvoir manipuler la première zone de texte, il nous suffit d'y accéder par son index dans la collection Shapes:
Accéder aux éléments d'un slide
// On remplit le texte de la première textbox du template PowerPoint
slideIntro.Shapes[1].TextFrame.TextRange.Text = String.Format("Automation PowerPoint");
// Celui de la deuxième textbox
slideIntro.Shapes[2].TextFrame.TextRange.Text = String.Format("Avec les VSTO 2");
// Et on change la taille de la police de la première TextBox
slideIntro.Shapes[1].TextFrame.TextRange.Font.Size = 50;
Voici le résultat en image:
Si vous voulez modifier l'indentation du texte, à l'intérieur de votre slide, cela vous est tout à fait possible: il vous suffit de modifier la propriété IndentLevel.
Mise en forme dans un slide
// On ajoute un deuxième slide// Modèle du slide: Titre + Texte
PowerPoint.Slide slideText = slides.Add(2, Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutText);
// On insère le texte dans la TextArea du titre
slideText.Shapes[1].TextFrame.TextRange.Text = String.Format("Titre de la présentation");
// On change la police
slideText.Shapes[1].TextFrame.TextRange.Font.Size = 50;
// Et la couleur de la police
slideText.Shapes[1].TextFrame.TextRange.Font.Color.RGB = Color.White.ToArgb();
// On insère du texte dans la TextArea du bas// On utilise plusieurs niveau d'indentation
slideText.Shapes[2].TextFrame.TextRange.Text = String.Format("Texte de premier niveau");
slideText.Shapes[2].TextFrame.TextRange.Paragraphs(1, 1).IndentLevel = 1;
slideText.Shapes[2].TextFrame.TextRange.InsertAfter(String.Format("{0}Texte de second niveau", Environment.NewLine));
slideText.Shapes[2].TextFrame.TextRange.Paragraphs(2, 1).IndentLevel = 2;
slideText.Shapes[2].TextFrame.TextRange.InsertAfter(String.Format("{0}Texte de troisième niveau", Environment.NewLine));
slideText.Shapes[2].TextFrame.TextRange.Paragraphs(3, 1).IndentLevel = 3;
slideText.Shapes[2].TextFrame.TextRange.InsertAfter(String.Format("{0}Texte de quatrième niveau", Environment.NewLine));
slideText.Shapes[2].TextFrame.TextRange.Paragraphs(4, 1).IndentLevel = 4;
slideText.Shapes[2].TextFrame.TextRange.InsertAfter(String.Format("{0}Texte de cinquième niveau", Environment.NewLine));
slideText.Shapes[2].TextFrame.TextRange.Paragraphs(5, 1).IndentLevel = 5;
Ce qui donne ceci comme rendu:
Nous savons donc ajouter un slide, modifier le contenu déjà existant d'un slide. Voyons maintenant comment ajouter des éléments à un slide.
VI-C-4. Ajouter un élément à un slide
Pour ajouter un élément (TextBox, image, etc...) à un slide, la procédure ne s'avère pas très compliquée: il vous faut récupérer l'ensemble des éléments déjà présents sur le slide (au moyen de la collection Shapes).
Ensuite, il ne vous reste plus qu'à jouter un élément (Shape) à cette collection.
Voyons ce que cela donne:
Ajout d'un élément au slide
// On ajoute un troisième slide// Modèle du slide: Slide vide
PowerPoint.Slide slide = slides.Add(3, Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutBlank);
// On récupère la collection d'éléments (TextBox, Image, etc...) qui sont sur ce 3ème slide
PowerPoint.Shapes shapes = slide.Shapes;
// On ajoute un élément (TextBox) à cette collection et on y insère du texte// Ici, c'est le texte saisi par l'utilisateur// On indique l'orientation du texte et les coordonnées où mettre le texte.
PowerPoint.Shape shape = shapes.AddTextbox(Office.MsoTextOrientation.msoTextOrientationHorizontal, 0, 0, 500, 50);
shape.TextFrame.TextRange.InsertAfter(this.tbText.Text);
Le code précédent est donc utilisé pour:
Ajouter un nouveau slide à notre présentation
Récupérer la collection d'éléments (Shapes) présents sur le slide
Ajouter un élément (Shape) à cette collection: on spécifie pour cela l'orientation du texte, et les coordonnées où placer notre élement
Pour finir, on insère le texte saisi par l'utilisateur dans notre Textbox
Pour vous rendre compte du résultat, voyez l'image suivante:
Bien sur, vous pouvez ajouter autre chose qu'une simple TextBox, dans votre slide:
VI-C-5. Ajouter une animation à votre slide
Si vous voulez ajouter une animation à votre slide, vous devez utiliser un objet de type PowerPoint.Effect. Commencez par récupérer l'élément qui devra être animé, puis récupérer la présentation active de votre application et appelez la méthode AddEffect, vous permettant d'ajouter un effet/une animation.
Ajout d'une animation
// Ajout d'un effet sur un élément (la TextBox) de notre slide
PowerPoint.Shape shapeEffect = powerPoint.ActivePresentation.Slides[3].Shapes[1];
PowerPoint.Effect objEffect = powerPoint.ActivePresentation.Slides[3].TimeLine.MainSequence.AddEffect(shapeEffect,
Microsoft.Office.Interop.PowerPoint.MsoAnimEffect.msoAnimEffectPathStairsDown,
Microsoft.Office.Interop.PowerPoint.MsoAnimateByLevel.msoAnimateLevelNone,
Microsoft.Office.Interop.PowerPoint.MsoAnimTriggerType.msoAnimTriggerOnPageClick, 1);
La méthode AddEffect prend en paramètre:
L'élément qui devra être animé
Le type d'animation qui devra être jouée
Pour les graphiques, les diagrammes ou le texte, on indique ensuite le niveau auquel l'effet de l'animation sera appliqué. La valeur par défaut est msoAnimationLevelNone.
L'action qui déclenchera l'animation. Par défaut, il s'agit de msoAnimTriggerOnPageClick.
La position à laquelle sera inséré l'animation dans la collection d'animations. La valeur par défaut est -1 (c'est à dire ajouté à la fin)
Si vous lancez votre présentation (appuyez sur la touche F5 dans PowerPoint), et que vous faîtes afficher le slide sur lequel vous avez ajouter une animation, vous devriez la voir se jouer.
Un autre moyen de voir que ce slide possède une animation: dans PowerPoint, cliquer sur "Affichage" puis sélectionnez "Normal" ou "Normal (Restauration des volets)". Dans le panneau qui s'ouvre devant vous, cliquez sur l'onglet "Diapositives" et repérez le slide sur lequel vous avez inséré une animation: vous devriez voir une petite étoile (signe d'une animation) sur la gauche de la miniature.
VI-C-6. Ajouter un commentaire
Si vous désirez ajouter un commentaire à votre slide (utile pour donner des indications au lecteur), sachez que vous pouvez le faire simplement.
Pour cela, récupérer la collection de Comments et ajouter un commentaire à cette collection.
Ce qui donne, par exemple:
Ajout d'un commentaire
// Ajout d'un commentaire au 3ème slide la présentation// On récupère la liste de tous les commentaires présents sur le slide
PowerPoint.Comments comments = slide.Comments;
// On ajoute un commentaire à cette liste
PowerPoint.Comment comment = comments.Add(250, 100, "Thomas LEBRUN", "TL", "Un petit bonjour de votre application VSTO :)");
La méthode Add prend en paramètres:
les coordonnées où placer le commentaire
le nom de l'auteur
les initiales de l'auteur
le texte du commentaire
Pour voir le résultat, c'est ici:
VI-C-7. Chargement d'une présentation
Si vous voulez ouvrir directement une présentation, sachez que vous pouvez tout à faire le faire en appellant la méthode Open de la collection Presentations.
Chargement automatique d'une présentation
// Instanciation de l'objet
powerPoint = new Microsoft.Office.Interop.PowerPoint.Application();
// On fait apparaitre l'application à l'utilisateur
powerPoint.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
powerPoint.Presentations.Open(this.tbLoad.Text, Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoTrue);
De plus, si vous voulez que la diaporama se lance automatiquement après le chargement de votre présentation, voici la ligne de code à utiliser:
Cette ligne vous permet de récupérer la présentation active, puis de lancer la présentation au moyen de la méthode Run.
Sachez que vous pouvez également modifier le temps d'attente entre chaque slides, etc..
VI-C-8. Libération des ressources
Dans le cas où vous faîtes de l'automation Office avec des objets COM (c'est-à-dire des objets non managés), vous devez pensez à libérer les ressources que vous avez utilisé, et cela dès que vous n'en avez plus besoin.
Voici comment appliquer cette règle:
Libération des ressources non managées
if (powerPoint != null)
{
// Quitte l'application PowerPoint
powerPoint.Quit();
powerPoint = null;
}
//// Double appel à Collect et WaitForPendingFinalizers// En effet, le référence mémoire vers Excel peut-être conservée après le 1er appel// On demande donc un deuxième passage du Garbage Collector//
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Par ce bout de code, vous vous assurez de bien quitter l'application PowerPoint et de mettre sa référence à null. Ainsi, lorsqu'à la ligne suivante, on appellera le Garbage Collector, celui-ci saura que notre objet n'est plus utilisé et qu'il peut donc le supprimer de la mémoire.
Comme je vous l'ai dit, ce processus est important si vous voulez éviter de vous retrouver avec des problèmes de mémoire excessive, etc....
Si vous avez bien suivit jusqu'ici, vous avez dû vous rendre compte que, mis à part Word, Excel et Outlook, les références à ajouter pour manipuler les autres applications Microsoft Office se trouvent toutes dans l'onglet COM de la partie "Ajout de référence".
La raison en est simple: Pour le moment, seuls ces trois produits permettent l'exécution d'applications Microsoft Office en environnement managé. Avec la précédente version des VSTO, tout devait être fait par des composants COM (Word, Excel, etc....).
Cette nouvelle version apporte donc beaucoup plus de facilité de développement et d'interopérabilité. Cependant, il reste toujours une question en suspends: à quand une version d'Office entièrement managée (c'est-à-dire écrit avec un langage .NET) qu permettra de faire des applications Microsoft Office entièrement managée elles aussi ? ;)
VII. Et le futur ?
Selon Eric CARTER, membre de l'équipe de développement des Visual Studio Tools For Office, le développement des VSTO 3 est prévu et ciblera la plateforme Microsoft Office 12 (Source).
Leur développement a même déjà commencé: une préview des VSTO 3 a été présentée lors de la session OFF417 de la PDC (Voir ici pour plus d'informations).
On peut supposer (mais ce n'est que mon avis, rien d'officiel) que cette nouvelle version des VSTO sera disponible en même temps que la future version de Visual Studio (Nom de code: Orcas).
VIII. Conclusions
Nous avons donc vu que les VSTO nous permettent:
des développement simples et rapides d'applications Microsoft Office
l'utilisation de la puissance de .NET au service d'Office
A vous maintenant d'apprendre à utiliser ces outils pour pouvoir vous rendre compte, par vous même, des multiples possibilités des VSTO ;)