jeudi 31 mai 2012

Dessiner des diagrammes à partir d'une barre d'outils personnalisée

Voici un tutoriel qui  vous permettra de réaliser un outil de dessin de diagrammes à partir d'une barre d'outils personnalisée.Il s'agit d'un développement simple et rapide, facilement adaptable à vos besoins. et qui est du plus bel effet !

Plaçons le décor... 

La zone de travail
Commencez par désactiver la grille Excel dans les options d'affichage.
Délimitez la zone de dessin au centre de l'écran en sélectionnant les cellules correspondantes et en traçant les bordures dans les propriétés de format de cellules.
Maintenez les cellules sélectionnées, et nommez cette zone "Zone". Le nommage se fait en modifiant l'intitulé situé à gauche de la barre de formule. Vous constaterez qu'à chaque fois que vous sélectionnerez "Zone" dans cette liste déroulante, la zone en question sera sélectionnée automatiquement.
Vous pouvez placer un titre au-dessus de la zone de travail soit en fusionnant les cellules soit en insérant un contrôle ActiveX de type Label personnalisé.

La liste des composants
Sous MS Office 2003, affichez la barre d'outils "Visual Basic". Sous MS Office 2007/2010, affichez l'onglet "Développeur". Passez Excel en mode Edition et insérez à partir de la boîte à outils :
  • un contrôle ActiveX de type ListBox à droite de la zone de travail que vous venez de délimiter. Cette première ListBox s'appelle par défaut ListBox1.
  • deux contrôlesActiveX de type CommandButton sous la ListBox. Ces deux boutons s'appelleront par défaut CommandButton1 et CommandButton2.
Pour que la ListBox aie la même bordure fine que la zone de travail, vous pouvez :
  • soit modifier sa propriété SpecialEffect en lui attribuant la valeur 3 - fmSpecialEffectEtched. La bordure sera alors grise par défaut.
  • soit modifier sa propriété SpecialEffect en lui attribuant la valeur 0 - fmSpecialEffectFlat, et modifier sa propriété BorderStyle en lui attribuant la valeur 1 - fmBorderStyleSingle en veillant à choisir la couleur qui vous convient dans l'attribut BorderColor.
Modifiez l'intitulé des boutons: 
  • CommandButton1 devient "Afficher" : ce bouton servira à afficher un composant de la liste sur le diagramme. Dans cet exemple, chaque composant ne peut être instancié / affiché qu'une seule fois.
  • CommandButton2devient "Supprimer" : ce bouton servira à supprimer un composant de la liste et du diagramme.
La barre d'outils
Délimitez la zone où vous souhaitez placer votre barre d'outils en sélectionnant les cellules correspondantes et en traçant les bordures dans les propriétés de format de cellules. Si vous le souhaitez, vous pouvez colorer cette zone en lui affectant un fond uniforme ou en dégradé comme sur l'exemple ci-dessous.

Placez dans cette zone trois contrôles ActiveX de type Label de tailles identiques : ils s'appelleront par défaut Label1, Label2 et Label3.
Modifiez le paramètre Picture de ces trois labels en y appliquant des images de votre choix au format BMP.

  

Passez à l'onglet "Feuil2" et insérer les mêmes images que vous venez d'utiliser. Réglez leur taille aux dimensions auxquelles vous souhaitez les faire apparaître sur le diagramme.
Sélectionnez chaque image séparément et modifier son nom dans la zone de nommage située à gauche de la barre de formule, comme nous l'avions fait pour la zone de dessin en "Feuil1". Désormais, vous pourrez manipuler vos images en les invoquant par les noms que vous leur aurez donné.

Le formulaire de saisie
A partir de la barre d'outils "VisualBasic" (MS 2003) ou de l'onglet "Développeur" (MS 2007/2010), lancez l'éditeur de code VBA. Insérez dans le projet en cours une nouvelle feuille de type UserForm : votre nouveau formulaire s'appellera par défaut UserForm1.

Placez les éléments de votre formulaire :
  • Affichez la fenetre de propriétés.
  • Sélectionnez le formulaire et modifiez son titre en saisissant le titre souhaité (dans cet exemple "Composant")  dans la propriété Caption.
  • Créez un Label  qui servira à indiquer à l'utilisateur l'action à réaliser (dans cet exemple on lui demande de renseigner le nom du composant de diagramme).
  • Créez une TextBox qui servira à saisir du texte (dans cet exemple il s'agit du nom du composant)
  • Créer deux CommandButton qui serviront à valider ou annuler la saisie. Par défault ils s'appelleront CommandButton1 et CommandButton2. Modifiez l'intitulé des boutons en renseignant leur propriété Caption : CommandButton1 prendra la valeur "OK" et CommandeButton2 prendra la valeur "Annuler".

Les détails
Revenons à l'onglet "Feuil1". Vous pouvez placer de la décoration et des titres au-dessus de chacun des éléments que vous avez créé, soit directement dans des cellules fusionnées, soit en insérant un contrôle ActiveX de type Label personnalisé.

 ... puis passons au codage

Pour atteindre le code d'un contrôle ActiveX, sachez qu'il vous suffit de double cliquer sur celui-ci lorsque vous êtes en mode édition. Allons-y !

La barre d'outils
Les éléments de la barre d'outils seront considérés comme des boutons cliquables, bien qu'il s'agissent de contrôles Label. Voir le tutorial Customisez vos boutons.
  • Label1 servira à créer un composant représentant un logo blanc.
  • Label2 servira à créer un composant représentant un logo vert.
  • Label3 servira à créer un connecteur dynamique (parmi les formes automatiques de MS Office) pour relier les composants entre eux.
Pour chacun des trois éléments de la barre d'outils, nous allons donc coder trois procédures :
  • Celle qui se déroule lorsqu'on appuie sur le label avec le bouton gauche de la souris : Mouse_Down().
  • Celle qui se déroule lorsqu'on relève le bouton gauche de la souris au-dessus du label : Mouse_Up().
  • Celle qui se déroule lorsqu'on a fini de cliquer sur le label : Click().
Dans l'éditeur de code VBA, copiez et collez  les procédures ci-dessous dans la zone de codage de l'onglet "Feuil1". Vous constaterez que ce code fait appel au formulaire UserForm1 que nous allons coder par la suite.

Private Sub Label1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label1.SpecialEffect = fmSpecialEffectSunken
End Sub

Private Sub Label1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label1.SpecialEffect = fmSpecialEffectEtched
End Sub

Private Sub Label1_Click()

    ' Placer le composant dans la zone de diagramme nommée "Zone"
    Sheets("Feuil2").Shapes("LogoBlanc").Copy
    ActiveSheet.Range("Zone").Select
    ActiveSheet.Paste
          
    ' Nommer le composant via formulaire
    UserForm1.Show

End Sub

Private Sub Label2_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label2.SpecialEffect = fmSpecialEffectSunken
End Sub

Private Sub Label2_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label2.SpecialEffect = fmSpecialEffectEtched
End Sub

Private Sub Label2_Click()

    ' Placer le composant dans la zone de diagramme nommée "Zone"
    Sheets("Feuil2").Shapes("LogoVert").Copy
    ActiveSheet.Range("Zone").Select
    ActiveSheet.Paste
   
    ' Nommer le composant via formulaire
    UserForm1.Show

End Sub

Private Sub Label3_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label3.SpecialEffect = fmSpecialEffectSunken
End Sub

Private Sub Label3_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label3.SpecialEffect = fmSpecialEffectEtched
End Sub

Private Sub Label3_Click()
    ActiveSheet.Shapes.AddConnector(msoConnectorCurve, 249#, 296.25, 63#, 84.75 _
        ).Select
    Selection.ShapeRange.Line.ForeColor.SchemeColor = 23
    Selection.ShapeRange.Line.Visible = msoTrue
    Selection.ShapeRange.Line.BeginArrowheadStyle = msoArrowheadOval
    Selection.ShapeRange.Line.EndArrowheadStyle = msoArrowheadOval
    Selection.ShapeRange.Line.BeginArrowheadWidth = msoArrowheadWidthMedium
    Selection.ShapeRange.Line.BeginArrowheadLength = msoArrowheadLengthMedium
    Selection.ShapeRange.Line.EndArrowheadWidth = msoArrowheadWidthMedium
    Selection.ShapeRange.Line.EndArrowheadLength = msoArrowheadLengthMedium
    Selection.ShapeRange.Line.Visible = msoTrue
End Sub


Le formulaire de saisie
Affichez la fenêtre d'édition du formulaire, puis double cliquez sur le bouton "OK" (CommandButton1) pour accéder à son code. Copiez et collez le code suivant en lieu et place des deux lignes qui sont créées automatiquement : "Sub CommandButton1()" et "End Sub".

Private Sub CommandButton1_Click()
   
    ' Nommer le composant sélectionné sur le diagramme (il vient d'être collé, il est donc toujours sélectionné)
    Selection.Name = TextBox1
   
    ' Ajouter le composant à la liste
    ActiveSheet.ListBox1.AddItem Selection.Name
   
    ' Fermer le formulaire
    Unload Me
   
End Sub

Revenez à la fenêtre d'édition du formulaire, puis double cliquez sur le bouton "Annuler" (CommandButton2) pour accéder à son code. Copiez et collez le code suivant en lieu et place des deux lignes qui sont créées automatiquement : "Sub CommandButton2()" et "End Sub".

Private Sub CommandButton2_Click()
    ' Annuler la création de composant : supprime le logo du diagramme et ferme le formulaire
    Selection.Delete
    Unload Me
End Sub

Restez dans la fenêtre de code du formulaire et ajoutez ces quelques lignes qui permettront d'interdire la fermeture du formulaire par clic sur la croix en haut à droite. Le but de cette manoeuvre est de forcer l'utilisateur à annuler son action en cliquant sur le bouton "Annuler" ci-dessus.

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    ' Empêcher l'utilisateur de fermer le formulaire par la croix
    If CloseMode = 0 Then Cancel = True
End Sub

La liste des composants
Revenez à l'onglet "Feuil1" de votre classeur.
Nous ne coderons rien concernant la liste des composants ListBox1 car celle-ci est pilotée par le formulaire comme vous avez pu le constater dans les lignes de coques ci-dessus.
En revanche, nous allons coder les procédures des boutons "Ajouter" (CommandButton1) et "Supprimer" (CommandButton2).

 En restant en mode Edition, double cliquez-sur le bouton "Ajouter" (CommandButton1). Copiez et collez le code suivant en lieu et place des deux lignes qui sont créées automatiquement : "Sub CommandButton2()" et "End Sub".

Private Sub CommandButton1_Click()
    Dim s As Shape
   
    For Each s In Sheets("Feuil1").Shapes
        ' Vérification de la présence du composant parmi tous les éléments du diagramme
        If s.Type = msoPicture And s.Name = ActiveSheet.ListBox1.Value Then
            s.Select
            ' Le composant est déjà sur le diagramme, on le sélectionne et on quitte la procédure
            Exit Sub
        End If
    Next
   
    ' Le composant n'est pas sur le diagramme : afficher le composant
        ' Placer le composant dans la zone de diagramme nommée "Zone"
        Sheets("Feuil2").Shapes("LogoBlanc").Copy
        ActiveSheet.Range("Zone").Select
        ActiveSheet.Paste
        ' Nommer le composant
        Selection.Name = ActiveSheet.ListBox1.Value
       
End Sub

Restez dans la fenêtre de code VBA, et copiez-collez directement le code suivant après la procédure que vous venez d'insérer. Il s'agit de la procédure du bouton "Supprimer" (CommandButton2).

Private Sub CommandButton2_Click()
    Dim s As Shape
   
    For Each s In Sheets("Feuil1").Shapes
        ' Vérification de la présence du composant parmi tous les éléments du diagramme
        If s.Type = msoPicture And s.Name = ActiveSheet.ListBox1.Value Then
            s.Select
            ' Supprimer le composant du diagramme
            s.Delete
            Exit For
        End If
    Next
    ' Supprimer le nom de la liste
    ActiveSheet.ListBox1.RemoveItem (ActiveSheet.ListBox1.ListIndex)
   
End Sub

Finalisez votre travail
Terminez en désactivant l'affichage des en-têtes de lignes et de colonnes de l'onglet "Feuil1", ainsi que les onglets du classeur, afin d'épurer votre interface et d'éviter que l'on puisse modifier votre mise en page ou vos images.

A vous à présent d'adapter ce tutorial à vos besoins : modifiez l'apparence de la barre d'outils, créez de nouveaux composants, ajoutez des paramètres supplémentaires aux composants, créez une base de données associée à la liste de composants... 

Téléchargez le fichier

mercredi 30 mai 2012

Customisez vos boutons

N'est-il pas désolant de voir MS Office évoluer esthétiquement tandis que les contrôles ActiveX restent fidèles à leur look rétro ? Prenez les boutons de formulaire par exemple : uniformément gris et stricts.

Contrôle ActiveX "CommandButton" basique

Mettez un peu d'originalité dans vos formulaires en personnalisant les boutons ... sans utiliser de contrôle CommandButton !

Sachant que pour le même volume en KiloOctets, vous pouvez indifféremment utiliser un contrôle CommandButton, Label ou Image, profitons-en pour étudier les possibilités de personnalisation.

Pour cela, créez sous MS Powerpoint un rectangle sans contour, rempli avec un dégradé de couleur comme dans les exemples ci-dessous. Avec MS Powerpoint 2007 ou 2010, vous pouvez régler précisément la position de chaque couleur du dégradé pour un meilleur rendu de reflet lumineux. Sauvegardez ce rectangle comme une image au format BMP.


Rendez-vous sur Excel et créez trois controles ActiveX de mêmes dimensions : un CommandButton, un Label et une Image. Les dimensions sont réglables dans les champs Height et Width de la fenêtre de Propriétés des contrôles.
Configurez le paramètre Picture de chacun des contrôles en sélectionnant l'image BMP que vous venez de sauvegarder. Précisez dans le paramètre PicturePosition que l'image doit être centrée dans le contrôle : saisissez la valeur 12 - fmPicturePositionCenter. Cette valeur de paramètre signifie que que si vous ajoutez du texte à votre contrôles, celui-ci apparaîtra centré devant l'image.


Pour les contrôles Label et Image, précisez la valeur du paramètre SpecialEffect permettant d'obtenir un effet bouton : saisissez la valeur 1 - fmSpecialEffectRaised.

Pour les contrôles Label et CommandButton, renseignez le paramètre Caption en saisissant le texte que vous souhaitez faire apparaître sur le bouton. Vous constaterez que le contrôle Image ne permet pas de saisir de texte. Pour l'utiliser comme bouton, il vous faudra donc penser à intégrer le texte dans l'image de fond et à régler le paramètre PictureSizeMode à la valeur 1 - fmPictureSizeModeStretch afin d'étirer l'image aux dimensions du contrôle, comme dans l'exemple ci-dessous.


D'expérience, j'ai une préférence pour le contrôle Label car il permet d'avoir un meilleur rendu.
Pour utiliser un Label comme bouton, il faut le rendre cliquable. Pour cela, vous devrez définir son apparence lorsque le bouton de souris est en appui dessus, et lorsque le bouton de souris est relevé. Nous allons donc devoir rédiger quelques lignes de code VBA pour les évènements MouseDown() et MouseUp() du Label. Ces lignes de code ne sont absolument pas volumineuses en termes d'espace disque, ce qui rend l'usage du Label d'autant plus intéressant. Rendez-vous dans l'éditeur de code, à la feuille correspondant à l'onglet actuel et saisissez le code suivant (le Label s'appelle Label1) :

Private Sub Label1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label1.SpecialEffect = fmSpecialEffectSunken
End Sub

Private Sub Label1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Label1.SpecialEffect = fmSpecialEffectEtched
End Sub

Voici l'effet obtenu : un bouton moderne, plat, à reflets, qui s'enfonce et se relève lorsque l'on clique dessus !


Il ne reste alors plus qu'à coder l'action à réaliser lorsque le bouton est cliqué dans la procédure Label1_Click().

Private Sub Label1_Click()
    MsgBox "Smart XL !"
End Sub

N'hésitez pas à abuser de cette méthode qui rendra vos interfaces graphiques beaucoup plus attractives !

mardi 29 mai 2012

Oubliez les remplissages en aplats : privilégiez les dégradés !

Afin d'éviter la morosité et la platitude des cellules remplies en aplats de couleurs, privilégiez des remplissages en dégradés linéraires. Effet garanti !
Tableau avec cellules de titre en aplat (cliquez pour agrandir)

Tableau avec cellules de titre en dégradé linéaire (cliquez pour agrandir)
Pour cela, ne chercher pas dans l'onglet Accueil du ruban. Même en allant dans le sous-menu "Autres couleurs", Excel ne vous proposera que des aplats de couleurs.
 (cliquez pour agrandir)
Pour obtenir l'effet dégradé, sélectionnez vos cellules, puis faites un clic droit. Aller dans le sous-menu "Format de Cellule".

 (cliquez pour agrandir)
Rendez-vous à l'onglet "Remplissage" : vous pourrez alors définir des "Motifs et Textures" ce qui vous amène inexorablement à la fenêtre de définition des dégradés de couleurs.

 (cliquez pour agrandir)
Il ne vous reste plus qu'à trouver la couleur de texte la plus lisible sur votre fond dégradé, et régler la hauteur des lignes à votre convenance selon l'effet souhaité.

Prenez le contrôle de la zone d'affichage

Contrôlez l'apparence d'une feuille par le biais d'un code VBA s'exécutant dès l'activation de la feuille ou dès l'ouverture du classeur :
  • Cacher les barres d'outils (propriétés de l'objet Application)
  • Cacher la grille (propriété de l'objet ActiveWindow)
  • Supprimez l'affichage des en-têtes de lignes et de colonnes (propriété de l'objet ActiveWindow)
  • Lancez l'affichage en plein écran

Apparence initiale du classeur Excel (cliquez pour agrandir)
Apparence neutre du classeur Excel après application de la procédure Workbook_Open()  (cliquez pour agrandir)

Et surtout, empêchez l'utilisateur d'aller dans le menu d'options d'affichage pour réactiver ces éléments :  
Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    ' Empêcher l'affichage des en-têtes de lignes / colonnes
   If ActiveWindow.DisplayHeadings = True Then
        ActiveWindow.DisplayHeadings = False
        Dim Reponse As Integer
        Reponse = MsgBox("Veuillez ne pas modifier l'apparence de cette page", vbCritical, "Attention")
    End If
   
    'Empêcher la sélection d'une cellule pour la modifier
    ActiveSheet.Range("A65535").Select
    ActiveWindow.ScrollRow = 1
    ActiveWindow.ScrollColumn = 1
End Sub

Empêchez également l'utilisateur d'effectuer des actions de mise en forme en désactivant le clic droit sur la feuille :
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    Cancel = True
End Sub
Bien entendu, tout cela peut être appliqué à l'ensemble des feuilles du classeur en appliquant la procédure suivante à l'évènement Open du Workbook :
Private Sub Workbook_Open()

    With ActiveWindow
        .DisplayGridlines = False
        .DisplayHeadings = False
        .DisplayWorkbookTabs = False
    End With
       
    With Application
        .ShowStartupDialog = False
        .DisplayFormulaBar = False
    End With
   
    Application.CommandBars("worksheet menu bar").Enabled = False
   
    If Application.CommandBars("Standard").Visible = True Then
    Application.CommandBars("Standard").Visible = False
    End If
   
    If Application.CommandBars("Formatting").Visible = True Then
    Application.CommandBars("Formatting").Visible = False
    End If
   
    If Application.CommandBars("Borders").Visible = True Then
    Application.CommandBars("Borders").Visible = False
    End If
   
    If Application.CommandBars("Chart").Visible = True Then
    Application.CommandBars("Chart").Visible = False
    End If
   
    If Application.CommandBars("Control Toolbox").Visible = True Then
    Application.CommandBars("Control Toolbox").Visible = False
    End If
   
    If Application.CommandBars("Drawing").Visible = True Then
    Application.CommandBars("Drawing").Visible = False
    End If
   
    If Application.CommandBars("External Data").Visible = True Then
    Application.CommandBars("External Data").Visible = False
    End If
   
    If Application.CommandBars("Forms").Visible = True Then
    Application.CommandBars("Forms").Visible = False
    End If
   
    If Application.CommandBars("Formula Auditing").Visible = True Then
    Application.CommandBars("Formula Auditing").Visible = False
    End If
   
    If Application.CommandBars("List").Visible = True Then
    Application.CommandBars("List").Visible = False
    End If
   
    If Application.CommandBars("Picture").Visible = True Then
    Application.CommandBars("Picture").Visible = False
    End If
   
    If Application.CommandBars("PivotTable").Visible = True Then
    Application.CommandBars("PivotTable").Visible = False
    End If
   
    If Application.CommandBars("Protection").Visible = True Then
    Application.CommandBars("Protection").Visible = False
    End If
   
    If Application.CommandBars("Reviewing").Visible = True Then
    Application.CommandBars("Reviewing").Visible = False
    End If
   
    If Application.CommandBars("Task Pane").Visible = True Then
    Application.CommandBars("Task Pane").Visible = False
    End If
   
    If Application.CommandBars("Text To Speech").Visible = True Then
    Application.CommandBars("Text To Speech").Visible = False
    End If
   
    If Application.CommandBars("Visual Basic").Visible = True Then
    Application.CommandBars("Visual Basic").Visible = False
    End If
   
    If Application.CommandBars("Watch Window").Visible = True Then
    Application.CommandBars("Watch Window").Visible = False
    End If
   
    If Application.CommandBars("Web").Visible = True Then
    Application.CommandBars("Web").Visible = False
    End If
   
    If Application.CommandBars("WordArt").Visible = True Then
    Application.CommandBars("WordArt").Visible = False
    End If
   
    If Application.CommandBars("Exit Design Mode").Visible = True Then
    Application.CommandBars("Exit Design Mode").Visible = False
    End If
   
    If Application.CommandBars("Full Screen").Visible = True Then
    Application.CommandBars("Full Screen").Visible = False
    End If
   
    If Application.CommandBars("Organization Chart").Visible = True Then
    Application.CommandBars("Organization Chart").Visible = False
    End If
   
    If Application.CommandBars("Shadow Settings").Visible = True Then
    Application.CommandBars("Shadow Settings").Visible = False
    End If
   
    If Application.CommandBars("Drawing Canvas").Visible = True Then
    Application.CommandBars("Drawing Canvas").Visible = False
    End If
   
    If Application.CommandBars("Diagram").Visible = True Then
    Application.CommandBars("Diagram").Visible = False
    End If
   
    If Application.CommandBars("Compare Side by Side").Visible = True Then
    Application.CommandBars("Compare Side by Side").Visible = False
    End If
   
    If Application.CommandBars("Circular Reference").Visible = True Then
    Application.CommandBars("Circular Reference").Visible = False
    End If
   
    If Application.CommandBars("Chart Menu Bar").Visible = True Then
    Application.CommandBars("Chart Menu Bar").Visible = False
    End If
   
    If Application.CommandBars("3-D Settings").Visible = True Then
    Application.CommandBars("3-D Settings").Visible = False
    End If
   
End Sub

Seul petit bémol : un développeur aguerri saura activer le mode "Création" dans l'onglet "Visual Basic" (MS 2003) / "Développeur" (MS 2007/2010) pour accéder au contenu des cellules. Il ne pourra cependant pas modifier durablement l'apparence de la feuille car celle-ci reviendra automatiquement à l'apparence que vous lui avez fixée dès qu'elle sera ré-activée.