Jusqu'à la version Office 2003, les rubans n'existaient pas : il y avait les menus et les barres d'outils. Leur gestion était simple. Les rubans, c'est une autre histoire ! S'il est facile de personnaliser le ruban prédéfini, créer son propre ruban complémentaire de toutes pièces, c'est une autre paire de manches. |
Sommaire
Fichiers joints
CallBackAttributs.xlsx - Liste de tous les CallBacks et de tous les attributs de tous les coontrôles sous format Excel images.zip - Toutes les images nécessaires au didacticiel ImageMso.xml - Ruban d'affichage de toutes les images Mso Bases de données des différentes étapes de ce didacticiel : rubanpersocours01.zip Liens externes
dddd |
Lorsque vous concevez une base de données Access, vous créez généralement des boutons, des listes déroulantes qui permettent de faire telle ou telle action (Ouvrir des formulaires, des états, des graphiques, des requêtes, rechercher des enregistrements, etc.)
Vous avez certainement l'habitude de programmer vos éléments directement au coeur de vos formulaires.
L'idée des rubans personnalisés est de transférer ces commandes directement dans le ruban, afin de "coller" avec la philosophie de Microsoft Office.
Par exemple, je me suis amusé a reproduire toute une série de boutons et listes déroulantes sous forme de ruban personnalisé dans cette base de données :
Commencez par créer une base de données complètement vide, que vous appellerez RubanPersoCours.accdb, dans un dossier créé expressément pour l'occasion, ou vous voulez sur votre disque dur.
Avant de nous lancer dans la grande aventure de la création de rubans, regardons ce qu'il est possible de faire comme personnalisation directement dans Access.
Allez dans le menu Fichier/Options, et dans les rubriques de gauche : "Personnaliser le ruban". Nous allons créer un nouvel onglet, ainsi qu'un nouveau groupe, et une nouvelle icone dans le groupe.
Et voilà ! Maintenant, vous avez un nouvel onglet à votre ruban (entre accueil et créer), qui contient une seule icone (Enregistrer). Elle est en gris clair, parce qu'il n'y a rien a enregistrer (on n'a même pas encore créé une seule table)
Cette personnalisation est liée à votre Access de votre poste de travail, et absolument pas à la base de données que nous venons de créer. C'est à dire que si vous fermez cette base de données, cette personnalisation persistera, et sera toujours présente, quelle que soit la base de données que vous ouvrez. Et donc, si vous envoyez cette base de données par e-mail à quelqu'un, ce quelqu'un ne verra pas votre personnalisation.
Constatez que la petite icone de balance que vous avez choisi n'a servi a rien : elle n'apparaît nulle part. Nou verrons bien plus tard à quoi peuvent servir ces icones de groupe
Constatez également qu'il n'est pas possible de placer directement une commande (comme l'icone enregistrer que nous avons choisi) directement dans l'onglet Mes fruits sans créer un groupe Fruits frais, ce qui me parait un peu bizarre.
Cette personnalisation a été incluse dans un fichier externe dont j'ignore le nom et l'endroit. Toutefois, il est possible de visualiser le contenu de cette personnalisation en l'exportant. Retournez dans le menu Fichier/Options, et cliquez en bas à droite sur Importer/Exporter, et choisissez Exporter toutes les personnalisations :
Appelez-le Les fruits sont bons, et laissez l'extension .ExportedUI, et enregistrez ce fichier dans un dossier que vous retrouverez facilement.
Ouvrez ce fichier avec le bloc-notes (ou avec n'importe quel éditeur de texte, comme Word). Attention : pensez-bien a choisir Tous les types de fichiers, afin de voir les fichiers .exportedUI. UI sont les initiales de User Interface (Interface Utilisateur, c'est à dire en d'autres mots : les rubans).
Voici le contenu :
On ne comprend pas grand chose, mais si vous appuyez sur Entrée juste après chaque ">", on se rend déjà plus compte de quoi il s'agit (mso est l'acronyme de "MicroSoft Office":
En regardant de plus près, on voit qu'il y a des trucs entre < et > qui ont l'air de coommencer et de finir, comme par exemple <mso:ribbon> qui a l'aitr de finir par </mso:ribbon>.
Du coup, on pourrait essayer de les mettre à la même largeur (on dit "indenter"), comme ceci :
Comme vous voyez, on arrive nettement mieux à lire. ce que vous voyez s'appelle du XML (eXtended Markup Language). C'est ce qu'on appelle un "Langage de description de données". Nous n'allons pas ici faire un cours de XML, mais en gros, c'est un langage qui permet de décrire les choses de manière très formelle, à l'aide de balises < et >.
Voici la description d'une cuisine en français :
Voici une grande cuisine, avec une table sur laquelle il y a un couteau et trois assiettes (une rouge et deux bleues). Il y aussi un plan de travail avec une planche a pain, deux bouteilles, et une salière a moitié vide.
Et la même description, en XML :
XML<Cuisine Taille="Grande"> <Table> <Couteau/> <Assiette Couleur="Rouge"/> <Assiette Couleur="Bleu" Nombre="2"/> </Table> <PlanDeTravail> <PlancheAPain/> <Bouteille Nombre= "2" > <Salière Remplissage="50%" > </PlanDeTravail> </Cuisine>
Admettez qu'on se représente quand même mieux la cuisine et ses composants en lisant la description XML qu'en français, même si c'est moins poétique.
Du coup, maintenant que vous avez enregistré ces personnalisations dans un fichier à part, vous pouvez très bien envoyer ce fichier par e-mail à n'importe qui, qui pourra intégrer votre ruban à son propre Access.
Essayons :
Voilà : c'est tout ce que nous allons dire sur la personnalisation du ruban Access, car ce n'est vraiment pas le sujet de ce didacticiel. De plus, cette personnalisation est très limitée, comme vous le verrez par la suite lorsque nous allons créer nos propres rubans.
Nous allons créer notre premier ruban attaché à notre base de données. Accrochez-vous, parce qu'il faut avouer que ce n'est pas simple. Les rubans sont certes plus puissants et plus personnalisables que les anciennes barres d'outils d'Access 2003 et versions antérieures, mais pour personnaliser ce ruban, ça ne se fait pas du tout aussi facilement.
Commencez par créer une nouvelle table, avec exactement ces deux champs : RibbonName (Texte) et RibbonXML (Mémo) comme sur l'image:
Définissez RibbonName en clé primaire (Nous n'aurons jamais deux fois le même nom de ruban)
Enregistrez-là sous le nom exact : USYSRibbons, et fermez ensuite cette table.
Tiens ! Elle n'apparait pas dans la liste des tables du volet de navigation !
En fait, dès que vousnommez une table en commençant par USYS (User SYStem), que ce soit USYSRibbons, ou USYSJaimeLeChocolat, Access considère que c'est une table-système, et la masque. Access comporte, à la base plusieurs tables-système qu'il ne faut pas modifier, et qu'il est préférable de masquer. Mais dans notre cas, nous voulons la voir, cette table USYSRibbons.
Voici comment afficher les tables système : Cliquez avec le bouton DROIT de votre souris précisément ici, et choisissez Volet de navigation :
Cochez Afficher les objets système :
Les tables système sont maintenant affichées. Les tables système Microsoft, qui commencent par MSYS, en gris clair, qu'il ne faut pas toucher, et, en dernier, en noir, votre table USYSRibbons :
Allez dans USYSRibbons, et élargissez les lignes et les colonnes afin de pouvoir y écrire beaucoup de texte facilement, comme ceci :
Je vais commencer par vous montrer comment créer de simples onglets dans le ruban existant, nous mettrons les boutons, listes déroulantes, cases à cocher et toutes ces réjouissances bien plus bas dans ce didacticiel, soyez patients, car il est important de bien comprendre les bases.
Dans RibbonName, écrivez : Ruban des fruits, et dans RibbonXML, recopiez ceci (sans la moindre erreur) :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="ViveLeRuban" label="Mes fruits aussi"> </tab> </tabs> </ribbon> </customUI>
Maintenant, voyons voir ce que ça donne : nous allons définir ce Ruban des fruits comme ruban de notre base de données. Fermez USYSRibbons, et allez dans le menu Fichier/Options/Base de données active, et dans la partie de droite, cherchez la section Options de la barre d'outils et du ruban, et choisissez comme nom du ruban Ruban des fruits.
Oups ! La liste est vide !
C'est normal. Pour pouvoir choisir un ruban de USYSRibbons, il faut qu'Access ait pris le temps de le charger en mémoire. En bref, fermez et rouvrez votre base de données : Comme elle se trouve dans la liste des fichiers récents, c'est très facile :
Maintenant seulement, vous pouvez retourner dans Fichier/Options/Base de données active, et dans la partie de droite, cherchez la section Options de la barre d'outils et du ruban, et choisissez comme nom du ruban Ruban des fruits :
Ce n'est pas tout : il faut maintenant encore fermer et rouvrir la base de données pour que ce ruban soit appliqué.
OUF ! Voilà ! Nous avons enfin notre ruban qui apparait. Il est tout triste, tout vide, tout à droite, mais il est là !
Maintenant, si vous fermez la base de données, ou que vous en ouvrez une autre, Mes fruits restera apparent, tandis que mes fruits aussi disparaitra, ce qui sera bien la preuve que ce dernier onglet est bel et bien attaché à notre base de données.
Maintenant, attention ! Si vous faites la moindre erreur dans votre code XML, le ruban se contentera de ne pas être affiché, sans même que vous en soyez informé, c'est assez vache !
Essayez : Allez dans USYSRibbon, et remplacez ribbon par ribon (avec un seul b):
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> ...
par
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribon> <tabs> ...
Fermez et rouvrez votre base de données : aucune erreur, mais Mes fruits aussi n'apparait pas !
Ce serait quand même drôlement mieux si l'erreur pouvait nous êtes signalée !
C'est possible, mais c'est une option bien planquée : Fichier/Options/Rubrique de gauche : paramètres du client, et à droite cherchez le groupe Général, et cochez Afficher les erreurs du complément d'interface utilisateur :
Cette option est maintenant définie pour toutes vos bases de données, et pas seulement celle-ci.Fermez et rouvrez votre base de données. Vous voici confronté à un énorme message d'erreur totalement incompréhensible, suivi d'un deuxième, dès que vous avez cliqué sur OK On va regarder en détail ce qui se passe plus bas :
Dans le premier message d'erreur, il parle beaucoup de <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">. Quand on lit attentivement, on constate que c'est ribon qui pose problème (ben oui, on l'a fait exprès). Il nous facilite encore la vie en nous donnant le numéro de ligne sur laquelle le problème a été interpellé : 2. (La colonne ne nous sert pas à grand chose).
On sait déjà qu'il manque un b à ribbon, mais il nous le dit plus précisément : dans son "fichier de référence" (qu'on appelle un Schéma XML) http://schemas.microsoft.com/office/2009/07/customui", il est précisé que l'élément ribon n'est pas possible à utiliser. On dit que notre code XML est "invalide".
Le 2ème message parle presque de la même chose, mais il ne fait pas référence à ce schéma XML: il nous informe simplement que si on ouvre une balise par <ribon> avec un seul b, on ne peut pas la fermer par </ribbon> avec deux b. ce 2ème message se fiche du "fichier de référence", il se contente juste de dire qu'on a fait une sorte de "faute d'orthographe". On dit alors que le code XML est "Mal formé".
Ainsi, pour une seule toute petite faute, notre code XML est à la fois invalide, mal formé, on se fait insulter par deux gros messages d'erreur, et l'onglet ne s'affiche pas. Ca ne rigole pas !
Quand je vous dis que c'est vraiment très précis, je ne plaisante pas : il ne faut même pas confondre les minuscules et les majuscules. Si par exemple, je remplace <ribbon> par <Ribbon>, que je ferme et que je rouvre ma base de données, je vais avoir un message d'erreur également :
Pire encore : il faut respecter les espaces. Par exemple
<tab id="ViveLeRuban"label="Mes fruits aussi">
est mal formé parce qu'il manque un espace entre " et label. On doit vraiment écrire :
<tab id="ViveLeRuban" label="Mes fruits aussi">
Je vous invite maintenant à :
Ainsi, il y existe quelques différences entre le schéma XML pour Office 2007 et Office 2010. Si vous travaillez avec Access 2007, vous devez commencer votre ruban XML par :
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
Et si vous travaillez avec Office 2010 :
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
Si vous êtes curieux de savoir à quoi ressemble ce schéma XML, cliquez ici. Vous constatez que c'est un gros fichier assez complexe.
Nous avons vu comment attribuer un ruban à votre Access personnel, et un ruban supplémentaire pour votre base de données actuelle.
On peut, en plus, attribuer un ruban uniquement pour un formulaire ou un état particulier.
Pour commencer, il faut que nous créions ce deuxième ruban dans USYSRibbons, afin qu'on puisse le choisir dans notre formulaire :
Allez dans la table USYSRibbons, et ajoutez ce 2ème ruban simplement comme ceci :
RibbonName : Les beaux légumes
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="Tagada" label="Les beaux légumes"> </tab> </tabs> </ribbon> </customUI>
Fermez la table USYSRibbons, et créez un formulaire complètement vide, en mode création. Dedans, mettez une bête zone de texte "Formulaire de test de rubans", juste pour savoir de quoi on parle :
Enregistrez-le sous F_RubanTest
(Raccourci-clavier )
Demandez les propriétés du formulaire,
et dans l'onglet Autre/Nom du ruban,
choisissez Ruban les légumes :
Oups ! Il n'apparait pas !
C'est comme tout à l'heure, vous devez fermer la base de données, la rouvrir, rouvrir votre formulaire, et à ce moment-là seulement, vous pourrez le sélectionner :
Lancez votre formulaire en mode formulaire, et vous verrez alors votre nouvel onglet trôner fièrement à droite :
Vous connaissez maintenant les trois endroits de création de ruban :
Avant de se lancer dans la création de boutons, cases à cocher, listes déroulantes, etc. qui vont garnir nos rubans, je vous montre une dernière chose : vous verrez plus tard que certains codes XML de création de rubans soient extrêmement volumineux, au point ou le champ RibbonXML de la table USYSRibbons le refuse.
Aussi, nous avons une alternative : le chargement de rubans externes : c'est à dire que nous allons intégrer dynamiquement un fichier XML externe, à chaque ouverture notre base de données. Ce fichier XML sera disponible ensuite exactement de la même manière que les différents enregistremnts de la table USYSRibbons.
Nous avons déjà eu affaire avec des fichiers externes. vous vous rappelez des .exportedUI du début de ce didacticiel ? Bon, maintenant, ça va être quelque peu différent.
Ouvrez le bloc-notes, et recopiez-y ce code XML :
Attention : Si vous ne recopiez pas ce code XML, mais que vous préférez le taper au clavier, lorsque vous voudrez passer à la ligne, vous ne pouvez pas simplement taper sur , mais vous devez faire
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="Miam" label="Biscuits et bonbons"> </tab> </tabs> </ribbon> </customUI>
Enregistrez ensuite ce fichier au même endroit que votre base de données, et donnez-lui le nom
Bons biscuits.xml :
Le bloc-notes est un éditeur de texte vraiment rudimentaire ! ce serait quand même pas mal d'avoir à disposition un éditeur de texte qui reconnaît les balises XML, et qui les met en couleur par exemple !
Eh bien, cet éditeur de texte magique existe, et il est gratuit : il s'appelle NotePad++, et vous pouvez le télécharger ici par exemple.
Je vous le recommande très chaleureusement. regardez plutôt : lorsque je crée mon fichier xml avec NotePad ++, ça apparait comme ceci :
Mais ce n'est pas le meilleur : Allez dans le menu de Notepad++ language/xml :
Et admirez le résultat : le code xml est tout correctement mis en différentes couleurs, avec en plus, la possibilité de masquer les différentes balises de manière pertinente pour faciliter notre travail !
Maintenant que le fichier Les friandises.xml est créé, quittez le bloc-notes (ou Notepad++ si vous l'avez téléchargé)
Créez un nouveau module VBA (Créer/Module)
Recopiez y cette fonction :
VBAFunction ImportationRubanDessert() Dim GestionFichier As New FileSystemObject Dim BoiteABiscuits As TextStream Set BoiteABiscuits = GestionFichier.OpenTextFile(CurrentProject.Path & "\Bons biscuits.xml", ForReading) Application.LoadCustomUI "Les Friandises", BoiteABiscuits.ReadAll End Function
Analysons-là :
Function ImportationRubanDessert() ... End Function
Nous créons une Function et pas un Sub parce que cette fonction sera ensuite appelée par la macro AutoExec (Macro qui a la particularité de s'exécuter dès l'ouverture de la base de données), et les macros ne peuvent appeler que des Function, pas des sub (étrange, mais c'est ainsi). Si nous n'avions pas dû l'appeler depuis Autoexec, nous aurions créé un Sub.
Dim GestionFichier As New FileSystemObject
VBA possède beaucoup d'insctructions nativement, mais il a parfois besoin d'instructions se trouvant dans des bibliothèques externes. Dans notre cas, nous allons avoir besoin d'instructions permettant de lire le contenu d'un fichier texte (OpenTextFile). Ces instructions seront disponible par le biais de GestionFichier qui sera un objet issu de la bibliothèque FileSystemObject. Du coup, pour pouvoir l'utiliser, vous devez, depuis votre module VBA, installer un truc qui s'appelle Microsoft Scripting Runtime. Allez dans le menu Outils/Référence, et cochez la case Microsoft Scripting Runtime (C'est par ordre alphabétique). A présent, ce fichier sera inclus et disponible tout le temps dans CETTE base de données.
Pour info, en base de la boîte de dialogue, vous voyez de quel fichier il s'agit : scrrun.dll (SCRiptingRuntime.DLL)
Dim BoiteABiscuits As TextStream
Nous déclarons une variable de type TextStream (Flux de texte). C'est un type de variable qui va permettre de récupérer le contenu de notre fichier Bons biscuits.xml. Pour info, TextStream est aussi une variable qui se trouve dans la bibliothèque Microsoft Scripting Runtime.
Set BoiteABiscuits = GestionFichier.OpenTextFile(CurrentProject.Path & "\Bons biscuits.xml", ForReading)
Voici comment utiliser cette variable BoiteABiscuits : Nous ouvrons (OpenTextFile
) le fichier (Bons biscuits.xml) en lecture (ForReading
)
CurrentProject.Path
(Chemin d'accès du projet courant) représente le dossier de votre ordinateur dans lequel se trouve votre base de données, tout simplement. Par exemple, si votre base de données rubanpersocours.accdb se trouve dans C:\Mes documents\Exercices, alors, CurrentProject.Path
contient C:\Mes documents\Exercices. le signe &
veut dire "Coller", en quelque sorte. C'est à dire qu'on "colle" le fichier XML Bons biscuits.xml à la suite du dossier de votre base de données (sans oublier le "\" avant !)
Ainsi CurrentProject.Path & "\Bons biscuits.xml"
est en fait, dans notre exemple : C:\Mes documents\Exercices\Bons biscuits.xml
cette astuce vous permettra par la suite de déplacer tout votre dossier Exercices dans un autre endroit de votre disque dur sans que ça perturbe ce code VBA qui va toujours chercher le fichier XML dans le dossier courant.
XMLApplication.LoadCustomUI "Les Friandises", BoiteABiscuits.ReadAll
Voici comment nous rendons le ruban disponible : grâce à LoadCustomUI (Chargement Personnalisé du UserInterface). les Friandises sera le nom de ruban que vous pourrez sélectionner dans la liste déroulante des rubans disponibles dans Fichier/Options Access, ou dans la propriété Nom du ruban des formulaires ou des états, exactement de la même manière que les enregistrements de la table USYSRibbons.
BoiteABiscuits.ReadAll (LireTout) est l'instruction qui permet de lire tout le contenu du fichier Bons buscuits.xml d'un seul coup, même s'il contient des milliers de lignes XML (dans le cas d'un très très gros ruban). Et ce contenu est donc transféré en une fois dans Les friandises avec LoadCustomUI.
Et c'est bien là tout le bénéfice du fichier externe, même si c'est plus compliqué à gérer que USYSRibbons : c'est la possibilité d'avoir des énormes rubans. Vous verrez qu'on y arrive vite !
Revenez dans VBA et enregistrez votre module sous le nom P_ChargementRubans (P comme Programmation, mais c'est une norme à moi, ce n'est pas obligatoire) :
La fonction est écrite, mais nous ne l'avons pas encore exécutée. C'est à dire que si vous essayez de choisir les friandises comme ruban de la base de données, ou d'un formulaire, il n'apparaîtra pas.
Par contre, cliquez quelque part, n'importe ou dans votre function, et appuyez sur la touche (pour l'exécuter)
La preuve que ça a bien marché, si vous cliquez une 2ème fois sur , vous serez gratifié d'un message d'erreur comme quoi le ruban est déjà chargé, et qu'on ne peut pas le charcher une seconde fois :
Maintenant, sans même avoir besoin de fermer et rouvrir votre base de données, vous pouvez aller dans Fichier/Options/Base de données active, et constater que vous avez la possibilité de sélectionner Les friandises, en plus des deux rubans stockés dans USYSRibbons :
Choisissez Les friandises comme ruban principal de la base de données, et cliquez sur OK. Il vous informe que la base doit être fermée et rouverte pour que ce ruban soit pris en compte. OK, fermez et rouvrez !
Ah ! Bon, ben le ruban ne s'affiche pas ! Pourtant on devrait bien avoir un nouvel onglet "biscuits et bonbons" tout à droite (c'est ce qu'on avait décidé dans le fichier XML)
XML... <tabs> <tab id="Miam" label="Biscuits et bonbons
"> </tab> ...
Et pourtant, si vous retournez dans Fichier/Options, vous verrez bien que le ruban est défini sur Les friandises !
En fait, Les friandises n'est pas disponible ! vous avez pourtant bien exécuté la function, et vous avez pu la choisir dans la liste déroulante, MAIS ensuite, vous avez dû fermer et rouvrir la base de données, du coup, c'est comme si vous n'aviez pas exécuté la function ! C'est le serpent qui se mord la queue : si vous ré-exécutez la function, le ruban sera à nouveau disponible, mais vous devrez fermer et rouvrir la base de données, etc.
L'absence de messsage d'erreur est sans doute un oubli de Microsoft : en fait, vous pouvez écrire n'importe quoi comme ruban, il vous fera croire que ce ruban est disponible, mais il n'en est rien, et ce, même si vous avez coché la petite case des interceptions des erreurs que je vous ai montrée ici.
Cette fonction doit donc être appelée automatiquement dès l'ouberture de la base de données, à l'aide de cette fameuse macro Autoexec.
Voici la marche à suivre pour créer la macro Autoexec :
Une fois créée, vous pouvez maintenant fermer et rouvrir votre base de données. Maintenant, vous avez maintenant bien l'onglet Biscuits et bonbons qui apparait sur la droite de votre ruban :
Nous allons enfin nous attaquer à la création d'éléments dans un ruban !
Nous allons nous concentrer sur les boutons, mais il existe toute une pléiade d'autres contrôles que nous étudierons ultérieurement : Case à cocher (checkBox), Boutons-bascule (toggleButton), Simple texte (labelControl), Liste déroulante (comboBox), Zone d'édition (editBox), Galerie d'icones (Gallery), Bouton liste déroulante (splitButton) et Menu (dynamicMenu)
Afin de faciliter la lecture de notre table USYSRibbons, je vous conseille de définir la police de caractères en Courier New. En effet, cette police a l'avantage de donner la même largeur à toutes les lettres (On appelle ça une police non proportionnelle), comme sur les anciennes machines à écrire. C'est moins joli, mais pour lire le XML, c'est plus pratique :
Créez un nouvel enregistrement dans la table USYSRibbons :
RibbonName : Bouton
Rappel : Si vous ne recopiez pas ce code XML, mais que vous préférez le taper au clavier, lorsque vous voudrez passer à la ligne, vous ne pouvez pas simplement taper sur , mais vous devez faire
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="Coucou" label="Test de boutons"> <group id="Tralala" label="Quel joli groupe" <button id="Cocorico" label="Clique sur moi"/> </group> </tab> </tabs> </ribbon> </customUI>
Etes-vous observateur ? Voyez-vous la petite erreur que j'ai glissé dans ce code XML ?
Essayez de la trouver ! Si vous la trouvez, ne la corrigez pas. Si vous ne la trouvez pas, n'en faites pas une maladie ! C'est que vous êtes comme moi : très distrait.
Maintenant, fermez votre base de données, et rouvrez-là.
Dès l'ouverture de la base de données, cette petite erreur vous est signalée, même si ce ruban n'est absolument pas utilisé dans notre base de données : il existe juste dans USYSRibbon :
C'est très vache, parce qu'il vous signale bien le numéro de ligne (et même la colonne) sur laquelle se situe l'erreur, mais il ne vous dit absolument pas de quel ruban il s'agit !
C'est à dire que si vous vous étiez amusé à modifier plusieurs rubans de USYSRibbon, ainsi que le ruban externe Bons biscuits.xml, vous ne sauriez absolument pas de quel ruban il veut parler !
Bon, ici, nous savons que c'est le nouveau ruban qui pose problème.
En fait, j'ai simplement oublié le ">" à la fin de : "Quel joli groupe" :
XML... <tab id="Coucou" label="Test de boutons"> <group id="Tralala" label="Quel joli groupe">
...
Ouvrez votre formulaire F_RubanTest (Vous vous rappelez ?) en mode création, et définissez sa propriété Nom du ruban au ruban que nous venons de créer, que nous avons nommé "Un seul bouton".
Après avoir corrigé l'erreur, fermez et rouvrez encore une fois la base de données. Ouvrez F_RubanTest en mode création, et définissez Un seul bouton comme nom de ruban, à la place de Ruban des légumes :
On ne peut donc avoir qu'un seul ruban dans le formulaire, mais nous verrons qu'il peut contenir plusieurs onglets.
Lancez F_RubanTest en mode saisie de données, et constatez que nous avons bien votre onglet à droite, avec un bouton dedans :
<customUI>, c'est donc bien l'adresse du fichier de vérification, vous vous rappelez ?
Ensuite, nous avons, imbriquées obligatoirement l'une dans l'autre, successivement <tabs> (Onglets), <tab> (un onglet particulier), et <group>. Il est interdit de mettre directement un bouton dans le ruban sans l'intégrer dans un groupe. D'ailleurs, si vous cliquez sur les onglets prédéfinis d'Access, de Word, ou d'Excel, vous constaterez que tous les boutons font partie de groupes. Je ne dis pas que c'est bien ou mal, je constate que c'est comme ça.
Ensuite, nous avons notre fameux <button>. Constatez qu'il n'y a qu'une balise <button>, alors que toutes les autres balises s'ouvrent et se ferment. Et à chaque fermeture de balise, il y a la barre oblique : "/".
En XML, c'est comme ça : toute balise doit exister deux fois : une fois a l'ouverture et une fois à la fermeture, mais il est possible de n'avoir qu'une seule balise, comme dans le cas du button, mais si vous regardez attentivement, vous constatez qu'il y a quand même la barre oblique avant la fermeture : <button id="Cocorico" label="Clique sur moi"/>
la balise <button> possède plusieurs attibuts (id, label, et d'autres), mais id est obligatoire. Nous n'en avons pas encore vu l'utilité, mais nous devons indiquer une valeur sans espace (id="Coco Rico" n'aurait pas été possible)
Pour l'instant, quand on clique sur le bouton, il ne se passe rien, c'est normal, on n'a encore rien précisé.
A titre d'exercice, et pour ne plus avoir nos deux anciens onglets Mes fruits et Biscuits et bonbons sans arrêt sous les yeux, supprimez-les.
Pour Mes Fruits, rafraîchissez-vous la mémoire ici, et cliquez ici :
Pour Biscuits et bonbons, effacez simplement cette liste déroulante :
Fermez et rouvrez votre base de données ainsi que F_RubanTest :
La structure XML va nous permettre de créer facilement autant d'onglets, de groupes et de boutons qu'on désire. Recopiez ce ruban XML dans un nouvel enregistrement de USYSRibbons, dont vous appelerez le RibbonName : Fruits et légumes.
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TABFruit" label="Les fruits"> <group id="GRPFruitRouge" label="Fruits rouges"> <button id="BDCGroseille" label="Groseille"/> <button id="BDCFraise" label="Fraise"/> </group> <group id="GRPFruitJaune" label="Fruits jaunes"> <button id="BDCAnanas" label="Ananas"/> <button id="BDCCitron" label="Citron"/> </group> </tab> <tab id="TABLegume" label="Les légumes"> <group id="GRPLegume" label="Légumes"> <button id="BDCHaricot" label="Haricot"/> <button id="BDCTomate" label="Tomate"/> </group> </tab> </tabs> </ribbon> </customUI>
Ensuite, vous fermez et rouvrez votre base de données, vous rouvrez votre formulaire F_RubanTest en mode création afin de définir son ruban comme Fruits et légumes, et vous lancez votre formulaire en mode saisie de données :
Comme vous le constatez, le XML peut rapidement devenir long (et complexe). Aussi, j'insiste à nouveau pour que vous téléchargiez Notepad++
En effet, le fait de travailler directement dans USYSRibbon est vraiment malpratique : Vous devez démesurément élargir le champ RibbonName, vous n'avez absolument pas de coloration syntaxique, et vous devez toujours faire attention d'appuyer sur CTRL-ENTER au lieu de ENTER pour insérer des nouvelles lignes. Je préconise donc l'utilisation de Notepad++ comme instrument intermédiaire : vous travaillez dans NotePad++, et, au dernier moment, vous copiez-collez le contenu de votre XML dans un enregistrement de USYSRibbons.
Il est possible de commenter le code XML <!-- en les encadrant comme ceci -->.
Copiez collez le code XML Fruits et légumes dans NotePad++, et rajoutez des lignes de commentaire, comme ceci :
Vous pouvez évidemment ajouter ces commentaires drectement dans USYSRibbon, mais vous allez simplement un peu plus galérer.
Constatez qu'on peut créer des commentaires sur plusieurs lignes.
Attention : Vous ne pouvez pas ajouter plus de tirets que nécessaire, sinon une erreur survient.
Par exemple :
<!-- Tralala -------------------- --> ne sera pas accepté.
Une fois que vous avez fini de travailler confortablement avec Notepad++, vous allez simplement copier-coller votre XML dans USYSRibbons, comme ceci :
La coloration syntaxique vous évite également beaucoup d'erreurs : par exemple, si vous oubliez de refermer un commentaire, vous voyez immédiatement que quelque chose cloche : tout est en vert ! regardez cet exemple :
Cet exemple est particulièrement vache, parce que ça ne donnera pas d'erreur XML ! Eh non ! Access ne va simplement pas afficher le groupe des fruits rouges puisqu'ils sont considérés comme des commentaires.
Vous avez constaté que j'ai donné de snoms quelques peu plus "techniques" aux id. J'ai arrêté de les appeler Tralala ou Cocorico.
J'ai pris l'habitude, et ça nous aidera par la suite, de commencer par trois lettres en majuscule, suivi du nom de l'objet :
TABFruit : TAB pour indiquer que c'est un TAB (un onglet)
GRPFruitRouge : GRP pour GRouPe
BDCGroseille : BoutonDeCommande
Vous n'êtes pas obligé d'adopter ma nomenclature, mais c'est vraiment plus pratique d'être bien organisé avec ces id, comme vous le verrez.
Il s'agit maintenant de faire des trucs quand on clique sur un bouton, sinon, ça ne sert pas à grand chose.
Commencez par créer un nouveau ruban dans USYSRibbons.
RibbonName : Premier clic bouton
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TABProcedureRappel" label="Procédures de rappel"> <group id="GRPPremierTest" label="Callback"> <button id="BDCTestCallBack" label="Clique-moi!"onAction="TralalaYoupi
"/> </group> </tab> </tabs> </ribbon> </customUI>
Ensuite, créez un nouveau module VBA . C'est très important de créer un module à part. Vous ne pouvez pas créer la procédure suivanbte dans un module de formulaire, ça ne marche pas.
Créez-y cette procédure toute simple qui va juste afficher dans une petite boîte : MeSsaGeBOX "Je suis heureux que vous ayez cliqué !"
VBA' Cette procédure sera exécutée dès qu'on clique sur le bouton BDCTestCallBack :
SubTRALALAyoupi
(ViveLaVie As IRibbonControl) MsgBox "Je suis heureux que vous ayez cliqué !" End Sub
Nous comprendrons plus tard pourquoi ça s'appelle "Procédure de rappel", ou en anglais "CallBack"... C'est simplement une procédure qui va s'exécuter dès qu'on clique sur le bouton.
Vous devez donc indiquer le même nom que onAction="TralalaYoupi" (Constatez que seul le "A" de onAction est en majuscule ! C'est indispensable !), et vous devez ajouter entre parenthèses une variable de votre choix (ViveLaVie ou n'importe quoi d'autre) As IRibbonControl (Interface de Contrôle de Ruban). Nous verrons plus tard à quoi ça sert. Si vous ne le faites pas (par exemple, vous écrivez juste SubTralalaYoupi(), sans le paramètre ViveLaVie, vous recevrez un message d'erreur comme quoi TralalaYoupi n'existe pas.
Constatez que le commentaire en vert est juste précédé par une ' apostrophe, et ne se finit par rien, car c'est ainsi que s'écrivent les commentaires en VBA, alors qu'en XML c'est <!-- Comme ceci -->.
Les majuscules/minuscules ne sont pas importantes, contrairement au XML (J'ai écrit tralalayoupi différemment en VBA et dans XML, mais ça ne pose pas de souci.)
OUPS ! ERREUR !
Il ne trouve pas la fonction TralalaYoupi ! (Bon, déjà, ce n'est pas une "fonction", mais une "procédure" (Sub) !
Pourtant, je vous assure qu'on a tout fait bien comme il faut ! En fait, il y a un bug : voici comment y remédier : Allez dans un module VBA, n'importe lequel, et décochez, puis recochez la référence à Microsoft Office 14 Object Library, comme ceci :
Ne me demandez pas pourquoi ça marche mais ça marche. Etvous n'aurez plus jamais besoin de faire cette opération dans cette base de données.
Il vous suffit maintenant de retourner dans votre formulaire (même pas besoin de tout fermer), et de cliquer sur le bouton Clique-moi
Pour plus de lisibilité dans votre fichier XML, il est possible de placer les arguments des balises bien alignés l'un en dessous de l'autre, comme ceci :
Maintenant, modifiez le code XML de votre ruban Premier clic bouton pour ajouter deux autres boutons, comme ceci :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TABProcedureRappel" label="Procédures de rappel"> <group id="GRPPremierBouton" label="Callback"> <button id="BDCTestCallBack" label="Clique-moi!" onAction="TralalaYoupi"/><button id="BDCBanane" label="Banane" onAction="MangezDesFruits"/>
<button id="BDCFraise" label="Fraise" onAction="MangezDesFruits"/>
</group> </tab> </tabs> </ribbon> </customUI>
L'ordre des attributs n'a aucune importance en XML. Vous pouvez écrire indifféremment :
<button id="BDCBanane" label="Banane" onAction="MangezDesFruits"/>
ou
<button label="Banane" id="BDCBanane" onAction="MangezDesFruits"/>
ou même
<button onAction="MangezDesFruits" label="Banane" id="BDCBanane"/>
A savoir : dans un ruban, il est interdit d'avoir deux éléments avec le même id. Deux boutons qui s'appelleraient BDCFruit provoqueraient une erreur.
Ensuite, dans vba, ajoutez la procédure de rappel suivante :
Sub MangezDesFruits(MachinChouette As IRibbonControl) MsgBox "C'est bien de manger des fruits !" End Sub
Comme d'habitude, fermez la base, rouvrez-là, et rouvrez votre formulaire. Il n'y a pas besoin de s'occupper du ruban de formulaire, puisque vous l'avez déjà défini à Premier Clic Bouton, et nous nous sommes contenté d'améliorer ce ruban en ajoutant deux boutons, qui ont la particulaité d'appeler le même CallBack : MangezDesFruits. Ainsi lorsque vous cliquez sur le bouton Banane ou Fraise, il vous félicite pareillement de manger des fruits.
Du coup, c'est un peu bête d'avoir deux boutons qui font la même chose !
Regardons le paramètre MachinChouette. En fait, cette variable contient la référence au bouton sur lequel vous avez cliqué. Et ça va nous permettre d'affiner les choses !
Retournez dans VBA, et écrivez :
Pas besoin de fermer votre formulaire, ni la base de données : le VBA est immédiatement disponible, c'est le XML des rubans qu'il est nécessair de recharger à chaque changement en fermant et en rouvrant tout.
Cliquez sur Banane : vous allez avoir deux messages, et sur Fraise également :
On peut ainsi récupérer l'id, mais aussi une autre propriété : Tag (étiquette). Modifiez votre XML de cette manière :
XML... <button id="BDCTestCallBack" label="Clique-moi!" onAction="TralalaYoupi"/> <button id="BDCBanane" label="Banane" onAction="MangezDesFruits"/> <button id= "BDCFraise" label= "Fraise"tag= "Attention à l'urticaire"
onAction= "MangezDesFruits"/> ...
Modifiez votre VBA comme suit :
VBASub MangezDesFruits(MachinChouette As IRibbonControl) MsgBox MachinChouette.Id MsgBox MachinChouette.Tag End Sub
Tag est donc un simple petit texte qu'on peut passer en paramètre à VBA, sans plus. Nous verrons plus tard qu'il peut être vraiment très utile.
Si vous cliquez sur le bouton Banane, le message machinChouette.Tag restera vide, mais il n'y aura pas d'erreur. Attention : c'est très bizarre, mais dans XML, tag doit commencer par une minuscule, et dans VBA, il vous impose la majuscule.
Petit manque : vous ne pouvez pas, dans VBA utiliser les autres paramètres. Par exemple MsgBox MachinChouette.Label donnera une erreur au lieu de vous afficher Fraise ou Banane.
Il est possible d'appeler une macro (ou une sous-macro) à la place d'une procédure Sub, lorsqu'on clique sur un bouton du ruban.
Commencez par créer une macro qui va afficher une boîte de message (Zonemessage) "Je suis dans la macro", que vous appellerez M_MacroTestCallback (ce n'est pas un mot réservé, vous auriez pu l'appeler "J'aime les pommes", ça marcherait tout aussi bien) :
Maintenant, vous allez créer une 2ème macro, mais qui contient deux sous macros (TestSousMacro et AutreTestSousMacro). Chacune de ces deux sous-macros affiche un message tout bête, et vous appelerez la macro qui contient les deux sous macros : M_PlusieursSOusMacros, comme ceci :
Maintenant, vous allez dans USYSRibbon, et vous allez créer ce nouveau ruban :
RibbonName : Utilisation de macros
Ribbon XML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Appel macros"> <group id="GRP"> <button id= "BDC1" label= "Macro simple" onAction= "M_MacroTestCallback"/> <button id= "BDC2" label= "Première sous-macro" onAction= "M_PlusieursSousMacros.
TestSousMacro"/> <button id= "BDC3" label= "Deuxième sous-macro" onAction= "M_PlusieursSousMacros.
AutreTestSousMacro"/> </group> </tab> </tabs> </ribbon> </customUI>
Ensuite, comme d'habitude, fermez et rouvrez votre base de données, allez dans votre formulaire F_RubanTest, et définissez le nom du ruban de votre F_RubanTest à Utilisation de macros. Lancez votre formulaire, et cliquez sur les différents boutons de votre nouvel onglet : Les macros sont bel et bien appelées :
Le gros désavantage des macros est que vous vous ne pouvez apparemment pas exploiter les paramètres, comme dans VBA, vous vous souvenez ? :
Enfin, je suppose qu'on ne peut pas les exploiter. Pour vous parler franchement, comme je ne suis vraiment pas un fan des macros, je n'ai pas énormément fouillé pour trouver la possibilité de le faire.
Nous avons vu comment créer des boutons qui appellent des Sub ou des Macros personnalisées. Au tout début de ce didacticiel, lorsque nous avons créé un bouton personnalisé dans le ruban général Access, nous avions créé un bouton rattaché à une fonction bien définie (Enregistrer, dans cet exemple).
Nous pouvons faire de même avec notre code XML. Créez ce nouveau ruban dans USYSRibbons :
RibbonName : Test de idMso (idMso = Identification Microsoft Office)
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="TABBoutonMSO" label="Bouton idMso">
<group id="GRPBoutonMSO">
<button idMso="FileSave
"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Comme toujours, fermez la base de données, rouvrez-là, et définissez Test de idMso comme nom de ruban de F_RubanTest.
Et voilà : votre bouton d'enregistrement est bel et bien là. Bon, si vous cliquez dessus, ça ne va pas faire grand chose, ça va juste enregistrer votre formulaire. Pour que ce soit probant, il faudrait :
Vous constatez certainement avec moi que tous ces tests de ruban sont un peu pénibles. Aussi, je vais vous poposer de rationnaliser quelque peu la chose ! L'idée est de créer un formulaire en double-affichage, basé sur la table USYSRibbons. Et dès qu'on double-clique sur un ruban, hop : le ruban s'exécute.
Avant toute chose, ajoutez un nouveau champ CommentairePerso dans USYSRibbons, en mémo. ça vous permettra d'annoter les différents rubans que vous allez tester. (très pratique) :
N'hésitez donc pas à annoter les différents rubans que nous allons créer en utilisant ce champ, expressément créé pour ça !
Fermez la table, et créez un formulaire en double affichage, comme ceci :
Allez en mode création de ce formulaire, et double cliquez sur le champ RibbonName afin d'obtenir ses propriétés sur la droite de l'écran. Dans l'onglet Evénements, choisissez Sur Double clic, et cliquez sur les trois petits points, puis sélectionnez Générateur de code, et copiez-y le code suivant :
Me.RibbonName = Me.Controls("RibbonName").Value
Ca veut dire que quand on double-clique sur un RibbonName, le RibbonName sur lequel on vient de cliquer (Me.Controls("RibbonName").Value
) (Ruban des fruits, ruban des légumes, etc.) va devenir automatiquement la propriété RibbonName (Nom du ruban) du formulaire (Comme si vous le faisiez à la main, sauf que maintenant, c'est quand même carrément plus pratique)
Testez : Lancez votre formulaire en mode saisie de données, et double-cliquez sur vos différents rubans : vous verrez qu'il s'affiche immédiatement :
Attention : il y a tout de même une grosse limitation : ça marche très bien tant que vous vous contentez de double-cliquer sur les différents rubans qui sont déjà en mémoire. Mais si vous modifiez le code XML d'un ruban, son RibbonName, ou que vous en créez un nouveau directement dans ce formulaire, vous aurez beau double-cliquer tant que vous voulez, le nouveau ruban, ou le ruban modifié ne s'affichera pas. Vous pouvez bien entendu modifier, supprimer ou créer tout ce que vous voulez directement dans le formulaire : ça va correctement se répercuter dans la table USYSRibbons, mais vous devrez, comme d'habitude, fermer et rouvrir la base ded onnées, ainsi que le formulaire pour, enfin, pouvoir double-cliquer sur vos nouveaux rubans.
Maintenant, je vous propose de simplement relooker votre formulaire pour qu'il soit le plus convivial possible. Commencez par supprimer la disposition des trois champs, afin de pouvoir déplacer à la main les champs comme vous voulez (Sélectionnez .les 3 champs d'un coup, pas seulement RibbonName comme sur l'îllustration.
Voici un exemple de présentation :
Bon, le sujet de ce didacticiel est "Les rubans", pas "Le relooking d'un formulaire". Aussi, je vous propose de télécharger directement cette base de données qui contient la table USYSRibbons, tous les rubans que nous avons créé jusque-là, ainsi que ce formulaire F_USYSRibbons relooké comme sur l'image.
J'en ai profité pour demander à ce que ce formulaire F_USYSRibbons soit automatiquement ouvert au démarrage de la base de données (Outils/Options, et Base de données active : Afficher le formulaire F_USYSRibbons)
Dans cette base de données, vous trouverez également différentes tables qui nous seront utiles par la suite :
Nous avons vu, juste ici plus haut, comment installer un bouton prédéfini (<button idMso="FileSave"/>
).
Vous avez ainsi la possibilité de mettre n'importe quel bouton prédéfini dans vos rubans. Mais comment savoir quel bouton prédéfini possède quel nom ? FileSave, c'est facile, mais quel bouton permet, par exemple, de faire apparaître les petites jumelles pour rechercher du texte
Pour ce faire, vous allez dans Fichier/Options/Personnaliser le ruban, et vous positionnez votre souris, sans cliquer, sur l'icone désirée. Au bout d'une seconde, une petite infobulle apparait avec l'idMso correspondant :
Testez : modifiez le ruban test de idMso directement dans votre formulaire, comme ceci :
Ensuite, comme vous avez modifié un ruban existant, il ne suffit pas de double cliquer sur Test de idMso, mais il vous faut donc d'abord fermer et rouvrir votre base de données.
Ensuite, dans F_USYSRibbons, double-cliquez sur Test de idMso, et voici votre deuxième bouton, sur lequel vous pouvez cliquer :
Existe-t-il quelque part une liste de tous les idMso ? Oui. Si vous ouvrez la table T_imageMsoidMso, vous les découvrirez :
Attention : c'est une table que j'ai créé après avoir effectué pas mal de recherches sur internet pour glâner ce genre d'information, mais rien n'assure qu'elle soit à jour, complète, et je ne sais même pas si c'est la liste Access 2007 ou 2010. J'ai parfois été découragé devant le travail de fourmi que ce genre de recherche constitue.
Tous ces idMso ne sont pas forcément des boutons. Certains peuvent être d'autres genres de contrôles (que nous n'avons pas encore étudié). Par exemple, Font est un idMso qui représente la liste des polices de caractères.
Modifiez votre ruban Test de idMso comme ceci :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TABBoutonMSO" label="Bouton idMso"> <group id="GRPBoutonMSO">
<button idMso="FileSave"/> <button idMso="FindDialog"/> <button idMso="Font
"/></group> </tab> </tabs> </ribbon> </customUI>
Fermez et rouvrez votre base de données, et double-cliquez sur Test de ruban. Un message d'erreur survient :
Nous pouvons connaître le type réel de chaque idMso (ici, combobox d'après le message d'erreur) en allant dans la table T_IDMsoEmplacementMenu :
Cette table est très sympathique car elle permet de connaître tousles endroits prédéfinis ou se situe cette combobox (Liste déroulante) Font. Dans 6 endroits différents : dans l'onglet "accueil" (TabHomeAccess), dans le groupe "GroupTextFormatting" (Mise en forme du texte)., mais aussi par exemple ici (Je suis en mode création d'un formulaire quelconque) :
Maintenant, nous allons pouvoir affiner notre ruban Test de idMso en attribuant le bon type de contrôle, comme ceci (faites toujoures très attention aux majuscules et minuscules : comboBox - et pas Combobox, ni ComboBox, ni combobox):
XML... <group id="GRPBoutonMSO">
<button idMso="FileSave"/> <button idMso="FindDialog"/> <comboBox
idMso="Font"/></group> ...
Fermez, rouvrez, constatez : il n'y a plus d'erreur, et la police de caractère est sélectionnable dans la liste déroulante. Par contre, c'est Access qui décide si tel contrôle (bouton, liste déroulante, case à coocher, ...) est disponible ou pas, ce n'est pas vous. Par exemple, Microsoft a jugé bon de désactiver tous les contrôles de mise en forme de la police de caractère dans un formulaire en mode Formulaire, mais ces mises en forme sont actives et possibles dans la partie du bas du formulaire "double affichage", comme sur le schéma ci-dessous.
Ce que je veux dire par là, c'est que nous somnmes complètement sous la houlette de Microsoft : pas question d'activer expressément un idMso si Microsoft a décidé qu'il ne devait pas être actif. Dans certains cas, on peut comprendre : par exemple, c'est tout à fait logique que le bouton Enregistrer soit grisé s'il n'y a aucune table ni formulaire d'ouvert. Par contre, le fait que ces mises en forme de polices ne soient pas disponibles en tout temps dans un formulaire me parait bizarre, mais bon, c'est ainsi.
Plus d'informations dans le chapitre "Activation et visibilité"
Afin d'éviter d'avoir a réfléchir sur le type d'idMso, vous pouvez mettre control, comme ceci (Access déterminera lui-même quel contrôle afficher :
XML... <group id="GRPBoutonMSO">
<control
idMso="FileSave"/> <control
idMso="FindDialog"/> <control
idMso="Font"/></group> ...
Il n'est pas possible de redéfinir les actions prédéfinies. par exemple, admettons que quand on clique sur les jumelles, vous ne voulez pas que ce soit la boîte de dialogue standard "rechercher et remplacer" qui s'ouvre, mais un formulaire de votre cru, parce que vous êtes très fort en conception de formulaire de recherche (admettons)
Essayez : modifiez votre code XML comme suit :
XML... <group id="GRPBoutonMSO">
<control idMso="FileSave"/> <button
idMso="FindDialog" onAction="BDCFindDialog_onAction
"/> <control idMso="Font"/></group> ...
J'ai indiqué un nom de procédure de rappel un peu moins fantaisiste que TralalaYoupi (Vous vous rappelez ?): Je précise BDC (Bouton De Commande), suivi de l'id (ou ici, l'idMso : FindDialog), j'ajoute un _ et je termine par onAction pour me rappeler que c'est ce qui va se passer quand je clique sur ce bouton (nous étudierons plus tard des CallBack qui ne sont pas des onAction)
Ensuite, créez un nouveau module VBA , et recopiez-y cette procédure CallBack :
VBASubBDCFindDialog_onAction
(ElementRuban As IRibbonControl) MsgBox "Je remplace la boite de dialogue Rechercher/remplacer" End Sub
Evidemment, à la place du MsgBox, il faudrait la commande DoCmd.OpenForm pour ouvrir le formulaire de recherche qui remplacerait avantageusement la boîte de dialogue rechercher-remplacer, mais ce n'est absolument pas le sujet de ce didacticiel. Nous allons donc nous contenter d'un simple petit MsgBox. Enregistrez votre module (vous savez comment faire ?) sous P_TestDeidMso (Pour s'y retrouver, je vous propose de donner le même nom a votre module qu'a votre ruban, sauf que les noms de modules n'acceptent pas les espaces.
Fermez et rouvrez votre base de données, double-cliquez sur votre ruban test de idMso, et cliquez sur votre bouton .
Oups ! Ca ne fonctionne pas ! Il continue d'afficher la boîte de dialogue Rechercher-Remplacer par défaut, et il ne nous affiche pas notre MsgBox. Le plus troublant est qu'aucune erreur n'est générée.
Pour que ça fonctionne, nous devons créer un bouton personnalisé qui ressemble à s'y méprendre à ce bouton prédéfini. Nous allons utiliser une nouvelle propriété : imageMso. Il est possible d'utiliser toutes les images des boutons prédéfinis pour les réutiliser à notre sauce.
Corrigez votre code comme suit :
XML... <group id="GRPBoutonMSO">
<control idMso="FileSave"/> <button idMso="FindDialog"/><button id= "RecherchePerso"
label= "Rechercher"
imageMso= "FindDialog"
onAction= "BDCFindDialog_onAction"/>
<control idMso="Font"/></group> ...
Fermez et rouvrez la base de données, double-cliquez sur Test de idMso : vous avez maintenant deux fois exactement le même bouton Rechercher l'un en dessous de l'autre, mais celui du haut est le bouton prédéfini, celui du bas est le personnalisé :
Maintenant, il est possible de redéfinir les commandes prédéfinies idMso, mais il faut pour ça utiliser une autre technique : commands.
Créez un nouveau ruban : RibbonName : Redéfinition idMso
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"><!-- Redéfinition de quelques idMso : *********** -->
<commands><command idMso="FindDialog" onAction="CMDFindDialog_onAction"/>
</commands><!-- Ruban : ************************************ -->
<ribbon> <tabs> <tab id="TAB" label="Redéfinition idMso"> <group id="GRP"> <button idMso="FindDialog"/> </group> </tab> </tabs> </ribbon> </customUI>
Avant la création du ruban, nous redéfinissons les commandes idMso qui nous intéressent. Ainsi, à la limite, on n'est même pas obligé d'avoir une section <ribbon> : partout ou vous cliquerez sur les petites jumelles, le code VBA que nous allons créer va s'exécuter en lieu et place de l'affichage de la boîte de dialogue Rechercher/remplacer (Vous vous rappelez quand je vous ai expliqué qu'un même bouton idMso pouvait se situer dans différents rubans prédéfinis ?).
Créez un nouveau module VBA dans lequel vous placez ce code :
VBASub CMDFindDialog_onAction(ElementRuban As IRibbonControl, StopperIci) MsgBox "J'intercepte tous les boutons rechercher/remplacer" StopperIci = True End Sub
Enregistrez ce Module sous P_RedefinitionidMso :
Maintenant, fermez et rouvrez votre base de données, double-cliquez sur votre nouveau ruban Redéfinition idMso. Ensuite, cliquez sur l'un ou l'autre des boutons rechercher, dans les deux cas, c'est notre CallBack qui prend la priorité :
Jusqu'ici, nous nous sommes contentés de rajouter de nouveaux onglets au ruban existant. Or, il est possible d'effacer tous les onglets à part celui ou ceux que nous élaborons.
Créez un nouveau ruban : RibbonName : Ruban depuis zéro
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"><ribbon
startFromScratch="true"
> <tabs> <tab id="TAB" label="Onglet tout seul"> <group id="GRP"> <button id="BDCToutSeul" label="Je me sens seul"/> </group> </tab> </tabs> </ribbon> </customUI>
Testez-le (Comme toujours, fermez et rouvrez votre base de données, mais vous le savez maintenant, je vais arrêter de vous le répéter)
Voilà : startFromScratch="true" est le paramètre de <ribbon> qui permet de recommencer un ruban depuis zéro. Constatez deux choses :
Cette barre d'outils peut s'afficher au choix en haut ou en bas du ruban, et peut se personnaliser tout comme n'importe quel ruban :
Bien entendu, personnaliser la barre d'outils de cette manière affectera simplement votre Access de manière globale, tout comme la personnalisation des rubans que nous avons vu au début.
Voici comment personnaliser la barre d'outils :
Créez un nouveau ruban : RibbonName : Barre d'outils d'accès rapide
Il est obligatoire de startFromScratch="true", sinon une erreur surgira.
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="true
"> <qat> <sharedControls><control idMso="FileSave"/> <control idMso="Font"/> <button id="BDC1" imageMso= "_1" /> <button id="BDC2" imageMso= "_2" /> </sharedControls> </qat> </ribbon> </customUI>
Les imageMso appelés "_1", "_2", jusqu'à "_9" sont très pratiques pour les tests : ils affichent simplement un gros numéro sur le bouton.
Puisque vous avez imposé la personnalisation de cette barre d'outils, il est maintenant impossible de la "sur-personnaliser" avec la petite flèche :
Je n'ai aucune idée du pourquoi il est nécessaire d'inclure une balise <sharedControls> dans la <qat>, mais ce que j'ai compris, c'est qu'il est possible de créer une autre section en dessous (<documentControls>).
Créez un nouveau ruban que vous appelerez Barre d'outils 2 sections
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="true"> <qat> <sharedControls> <button id="BDC1" imageMso= "_1" /> <button id="BDC2" imageMso= "_2" /> </sharedControls><documentControls>
<button id="BDC3" imageMso= "_3" /> <button id="BDC4" imageMso= "_4" /></documentControls>
</qat> </ribbon> </customUI>
Je ne comprends pas l'utilité de ces sections, si ce n'est qu'une petite barre de séparation verticale est apparue entre le bouton 2 et le 3.
Nous n'avons pas encore vu comment créer des listes déroulantes personnalisées, mais je vous préviens déjà que dans la barre d'outils d'accès rapide, elles sont interdites (On peut seulement mettre des boutons et des Boutons-bascules, que nous verrons plus tard). les seules listes déroulantes possibles sont les idMso prédéfinis, tels que "Font".
Nous avons vu quelques images (_1, _2, _3, ..., FindDialog). Ces images sont compilées dans la table T_imageMsoidMso qui se trouve dans la base de données que vous avez téléchargé. Vous pouvez également visualiser les imagesMso en allant dans la personnalisation du ruban.
Je vous propose de visualiser toutes les imageMso de façon très conviviale, comme ceci :
Marche à suivre :
Commencez par télécharger ce fichier XML qui contient un ruban, qui contient lui-même toutes les imageMso (Clic droit, enregistrer sous, et mettez-le dans le même dossier que votre base de données). ce ruban est tellement volumineux que vous ne pouvez pas simplement copier-coller son contenu dans un nouvel enregistrement de la table USYSRibbons : il s'agit donc de charger ce ruban dès l'ouverture de la base de données, grâce à une fonction VBA appelée par la macro AutoExec (Vous vous souvenez ?).
Actuellement, votre macro Autoexec appelle la fonction ImportationRubanDessert(), Allez dans le module VBA P_ChargementRubans, et a modifiez-là comme suit :
VBAFunction ImportationRubanDessert()Dim GestionFichier As New FileSystemObject
Dim BoiteABiscuits As TextStream
Set BoiteABiscuits = GestionFichier.OpenTextFile(CurrentProject.Path & "\Bons biscuits.xml", ForReading)
Application.LoadCustomUI "Les Friandises", BoiteABiscuits.ReadAll
' Chargement d'un ruban permettant l'affichage de toutes les imageMso :
Dim ListeImageMso As TextStream Set ListeImageMso = GestionFichier.OpenTextFile(CurrentProject.Path & "\ImageMso.xml", ForReading) Application.LoadCustomUI "Liste des imageMso", ListeImageMso.ReadAll End Function
Comme ce ruban n'est pas dans USYSRibbons, vous ne pouvez pas simplement aller dans F_USYSRibbons pour double-cliquer dessus.
Aussi, nous allons définir ce ruban comme ruban général de la base de données. (Vous vous souvenez ?)
Maintenant, lorsque vous fermez et rouvrez votre base de données, vous disposez d'un onglet vous permettant de visualiser toutes les icones dans deux tailles différentes (16X16 pixels et 32X32 pixels), comme ceci :
Ce qui serait bien, ce serait que, quand on clique sur chacune des images, un petit message nous informant de la dénomination de l'imageMso apparaisse, comme ceci :
Pour ce faire, nous allons ajouter une procédure CallBack à chaque fois qu'on clique sur une icone. Si vous avez la curiosité d'ouvrir le fichier ImageMso.xml que vous avez téléchargé, vous verrez qu'une procédure est déjé prévue (mais vous ne l'avez pas encore créée dans VBA) :
XML... <group id="rxgrp16by16"
label="imageMso 16 x 16">
<gallery
id="rxgal16161"
label="imageMso A to E"
imageMso="PhotoAlbumInsert"
showItemLabel="false"
itemWidth="16"
itemHeight="16"
supertip="Click here to expand the imageMso list from A to E."
columns="10"
onAction="AfficherImageMso
">
<item id="B" imageMso="B" label="B" screentip="B"/>
<item id="BehindText" imageMso="BehindText" label="BehindText" .../> <item id="BibliographyAddNewPlaceholder" imageMso="BibliographyAddNewPlaceholder" .../>
<item id="BibliographyAddNewSource" imageMso="BibliographyAddNewSource" .../> ...
Il s'agit d'un contrôle gallery (qui est une sorte de liste déroulante de boutons, mais nous l'étudierons plus tard). Tout ce que vous devez faire pour l'instant, c'est créer un nouveau module VBA que vous appellerez P_ListeTouteImageMso, dans lequel vous recopierez cette procédure :
Sub AfficherImageMso(ElementRuban As IRibbonControl, IdSelection, IndexSelection) InputBox "L'ImageMso sélectionné est :", "Images Microsoft Office", IdSelection End Sub
Et voilà ! Normalement, vous devriez maintenant pouvoir cliquer sur chaque image pour obtenir son imageMso.
Si vous n'y arrivez pas, ou si tout simplement vous n'avez pas envie de le faire, je suis tellement gentil que je vous propose de télécharger la base de données telle qu'elle est à cette étape du didacticiel (et donc avec ce ruban). Par contre, ça ne vous dispense pas de télécharger tout de même le fichier XML dans le même dossier !
Les images sur les boutons peuvent se décliner en 3 tailles : 16X16(pixels), 32X32 ou 48X48, selon la manière dont ils se présentent :
Nous étudierons la personnalisation du menu fichier plus tard, mais pour le moment, voici comment afficher les images en 16X16 et en 32X32 :
Créez un nouveau ruban dans F_UsysRibbons (RibbonName = Tailles d'images)
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="TAB" label="Tailles d'images"> <group id="GRP" label="Tailles"> <button id="BDC1" label="Taille non précisée" imageMso="FileSave"/> <button id="BDC2" label="Petit" imageMso="FileSave"size="normal"
/> <button id="BDC3" label="Grand" imageMso="FileSave"size="large"
/> <button id="BDC4" label="Petit" imageMso="Bold" size="normal"/> <button id="BDC5" label="Grand" imageMso="Bold" size="large"/> </group> </tab></tabs>
</ribbon>
</customUI>
Lorsque vous ne précisez pas la taille, il décide de vous afficher l'icone en 16X16 (normal), sinon, il faut que vous précisiez que vous désirez du 32X32 (large). Le 32X32 est la plus grande taille possible pour le ruban : entre les espaces ajoutés sur les côtés de l'icone, ainsi que le texte de label, une icone 32X32 prend en fait la taille en hauteur de 3 petites icones. Certaines imageMso sont manifestement prévues pour être affichées en plusieurs tailles (FileSave reste une belle icone en 16X16 comme en 32X32), mais d'autres (j'ignore lesquelles), comme Gras (Bold), qui sont des icones qui s'affichent très bien en 16X16, mais qui sont toutes floues, avec des bords "en escalier" en 32X32.
Il est possible de créer vos propres images, au lieu de vous contenter des imageMso proposées. Mais attention : ça suppose que vous disposez d'un programme de dessin (Comme Paint, photoshop, The Gimp, ou un autre), que vous maîtrisez quelque peu.
Je ne vais donc pas m'embarquer dans un cours de graphisme sur ordinateur, car ça sortirait carrément du sujet.
Les trois formats possibles pour la création de vos icones personnalisées sont .GIF, .JPG et .PNG. L'avantage du GIF et du PNG est que ces formats permettent de jouer avec la transparence, mais ne brûlons pas les étapes !
Avant tout, je vous propose de télécharger
ce fichier images.zip, et d'extraire les images qu'il contient dans le même dossier que votre base de données :
Ce sont de simples images de fruits, en différentes tailles, et en différents formats : il y a des bananes , des fraises
et des pommes
en 32X32 pixels mais également en
16X16 pixels, eet même en
48X48 pixels. Il y a également ces mêmes images en format JPG pour montrer le fond blanc
qui apparait à la place du fond transparent, et finalement un gros fichier rectangulaire (IMGPommeRectangleTropGrand.jpg :
Ensuite, créez un nouveau ruban dans F_USYSRibbons :
RibbonName : Image perso
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="image importée"> <group id="GRP"> <button id= "BDCBanane" size= "large"image= "C:\Mes documents\IMGBanane32X32.jpg"/></group> </tab> </tabs> </ribbon> </customUI>
Malheureusement, ce XML ne fonctionne pas aussi simplement ! Si vous exécutez ce ruban, vous serez gratifié de ce message d'erreur :
Il y a deux manières de régler le problème
Première manière : commencez par modifier votre ruban comme suit :
XML<customUI xmlns= "http://schemas.microsoft.com/office/2009/07/customui"loadImage= "ChargementImageGlobaleRuban">
<ribbon> <tabs> <tab id="TAB" label="image importée"> <group id="GRP"> <button id= "BDCBanane" size= "large" image= "IMGBanane32X32.jpg
"/> <button id= "BDCFraise" size= "large" image= "IMGFraise32X32.jpg
"/> </group> </tab> </tabs> </ribbon> </customUI>
Ensuite, créez un nouveau module VBA, que vous appellerez P_ImagePerso, dans lequel vous copiez le code suivant :
Sub ChargementImageGlobaleRuban(NomDuFichierImage, ByRef image) MsgBox "Je charge l'image" & NomDuFichierImage Set image = LoadPicture(CurrentProject.Path & "\" & NomDuFichierImage) End Sub
Cette procédure CallBack va être appelée autant de fois qu'il existe d'attributs image dans le ruban (Deux fois dans notre exemple), non pas au moment ou vous allez double-cliquer sur votre ruban pour le charger, mais à l'instant ou vous cliquerez sur l'onglet image importée, comme sur ce schéma (Essayez) :
Comme le fond du ruban est gris clair, on ne se rend pas tout de suite compte du fond blanc qui entoure les fruits.
Cependant, lorsque vous passez la souris par dessus les boutons (sans cliquer), ce fond blanc apparaît cette fois dans toute sa splendeur :
Voyons maintenant ce que donnent les images lorsqu'elles s'affichent en formats différents (JPEG, GIF, PNG), mais aussi lorsqu'on les force à s'afficher dans des tailles non correspondantes :
Créez un nouveau ruban. RibbonName : Images perso 2
RibbonXML :
XML<customUI xmlns= "http://schemas.microsoft.com/office/2009/07/customui"loadImage= "ChargementImageGlobaleRuban">
<ribbon> <tabs> <tab id="TAB" label="Images différentes"> <group id="GRPFormatsJpgGifPng
"> <button id="BDCBananeJPG" size="large" label="jpg" image= "IMGFraise32X32.jpg
"/> <button id="BDCBananeGIF" size="large" label="gif" image= "IMGFraise32X32.gif
"/> <button id="BDCBananePNG" size="large" label="png" image= "IMGFraise32X32.png
"/> </group> <group id="GRPDimensionForcee
"> <button id="BDCBanane1632" size="normal
" image= "IMGFraise32X32
.gif"/> <button id="BDCBanane3216" size="large
" image= "IMGFraise16X16
.gif"/> <button id="BDCPommeRectangle" size="large
" image= "IMGPommeRectangleTropGrand
.jpg"/> </group> </tab> </tabs> </ribbon> </customUI>
Il y a donc deux groupes : le premier vous montre l'affichage des trois formats possibles, et le 2ème groupe vous montre comment Access fait pour afficher des images dans des dimensions différentes aux dimensions d'origine. loadImage= "ChargementImageGlobaleRuban" appelle la même procédure que le ruban d'avant, on n'y touche donc pas.
Testez votre ruban.
Oh oh... Un message d'erreur :
Le message d'erreur vient de VBA et pas du XML (pour une fois). Lorsque vous cliquez sur Débogage, la ligne incriminée s'affiche en jaune. Positionnez votre souris (sans cliquer) sur NomDuFichierImage, et une petite infobulle vous informe que c'est le fichier .png qui pose problème.
On ne peut apparemment pas utiliser comme ça les.png (Comme expliqué ici). Nous allons donc nous contenter des gif et des jpg.
Cliquez sur le petit carré bleu (Réinitialiser), et regardez votre ruban :
Je vous propose de supprimer le bouton de votre RibbonXML :
<button id="BDCBananePNG" size="large" label="png" image= "IMGFraise32X32.png"/>
Si vous désirez vraiment créer des images tansparentes, voyez ce didacticiel et celui-ci (Utilisation de GdiPlus et du format ICO sur Développez.com)
Voici maintenant l'autre manière de placer des images personnalisées sur les boutons :
Créez un nouveau ruban dans F_USYSRibbons. RibbonName : getImage
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Utilisation getImage"> <group id="GRP"> <button id="BDCBanane" size="large" getImage= "ChargerLaBanane
"/> <button id="BDCFraise" size="large" getImage= "ChargerLaFraise
"/> <button id="BDCPomme" size="large" getImage= "ChargerLaPomme
"/> </group> </tab> </tabs> </ribbon> </customUI>
Cette fois, chaque bouton appelle un CallBack différent.
Créez un nouveau module VBA que vous appellerez P_GetImage, dans laquelle vous installez les trois procédures de rappel suivantes :
Sub ChargerLaBanane(ElementRuban As IRibbonControl, ByRef image) Set image = LoadPicture(CurrentProject.Path & "\IMGBanane32X32.gif") End Sub Sub ChargerLaFraise(ElementRuban As IRibbonControl, ByRef image) Set image = LoadPicture(CurrentProject.Path & "\IMGFraise32X32.gif") End Sub Sub ChargerLaPomme(ElementRuban As IRibbonControl, ByRef image) Set image = LoadPicture(CurrentProject.Path & "\IMGPomme32X32.gif") End Sub
Testez, ça marche très bien :
Le seul hic, c'est qu'il est nécessaire de créer une procédure CallBack par image. Mais il y a une parade à ça !
Nous allons utiliser ElementRuban.Id. Nous allons créer une seule procédure qui va afficher telle ou telle image selon l'Id (BDCBanane, BDCFraise ou BDCPomme). Modifiez le XML de votre ruban comme suit :
XML...<group id="GRP">
<button id="BDCBanane" size="large" getImage= "ChargerLeFruit
"/> <button id="BDCFraise" size="large" getImage= "ChargerLeFruit
"/> <button id="BDCPomme" size="large" getImage= "ChargerLeFruit
"/></group>
...
Et remplacez les trois procédures CallBack ChargerLaBanane, ChargerLaFraise et ChargerLaPomme par l'unique procédure ChargerLeFruit :
VBASub ChargerLeFruit(ElementRuban As IRibbonControl, ByRef image) Select Case ElementRuban.Id
Case "BDCBanane" : Set image = LoadPicture(CurrentProject.Path & "\IMGBanane32X32.gif") Case "BDCFraise" : Set image = LoadPicture(CurrentProject.Path & "\IMGFraise32X32.gif") Case "BDCPomme" : Set image = LoadPicture(CurrentProject.Path & "\IMGPomme32X32.gif") End Select End Sub
Select Case est une instruction VBA qui veut simplement dire : "Selon le cas..." Ainsi, "Si le cas ElementRuban.Id est BDCBanane", on LoadPicture l'image de la banane. Si le cas ElementRuban.Id est BDCFraise, on charge l'image de la fraise, et pareil pour la pomme.
Vous pouvez tester. Le résultat est le même que si vous aviez trois procédures distinctes :
Tout comme avec loadImage, les images importées avec getImage seront importées à l'instant ou l'utilisateur cliquer sur l'onglet qui contient les images.
Il existe une solution encore bien plus élégante. Parmi les attributs possibles, il existe la propriété Tag, qui n'a pas de fonction particulière . c'est un simple texte qu'on peut utiliser pour passser des informations du bouton vers VBA.
Créez un nouveau ruban : Tag image
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Utilisation getImage"> <group id="GRP"> <button id="BDCBanane" size="large"tag
="IMGBanane32X32.gif" getImage= "FruitAvecTag"/> <button id="BDCFraise" size="large"tag
="IMGFraise32X32.gif" getImage= "FruitAvecTag"/> <button id="BDCPomme" size="large"tag
="IMGPomme32X32.gif" getImage= "FruitAvecTag"/> </group> </tab> </tabs> </ribbon> </customUI>
Créez ensuite un nouveau module VBA que vous appellerez P_TagImage, dans lequel vous copiez ce CallBack :
VBASub FruitAvecTag(ElementRuban As IRibbonControl, ByRef image) Set image = LoadPicture(CurrentProject.Path & "\" & ElementRuban.Tag) End Sub
Une seule instruction suffit : On demande à charger l'image qui se trouve dans le dossier CurrentProject.Path (le dossier de votre base de données, on y ajoute la barre oblique, et on y ajoute enfin ElementRuban.Tag qui contient à chaque fois le nom du fichier image.
Attention : Dans XML, tag s'écrit avec une minuscule, et dans VBA, il vous imposera une majuscule, c'est comme ça...
Le ruban affichera également les trois boutons avec les trois fruits correctement.
Il n'y a pas que les boutons dans la vie ! Nous avons la possibilité de placer bien d'autres choses dans nos rubans. Par exemple, des cases à cocher ou des boutons bascules (ils remplissent la même fonction : on peut cocher la case, ou enfoncer le bouton bascule : Dans les deux cas, ça veut dire "oui".
Nous avons étudié les boutons, et nous nous focalisons maintenant sur les cases à cocher et boutons bascules. Mais bien plus bas dans ce didacticiel, nous aborderons tous les autres contrôles possibles : Simple texte (labelControl), Liste déroulante (comboBox), Zone d'édition (editBox), Galerie d'icones (Gallery), Bouton liste déroulante (splitButton) et Menu (dynamicMenu).
Créez un nouveau ruban que vous nommerez Case à cocher et bouton bascule
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="TAB" label="Cases à cocher, boutons bascules"> <group id="GRP"><!-- BouTon Bascule : ***************** -->
<toggleButton
id= "BTBRetraite" size= "large" label= "retraité ?"/><!-- Case A Cocher : ***************** -->
<checkBox
id= "CACRetraite" label= "retraité ?"/> </group> </tab> </tabs> </ribbon> </customUI>
Exécutez ce ruban, et constatez que vous pouvez cliquer sur le bouton "retraité" (Il reste enfoncé - en orange), et vous pouvez cocher la case :
Il n'est pas possible d'avoir une grande case à cocher. L'attribut large ne fonctionne pas, de même qu'on pourra attribuer une image au ToggleButton, mais pas à la case à cocher.
Il est possible de préciser que le bouton doit être enfoncé (ou la case à cocher déjà cochée par défaut), mais malheureusement, ce n'est pas si simple : Ce XML ne fonctionne pas :
XML... <toggleButton id= "BTBRetraite" label= "retraite ?"pressed= "true"/><checkBox id= "CACRetraite" label= "retraité ?"pressed= "true"/>...
Nous sommes obligés de passer par un CallBack getPressed, comme ceci (essayez) :
XML... <group id="GRP"> <toggleButton id= "BTBRetraite" label= "retraite ?" getPressed= "ValeurDefautBoutonBascule"/> <checkBox id= "CACRetraite" label= "retraité ?" getPressed= "ValeurDefautCaseACocher"/> </group> ...
Créez un module VBA que vous appellerez P_CaseACocherBoutonBascule, dans laquelle vous copiez ces deux CallBack :
Sub ValeurDefautBoutonBascule(ElementRuban As IRibbonControl, EnfonceOuPas) EnfonceOuPas = True End Sub Sub ValeurDefautCaseACocher(ElementRuban As IRibbonControl, EnfonceOuPas) EnfonceOuPas = True End Sub
Testez et constatez que dès l'ouverture du ruban, le bouton est enfoncé, et la case est cochée sans que vous ayez besoin de cliquer : .
Tout comme nous l'avons vu au chapitre précédent, avec les images et le select case, nous pouvons resserer des deux CallBack en un seul, comme ceci :
XML... <toggleButton id= "BTBRetraite" label= "retraite ?" getPressed= "ValeurDefaut"/> <checkBox id= "CACRetraite" label= "retraité ?" getPressed= "ValeurDefaut"/> ...
VBASub ValeurDefautBoutonBascule(ElementRuban As IRibbonControl, EnfonceOuPas) EnfonceOuPas = True End Sub Sub ValeurDefautCaseACocher(ElementRuban As IRibbonControl, EnfonceOuPas) EnfonceOuPas = True End SubSub ValeurDefaut(ElementRuban As IRibbonControl, EnfonceOuPas) Select Case ElementRuban.Id Case "BTBRetraite": EnfonceOuPas=True Case "CACRetraite": EnfonceOuPas=False End Select End Sub
dans cet exemple, le bouton bascule sera activé, mais pas la case à cocher. Si vous avez un ruban composé de beaucoup de coutons bascules ou de cases à cocher, ce peut être une bonne idée de tout contrôler à l'aide d'un seul CallBack et d'un Select Case.
Lorsqu'on clique sur un simple bouton, l'appel au CallBack onAction est simple (vous vous rappelez ?). par contre, lorsque vous cochez une case à cocher, ou que vous enfoncé un bouton bascule, on voudrait que ce qui est exécuté soit différent selon qu'on coche ou décoche. Voici comment faire pour avoir un message "Vous venez de cocher" quand vous meettez la coche et "Vous venez de décocher" quand vous l'enlevez :
Créez un nouveau ruban que vous appellerez Action case à cocher
XMLRibbon :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="TAB" label="Actions sur cases à cocher"> <group id="GRP"> <checkBox id= "CACRetraite" label= "retraité ?" onAction= "ClicSurcaseACocher"/>/> </group> </tab> </tabs> </ribbon> </customUI>
Créez ensuite un nouveau module VBA que vous appellerez P_ActionCaseACocher, dans lequel vous copiez ce CallBack :
VBASub ClicSurcaseACocher(ElementRuban As IRibbonControl,Coche
As Boolean) IfCoche
= True Then MsgBox "Vous venez de cocher" Else MsgBox "Vous venez de décocher" End If End Sub
Le second paramètre (Coche, ou le nom que vous voulez) contient la valeur de la case à cocher. On peut ainsi faire telle ou telle action selon les cas. Vous pouvez tester.
Depuis le début de ce didacticiel, vous avez constaté que les Callback peuvent contenir des paramètres différents, comme dans les différents exemples que nouis avons étudié jusque-là :
Sub TRALALAyoupi(ViveLaVie As IRibbonControl)
Sub MangezDesFruits(MachinChouette As IRibbonControl)
Sub CMDFindDialog_onAction(ElementRuban As IRibbonControl, StopperIci)
Sub AfficherImageMso(ElementRuban As IRibbonControl, IdSelection, IndexSelection)
Sub ChargementImageGlobaleRuban(NomDuFichierImage, ByRef image)
Sub ChargerLa Banane (ElementRuban As IRibbonControl, ByRef image)
Sub ValeurDefautBoutonBascule(ElementRuban As IRibbonControl, EnfonceOuPas)
Comment fait-on pour savoir combien de paramètres sont obligatoires et quels sont-ils ?
Je vous propose d'abord de télécharger la base de données qui sert de base à ce didacticiel dans l'état actuel (Tous les exemples et exercices proposés jusque là y sont inclus)
Si vous ouvrez la table T_FonctionCallBack, vous trouverez toutes les syntaxes. Attention : c'est une liste glânée sur internet, modifiée par mes soins, mais je ne suis vraiment pas certain qu'elle soit complète, et je ne sais même pas si c'est Office 2007 ou 2010 (les infos sont difficiles à trouver, mais je n'ai peut être pas assez fouillé). Sur cette image, vous pouvez voir un exemple d'utilisation du clic sur une case à cocher, comme on l'a vu dans l'exemple précédent.
A la place de onAction ="ClicSurCaseACocher"
et Sub ClicSurcaseACocher(ElementRuban As IRibbonControl, Coche As Boolean)
, j'aurais très bien pu suivre l'exact modèle onAction ="onAction"
et Sub onAction(control As IRibbonControl, pressed As Boolean)
.
J'ai évoqué un peu plus haut dans ce didacticiel les avantages d'utiliser des noms de procédures plus normalisées (Vous vous souvenez ?). A partir de maintenant, je propose d'utiliser à chaque fois cette notation pour mieux s'y retrouver.
Pour l'instant, lorsqu'on coche une case dans le ruban, nous avons juste appris à afficher un simple message "Vous avez coché la case". Mais ce qui serait plus intéressant, ce serait que quand on coche une case dans le ruban, ça coche également une case dans un formulaire.
Pour faire ce test, vous avez à disposition une table T_Celebrite, qui contient simplement une centaine de personnes célèbres.
Commencez par créer un formulaire basée sur cette table, que vous enregistrerez sous F_Celebrite :
Le champ qui nous intéresse tout particulièrement est le champ "Decede" (Oui/Non dans la table).
L'idée est de cocher la case Decede du formulaire directement depuis un ruban.
Fermez F_Celebrite, et retournez dans F_USYSRibbons. créez un nouveau Ruban : RibbonName : F_Celebrite Case à cocher (Comme ça, on sait que c'est un ruban que nous allons exploiter dans F_Celebrite)
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="TAB" label="Ruban spécifique à ce formulaire"> <group id="GRP"> <checkBox id= "CACDecede" label= "Décédé ?" onAction= "CACDecede_onAction
"/> </group> </tab> </tabs> </ribbon> </customUI>
Ensuite, créez un nouveau module VBA que vous appellerez P_F_CelebriteCaseACocher, dans lequel vous mettez le CallBack suivant :
VBASub CACDecede_onAction(ElementRuban As IRibbonControl, Coche As Boolean) If Coche = True Then Forms!F_celebrite!Decede =True
Else Forms!F_celebrite!Decede =False
End If End Sub
Je pense que vous comprenez : Si la case du ruban est cochée, hop, on coche le champ Decede du formulaire, et sinon, on le décoche.
Mais a-t-on réeellement besoin de ce If ... Else ? Puisqu'en fait, si la Coche du ruban est à True (Coché), on coche la case à cocher Decede, et si elle n'est pas cochée, on la décoche. On peut réduire le code VBA en une seule ligne, en attribuant directement la valeur de la Coche à Decede, comme ceci :
VBASub CACDecede_onAction(ElementRuban As IRibbonControl,Coche
As Boolean) Forms!F_celebrite!Decede =Coche
End Sub
Ensuite, fermez et rouvrez votre base de données.
Retournez dans F_Celebrite en mode création, et définissez F_Celebrite Case à cocher comme ruban de ce formulaire :
Lancez votre formulaire en mode formulaire.
Et voilà le miracle qui s'accomplit : votre ruban s'affiche bien, avec votre case à cocher, et dès que vous cliquez sur la case à cocher du ruban, hop, la case à cocher du formulaire se coche et se décoche en même temps :
Attention : l'inverse n'est pas vrai du tout : Si vous cochez ou décochez diractement la case "Décédé ?" dans le formulaire, ça n'a aucune influence sur la case à cocher du ruban.
Autre problème : Si vous avez coché la case du ruban, non seulement, ça a coché (et donc modifié le champ existant), mais cette case du ruban reste cochée, même quand vous changez d'enregistrement, et nous avons alors une incohérence :
Commençons par régler le premier problème : il faut que, lorsque nous cochons ou décochons la case à cocher Decede du formulaire, la case à cocher du ruban suive le même mouvement.
Malheureusement, on ne peut pas simplement modifier la valeur de la case à cocher du ruban en allant sur l'événement Après MAJ de la case à cocher. Quelque chose de style :
ne fonctionne pas du tout.ElementRuban.CACDecede.Value = True
Nous allons toutefois nous assurer que c'est quand même bien dans cet événement que la mise à jour doit se passer. créez ce code VBA dans l'événement Après Mise à Jour de la case à cocher Decede :
Lancez le formulaire en mode saisie de données, et cochez et décochez la case Decede, afin de vous assurer qu'il vous informe correctement d'un petit message :
A la place de ces petits messages, nous allons devoir trouver une manière de cocher et décocher la case dans le ruban. Pour ce faire, nous allons Rappeler une 2ème fois getPressed (Du coup, on commence à comprendre pourquoi ça s'appelle procédure de rappel, ou CallBack). Vous vous souvenez de getPressed ? Dans l'exemple que je vous avais montré, il s'agissait de simplement imposer que la coche soit cochée.
Mais maintenant, nous allons plutôt lui imposer la valeur de la case à cocher Decede du formulaire.
Modifiez votre ruban F_Celebrite Case à cocher comme suit :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="TAB" label="Ruban spécifique à ce formulaire">
<group id="GRP">
<checkBox id= "CACDecede" label= "Décédé ?" getPressed= "CACDecede_getPressed
" onAction= "CACDecede_onAction"/></group>
</tab>
</tabs>
</ribbon>
</customUI>
Et dans votre module VBA P_F_CelebriteCaseACocher, ajoutez ce CallBack CACDecede_getPressed, comme ceci :
VBASub CACDecede_onAction(ElementRuban As IRibbonControl, Coche As Boolean)
Forms!F_celebrite!Decede = Coche
End Sub
Sub CACDecede_getPressed(ElementRuban As IRibbonControl, Coche)Coche = Forms!F_Celebrite!Decede
End Sub
Il ne faut surtout pas préciser que Coche est de type Booléen :
(Sub CACDecede_getPressed(ElementRuban As IRibbonControl, Coche
) empêche le bon fonctionnement, alors que pourtant Coche est bel et bien de type Booléen (C'est à dire qu'il peut juste contenir True ou False). J'ignore pourquoi ça pose un problème.as Boolean)
Remarquez qu'il est indispensable de préciser l'accès au formulaire. je veux dire par là que si on avait écrit
Coche = Decede
à la place de Forms!F_Celebrite!Decede
, ça n'aurait pas marché, car nous sommes dans un module VBA à part (pas dans un module du formulaire). D'ailleurs, en parlant de ça, vous ne pouvez pas non plus installer les procédures CallBack dans les modules VBA de formulaire.
Ceci n'aurait pas fonctionné :
Maintenant :
- Si sa case à cocher Decede est cochée, alors, la case à cocher de votre ruban est cochée
- Si sa case à cocher Decede n'est pas cochée, alors, la case à cocher de votre ruban est aussi décochée.
Il s'agit maintenant de faire en sorte que quand on coche ou décoche la case Decede du formulaire, ça coche/décoche la case à cocher du ruban. L'inverse était assez facile, vous vous souvenez ?
Ici, c'est une autre paire de manches. Voici comment il faut procéder : A chaque fois qu'on met à jour la case à cocher du formulaire (Donc à chaque fois qu'on clique dessus pour la faire changer d'état), nous allons devoir réexécuter CACDecede_getPressed
.
Mais on ne peut pas simplement appeler cette procédure après mise à jour. Par exemple, ceci ne marche pas du tout :
La seule façon de faire est de rappeler à chaque clic sur la case à cocher toutes les procédures CallBack liées à cette case à cocher.
En fait, il n'y a qu'une procédure CallBack : CACDecede_getPressed.
Mais selon les cas, il peut y en avoir plusieurs. Vous vous rappelez quand on a abordé l'importation d'images avec getImage ?
Ici, nous sommes dans le cas de cases à cocher, sans image, mais on pourrait très bien avoir un ToggleButton qui contient à la fois une procédure CallBack getImage et getPressed, comme ceci :
XML (Exemple juste pour vous montrer)<toggleButton id= "BTBVert" size= "large" label= "Aimez-vous le vert ?"getImage
= "ImportImage"getPressed
= "CocheOuPasCoche"/>
Ce que je veux dire par là, c'est que nous pourrons seulement réexécuter (rappeler) les deux procédure getImage et getPressed ensemble. Il sera impossible de n'en rappeler qu'une des deux.
Mais comment faire ce rappel ? Dès le chargement du ruban, nous allons devoir créer une variable publique (une variable lisible en tout temps, depuis n'importe quelle procédure VBA) qui va contenir la référence en ruban actuel.
Pour ce faire, il faut que nous créions une procédure CallBack onLoad du ruban (une procédure qui, comme son nom l'indique, sera exécutée une seule fois au démarrage du ruban). Modifiez le XML de votre ruban F_Celebrite Case à cocher comme suit :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"onLoad="F_CelebriteCaseACocher_onLoad">
<ribbon startFromScratch="false"><tabs>
<tab id="TAB" label="Ruban spécifique à ce formulaire">
...
Créez ensuite le VBA suivant (dans le même module que les autres) :
Ainsi, dès le démarrage du ruban, nous disposerons d'une référence au ruban (RubanCelebrite).
Maintenant, allez dans l'événement Après MAJ de la case à cocher Decede, et écrivez-y RubanCelebrite.Invalidate, comme sur ce schéma qui vous montre les choses en détail :
Ce terme (Invalidate) me paraît quelque peu mal choisi. ça suppose une notion d'invalidité, alors, qu'il s'agit plutôt d'une répétition, ou d'un rafraîchissement.
Vous avez la possibilité de ne rafraîchir les CallBack que d'un seul élément au lieu de tous les éléments du ruban (Dans notre cas, ça ne va rien changer puisqu'on en n'a qu'un de toute façon). Mais la syntaxe est alors : RubanCelebrite.InvalidateControl "CACDecede"
.
Toujours est-il qu'à présent, vous allez pouvoir cocher et décocher la case du focmulaire Decede, et constater que cette coche se répercute maintenant dans le ruban.
Passons maintenant au deuxième souci (plus simple a régler : lorsque vous passez à un enregistrement suivant (), les deux cases à cocher ne sont plus synchrones : en effet, c'est seulement lorsqu'on clique sur la case à cocher que Invalidate se met en marche. La solution est toute simple : appelez également la méthode Invalidate depuis l'événement Sur Activation sur formulaire, afin que dès qu'on change d'enregistrement (Ou même dès l'ouverture du formulaire, qui provoque également l'événement Sur Activation), la case à cocher du menu se mette au diapason de la coche du formulaire.
Voilà : Dès maintenant, vous pouvez aller sur n'importe quel enregistrement de votre formulaire, les deux cases à cocher seront toujours équivalentes. Nous avons donc géré :
Si vous n'avez pas fait l'exercice, ou que vous avez des erreurs, je vous invite à télécharger la version de la base de données telle qu'elle est à ce stade du didacticiel.
Lorsque nous aborderons les zones d'édition (EditBox), je vous proposerai un autre exercice a base d'invalidate.
Voici un autre exemple de rappel de fonctions : nous allons modifier carrément l'aspect du ruban à l'aide d'une case à cocher placée dans ce même ruban.
Lorsque nous cocherons ou décocherons une case à cocher, ça affichera ou masquera deux boutons, comme ceci :
Pour commencer, allez dans votre formulaire habituel F_USYSRibbons, et créez un simple ruban pourvu de la case à cocher et des deux boutons :
RibbonName : Affiche boutons
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="TAB" label="Afficher les boutons dynamiquement"> <group id="GRP"><!-- Case à cocher de contrôle de visibilité des boutons : -->
<checkBox id= "CACAfficheBouton" label= "Afficher les boutons ?"/><!-- Boutons visibles ou pas, selon la valeur de la case à cocher : -->
<button idMso= "FileSave" size= "large"/> <button idMso= "MasterViewClose" size= "large"/> </group> </tab> </tabs> </ribbon> </customUI>
Refermez votre base de données, rouvrez-là, et double-cliquez sur le nom de votre ruban pour l'activer : voici le résultat :
Maintenant, nous allons simplement rendre ces deux boutons invisibles.
Corrigez le code XML comme suit :
XML... <group id="GRP"> <checkBox id= "CACAfficheBouton" label= "Afficher les boutons ?"/> <button idMso= "FileSave" size= "large" getVisible= "BDC_getVisible"/> <button idMso= "MasterViewClose" size= "large" getVisible= "BDC_getVisible"/> </group> ...
Créez un nouveau module VBA que vous enregistrerez sous P_AfficheBoutons, dans lquel vous copiez cette procédure CallBack :
VBASub BDC_getVisible(ElementRuban As IRibbonControl, Visible) Visible = False End Sub
Voici le résultat : les deux boutons ont simplement disparu :
Nous allons faire en sorte que les boutons n'apparaissent QUE quand la case est cochée.
A la base, si on crée une case à cocher dans un ruban, et qu'on ne précise pas si elle est cochée ou pas avec getPressed (vous vous rappelez ?), elle n'est pas cochée par défaut : sa valeur est False.
Maintenant, nous allons devoir modifier notre VBA BDC_getVisible :
VBASub BDC_getVisible(ElementRuban As IRibbonControl, Visible) Visible = La valeur de la case à cocher CACAfficheBouton End Sub
Oui, mais ccomme on l'a vu précédemment, on ne peut pas aller piocher la valeur de la case éà cocher dans le ruban ! Ce serait trop simple !
Il faut qu'on commence par créer une procédure onLoad du ruban, afin d'obtenir la référence du ruban. Modifiez votre XML comme ceci :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="RUBAfficheBouton_onLoad"> <ribbon startFromScratch="false"> <tabs> <tab id="TAB" label="Afficher les boutons dynamiquement"> ...
Et modifiez votre VBA comme suit :
VBAOption Compare Database PublicVARRubanAfficheBouton
As IRibbonUI Sub RUBAfficheBouton_onLoad(Ruban As IRibbonUI) SetVARRubanAfficheBouton
= Ruban End Sub Sub BDC_getVisible(ElementRuban As IRibbonControl, Visible) Visible = False End Sub
Maintenant, nous devons mémoriser l'état de la case à cocher à chaque fois qu'on clique dessus dans une variable publique que nous appellerons VARCocheVisible
Modifiez votre code XML ainsi :
XML... <group id="GRP"> <checkBox id= "CACAfficheBouton" label= "Afficher les boutons ?"onAction= "CACAfficheBouton_onAction"/>
<button idMso= "FileSave" size= "large" getVisible= "BDC_getVisible"/> <button idMso= "MasterViewClose" size= "large" getVisible= "BDC_getVisible"/> </group> ...
Modifiez ensuite votre VBA comme suit :
VBAOption Compare Database Public VARRubanAfficheBouton As IRibbonUI Public VARCocheVisible As Boolean Sub RUBAfficheBouton_onLoad(Ruban As IRibbonUI) Set VARRubanAfficheBouton = Ruban End Sub Sub BDC_getVisible(ElementRuban As IRibbonControl, ByRef Visible) Visible = VARCocheVisible End Sub Sub CACAfficheBouton_onAction(ElementRuban As IRibbonControl, Coche) VARCocheVisible = Coche VARRubanAfficheBouton.Invalidate End Sub
Analysons ce code :
Ce sont deux variables publiques que nous allons voir comment utiliser :
Public VARRubanAfficheBouton As IRibbonUI Public VARCocheVisible As Boolean
Dès le chargement du ruban, une seule fois au début, nous transférons la référence du ruban dans notre variable publique VARRubanAfficheBouton. ça, c'est fait !
Sub RUBAfficheBouton_onLoad(Ruban As IRibbonUI) Set VARRubanAfficheBouton = Ruban End Sub
La procédure RUBAfficheBouton_onLoad s'exécute dès le chargement du ruban, sans qu'on aie a cliquer sur notre onglet personnalisé Afficher les boutons dynamiquement. Juste après, dès qu'on clique sur l'onglet personnalisé, boum, BDC_getVisible s'exécute carrément deux fois de suite, parce que les deux boutons (FileSave et MasterViewClose) appellent cette même procédure (Rappelez-vous le code XML : getVisible= "BDC_getVisible"). On précise que Visible (L'argument passé en paramètre qui va donc décider si le contrôle est visible ou pas) est égal à VARCocheVisible.
VARCocheVisible est donc une variable publique de type Boolean (Qui peut contenir True ou False) déclarée en début du module, mais nous ne lui avons pas attribuée de valeur. Du coup, elle vaut True ou False ? ... Comme on n'a rien dit, VBA pense que c'est donc False.
Ainsi, à la base, les deux images ne seront pas visibles :
Sub BDC_getVisible(ElementRuban As IRibbonControl, ByRef Visible) Visible = VARCocheVisible End Sub
Lorsqu'on clique sur la case à cocher pour la cocher ou la décocher, c'est CACAfficheBouton_onAction qui s'exécute à chaque fois. Le 2ème paramètre (Coche) contient la valeur de la case a cocher (True si vous venez de la cocher, et False si vous venez de la décocher).
Première chose : On envoie la valeur de Coche dans la variable publique VARCocheVisible (True si vous venez de cocher la case, et False si vous venez de la décocher, donc)
Et c'est ici que toute la subtilité entre en jeu : VARRubanAfficheBouton.Invalidate va forcer tous les contrôles à réeexécuter (rappeler) toutes leurs procédures de rappel qui commencent par get. Afin de pouvoir exécuter Invalidate, nous avons besoin de la référence au ruban : d'ou l'utilité de la variable publique VARRubanAfficheBouton qui a été initialisée lors de RUBAfficheBouton_onLoad
Dans notre cas, ce VARRubanAfficheBouton.Invalidate va donc réexécuter :
Et donc, comme nous attribuons la valeur de la case à cocher (True ou False) à la variable Publique VARCocheVisible, cette variable publique aura enfin une valeur que nous lui attribuons, et, de ce fait, les images vont être visible False ou True selon la valeur de la case à cocher :
Sub CACAfficheBouton_onAction(ElementRuban As IRibbonControl, Coche) VARCocheVisible = Coche VARRubanAfficheBouton.Invalidate End Sub
Afin de mieux vous rendre compte de la manière dont tout ceci fonctionne, je vous propose ceci :
Commencez par disposer Access et le formulaire F_USYSRibbon d'un côté de votre écran, et l'environnement VBA de l'autre, comme ceci :
Ensuite, dans VBA , faites apparaître la fenêtre d'exécution.
Disposez les fenêtres de manière à voir le code VBA et la fenêtre d'exécution en même temps :
On peut écrire toutes sortes d'informations dans cette fenêtre d'exécution, avec l'instruction Debug.Print.
Aussi, je vous propose de corriger votre code VBA de manière à afficher dans cette petite fenêtre les défférentes étapes de nos procédure CallBack. Corrigez votre code VBA de cette manière :
VBAOption Compare Database Public VARRubanAfficheBouton As IRibbonUI Public VARCocheVisible As Boolean Sub RUBAfficheBouton_onLoad(Ruban As IRibbonUI) Set VARRubanAfficheBouton = Ruban Debug.Print "Initialisation du ruban avec onLoad" End Sub Sub BDC_getVisible(ElementRuban As IRibbonControl, ByRef Visible) Visible = VARCocheVisible Debug.Print "BDC_getVisible : VARCocheVisible = " & VARCocheVisible End Sub Sub CACAfficheBouton_onAction(ElementRuban As IRibbonControl, Coche) VARCocheVisible = Coche VARRubanAfficheBouton.Invalidate Debug.Print "CACAfficheBouton_onAction : VARCocheVisible = " & VARCocheVisible End Sub
Ensuite, fermez et rouvrez votre base de données, assurez-vous d'avoir toujours Access d'un côté de votre écran, VBA et sa fenêtre exécution de l'autre, et regardez ce qui se passe lorsque vous double-cliquez sur votre ruban pour le charger, et que vous cochez et décochez votre case :
Si vous le désirez,. vous pouvez télécharger la base de données de ce didacticiel dans son état actuel en cliquant ici.
Créez un nouveau ruban dans votre formulaire F_USYSRibbon. RibbonName : Placement onglets
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="false"> <tabs> <tab id= "TABFruit" label= "Fruits"insertBeforeMso= "TabExternalData"
/> </tabs> </ribbon> </customUI>
Si vous fermez et rouvrez votre base de données, puis double-cliquez sur Activation et placement onglets, vous verrez votre onglet correctement placé ici (sans toutefois être automatiquement activé : vous devrez cliquer dessus pour voir son contenu - qui est de toute façon ... vide).
On peut utiliser insertBeforeMso ou InsertAfterMso. Si on ne précise aucun de ces deux paramètres, l'onglet sera placé tout à droite des onglets existants.
Il faut connaître la dénomination anglaise de tous les onglets existants pour pouvoir gérer les emplacements.
Voici les correspondances des onglets principaux :
Le menu Fichier (Appelé Mode BackStage, que nous verrons plus tard) est inamovible : on ne peut ni le masquer, ni ajouter d'onglets avant, ni le renommer.
TabHomeAccess | Accueil |
TabCreate | Créer |
TabExternalData | Données externes |
TabDatabaseTools | Outils de base de données |
Il existe bien d'autres onglets d'autres rubans prédéfinis (Lorsqu'on est en mode aperçu avant impression, ou lorsqu'on est en création de table), mais les onglets principaux sont les quatre que je viens de citer.
Si vous désirez connaître les noms de tous les autres onglets avec leur traduction en français, vous pouvez ouvrir la table T_ImageMsoIdMso, et dans la colonne de gauche, filtrer par le mot Tab :
Par contre, jignore comment (je ne suis même pas certain que ce soit possible) de déterminer qu'un certain onglet doit se placer avant ou après un autre onglet personnalisé. par exemple, dans notre base de données, si vous vous souvenez, nous avons défini un ruban général qui nous permet de visualiser toutes les imageMso (ici). Si on voulait insérer un nouvel onglet après, il suffirait de ne rien préciser, et si on voulait insérer un onglet avant, il faudrait alors préciser
insertAfterMso= "TabDatabaseTools"
.
On peut aussi masquer certains onglets prédéfinis. Corrigez votre XML du ruban Placement onglets comme suit :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id= "TABFruit" label= "Fruits" insertBeforeMso= "TabExternalData"/><tab idMso= "TabHomeAccess"
visible="false"/>
</tabs>
</ribbon>
</customUI>
L'onglet Accueil a disparu, et le 2ème onglet (créer) est donc actif par défaut:
Si nous désirons qu'un onglet particulier s'active au démarrage d'un ruban, c'est la méthode Activate qu'il faut exécuter sur onLoad.
Modifiez votre ruban XML comme suit :
XML<customUI xmlns= "http://schemas.microsoft.com/office/2009/07/customui"onLoad= "RUBPlacementOnglet_onLoad">
<ribbon startFromScratch="false"> <tabs> <tab id= "TABFruit
" label= "Fruits" insertBeforeMso= "TabExternalData"/> </tabs> </ribbon> </customUI>
Créez ensuite un module VBA que vous appellerez P_PlacementRuban, dans lequel vous copiez cette procédure CallBack :
VBASub RUBPlacementOnglet_onLoad(Ruban As IRibbonUI) Ruban.ActivateTab "TABFruit
" End Sub
Et voilà : dès le lancement du ruban, votre onglet sera actif/visible immédiatement :
Attention : c'est une nouveauté d'Office 2010. Ca ne fonctionne pas avec 2007.
Il est possible d'activer un ruban depuis un bouton sur votre formulaire, ou même depuis un bouton sur un autre de vos rubans. Admettons que le ruban Fruit s'affiche au démarrage (c'est ce que nous venons de faire), mais sur ce ruban fruit, nous allons installer un bouton "Afficher les légumes", qui va afficher un autre onglet "Légumes".
Commencez par modifier votre code XML de votre ruban Placement Onglet
XML<customUI xmlns= "http://schemas.microsoft.com/office/2009/07/customui" onLoad= "RUBPlacementOnglet_onLoad"> <ribbon startFromScratch="false"> <tabs> <tab id= "TABFruit" label= "Fruits" insertBeforeMso= "TabExternalData"> <group id="GRP"> <button id= "BDCChangeOnglet
" label= "Va sur onglet Légumes
"onAction= "BDCChangeOnglet_onChange"/>
</group> </tab> <tab id="TABLegume
" label="Légumes"/> </tabs> </ribbon> </customUI>
Le ruban a cet aspect :
Il faut maintenant programmer le bouton pour activer l'onglet légumes.
On a vu plus haut que nous avons besoin de la référence au ruban pour pouvoir utiliser la méthode Activate (Ruban.Activate). Aussi, nous allons initialiser une variable globale VARRubanFruitLegume depuis onLoad, afin de pouvoir l'utiliser sur le CallBack onAction du bouton. Modifiez votre VBA comme suit :
VBAOption Compare Database PublicVARRubanFruitLegume
As IRibbonUI Sub RUBPlacementOnglet_onLoad(Ruban As IRibbonUI) Ruban.ActivateTab "TABFruit" SetVARRubanFruitLegume
= Ruban End Sub Sub BDCChangeOnglet_onChange(ElementRuban As IRibbonControl)VARRubanFruitLegume
.ActivateTab "TABLegume" End Sub
Voilà : maintenant, le clic sur le bouton fonctionne :
Si votre but est de simplement limiter les actions possibles des utilisateurs de votre base de données (mais pas forcément de leur créer des boutons supplémentaires), il y a trois options :
1. Utiliser startFromScratch=True (Nous l'avons vu ici)
XML<customUI xmlns= "http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="true"/> </customUI>
Voici ce ruban réduit à sa plus spartiate expression :
2. Masquer les onglets prédéfinis comme nous venons de le voir
3. Aller dans outils/Options, à gauche : "Base de données active", et à droite dans la rubrique "Options de la barre d'outils et du ruban", décocher la case "Autoriser les menus complets"
Lorsque vous retirez la coche à "Autoriser les menus complets", et que vous fermez et rouvrez votre base de données, vous n'aurez plus alors qu'un seul onglet : Accueil :
L'onglet personnalisé qui a été défini dans le ruban par défaut de la base de données (Liste des images Mso) n'a pas été supprimé par le fait d'avoir ôté la case à cocher "Autoriser les menus complets".
Lorsque vous décochez "Autoriser les menus complets", le menu Fichier subit un sacré lifting : Regardez la différence :
Lorsque vous n'autorisez pas les menus complets, dans le menu fichier, vous avez juste les boutons Imprimer, Options de confidentialité et Quitter.
On pourrait penser que Options de confidentialité donne seulement accès à cette sous-section des options :
Que nenni ! Le bouton Options de confidentialité permet d'accéder à toutes les options d'Access, ecxactement comme le bouton Options quand on autorise les menus complets. Et vous pouvez donc sans problème vous réattribuer les menus complets. C'est un bug.
De toute façon, si vous désirez démarrer votre base de données en court-circuitant toutes les options de démarrage :
il vous suffit de maintenir la touche Majuscule (Shift ) (Attention PAS Caps Lock ni Verr MAJ) pendant que vous ouvrez votre base de données (Ne la relâchez que quand la base est ouverte).
Nous verrons plus tard comment personnaliser complètement ce menu Fichier (Mode BackStage), car ça mérite tout un chapitre..
Entre les différents onglets prédéfinis idMso que nous avons abordés juste avant (TabHomeAccess, TabCreate, TabExternalData, ...) et les contrôles idMso que nous avons abordés ici (boutons FileSave, FindDialog, MasterViewClose, Liste déroulante Font, ...), il y a les groupes prédéfinis idMso.
Nous allons donc pouvoir personnaliser notre ruban à outrance. Commençons par ajouter un groupe avec un bouton personnalisé à un onglet idMso existant.
Créez un nouveau ruban dans votre formulaire F_USYSRibbons : RibbonName : Personnalise groupe
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tabidMso
="TabHomeAccess"> <groupid
="GRPFruit" label="Fruits"> <button id="BDCPomme" label="Pomme" size="large"/> </group> </tab> </tabs> </ribbon> </customUI>
Ce ruban va afficher notre nouveau groupe tout à droite de l'onglet Accueil :
Etonnamment, il n'est pas possible de placer notre groupe personnalisé ailleurs que tout à droite dun onglet idMso.
par exemple :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab idMso="TabHomeAccess"> <group id="GRPFruit" label="Fruits"insertBeforeIdMso="GroupFindAccess"> <button id="BDCPomme" label="Pomme" size="large"/> </group> </tab></tabs>
</ribbon>
</customUI>
Ne fonctionne pas et crée une erreur. Pourtant, GroupFindAccess représente bien ce groupe :
On peut être interloqué, puisque juste avant, nous avons réussi à placer un onglet personnalisé a un emplacement précis des onglets.
Par contre, si on essaie de placer un onglet prédéfini idMso a un autre endroit que prévu, on n'a pas d'erreur, mais il se place quand même ou il est censé se placer à la base. On peut ainsi le renommer, mais pas le déplacer.
Créez un nouveau ruban dans F_USYSRibbons. RibbonName : Placement personnalise onglet idMso
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab idMso= "TabExternalData"label= "Les trucs d'ailleurs"
insertBeforeMso= "TabHomeAccess"/>
</tabs> </ribbon> </customUI>
Le ruban va correctement afficher le contenu de l'onglet TabExtarnalData (Données externes), en lui ré-attribuant le label "Les trucs d'ailleurs", mais il ne va pas le mettre à gauche de accueil, et aucune erreur ne sera générée :
Cette section n'est pas vraiment utile pour la personnalisation de votre application, mais elle sert à bien comprendre le système des groupes.
Pour connaître les noms de tous les groupes idMso, vous pouvez ouvrir la table T_ImagemsoIdMso, et vous pouvez filtrer le champ TabGroup par le mot Group. Et comme vous vous en doutez, vous pouvez filtrer pour le mot Tab afin d'avoir la liste de tous les onglets possibles.
Attention : vous ne pouvez pas afficher n'importe quel onglet prédéfini idMso.
Par exemple, impossible d'afficher l'onglet de création de table si on est en mode de saisie d'un formulaire. Ce ruban génèrerait une erreur :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"><ribbon> <tabs>
<tab idMso="TabFormToolsDesign"/></tabs> </ribbon> </customUI>
Il est possible que cette interdiction vienne du fait que TabFormToolsDesign soit un groupe qui fait partie d'un TabSet. Un tabSet est un ensemble de rubans contextuels. Par exemple, lorsque vous êtes dans un formulaire en mode création, un ensemble de trois nouveaux onglets apparaissent :
"Outils de création de formulaires" est un TabSet dont l'idMso est TabSetFormTools. Il est composé de 3 onglets :
Ces onglets contiennent des groupes, qui contiennent eux-mêmes des contrôles (boutons, listes, etc.)
Il est possible de créer un TabSet personnalisé (un seul), qui prendra forcément le nom de votre formulaire (c'est dommage, mais c'est comme ça)
Créez une nouveau ruban dans F_USYSRibbon. RibbonName : Tab set
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon><contextualTabs>
<tabSet idMso="TabSetFormReportExtensibility">
<tab id="TAB1" label="Fruits rouges"> <group id="GRP1"> <button id="BDC1" label="Framboise"/> </group> </tab> <tab id="TAB2" label="Fruits jaunes"> </tab></tabSet>
</contextualTabs>
<tabs> <tab id="TAB3" label="Fruits verts"> </tab> </tabs> </ribbon> </customUI>
Le TabSet doit avoir pour nom TabSetFormReportExtensibility, et ne peut pas avoir de label="Quelque chose". Il prendra le nom du formulaire. Les Tabs du tabSet, se trouveront toujours le plus à droite du ruban. Dans notre exemple, bien qu'un tab "Fruits verts" soit défini en desssous du tabSet, il apparaîtra avant, comme ceci :
Si vous désirez connaître la hiérarchie de tous les TabSet, Tab, Group et Control, allez jeter un oeil dans la table T_IDMsoEmplacementMenu. Voici l'exemple du référencement de la liste déroulante "Taille de police", du groupe "Police", de l'onglet "Format" de l'ensemble d'onglets "Outils de création de formulaire" :
Ce que je viens de vous montrer n'est pas très intéressant pour la création de rubans personnalisés, car quel intérêt y a-t-il a afficher tel ou tel ensemble de rubans qui sont destinés à la création d'onjets ? ce qui nous intéresse, c'est ce qu'on peut faire en mode formulaire.
D'ailleurs, je vous ai signalé un peun plus haut qu'il n'est pas possible d'afficher le ruban TabFormToolsDesign (mais ce n'est pas bien grave), par contre, il est possible d'afficher n'importe quel groupe. Voici quelques exemple :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Groupe idMso"> <group idMso="GroupCreateReports
"/> <group idMso="GroupQueryResults
"/> <group idMso="GroupFieldsTools
"/> </tab> </tabs> </ribbon> </customUI>
Le résultat sera le suivant :
Utilisé rarement dans une application personnalisée : GroupCreateReport : Dans le premier groupe, nous avons la possibilité de crérer des états (mais va-t-on réellement créer des applicatiosn Access ou les utilisateurs seront appelés à créer leurs propres états ? En général, les états sont fdéjà faits par le concepteurs, il suffit de les ouvrir.
Déconseillé : GroupeQueryResults : Ici, les deux icones du groupe sont plutôt destinées à changer le mode d'affichage des requêtes, et leur exécution. On pourra utiliser ces icones dans un formulaire saisie de données, mais est-ce bien prudent ? est-ce bien utile ?
Carrément désactivé : GroupFieldsTools : cet exemple de groupe complètement hors de propos propose carrément des icones inactives : en effet, ce sont les deux icones qui permettent d'ajouter des champs dans un formulaire en mode création et afficher la feuille des propriétés.
Voici la liste (plus intéressante) des différents groupes des principaux onglets. Ne la prenez pas trop au pied de la lettre, je ne les ai pas tous testé, et je n'ai pas trouvé pourquoi ceux en rouge ne fonctionnent pas, mais je n'ai sans doute pas assez fouiné.
Access affiche ou pas certains éléments selon le contexte. Par exemple, il n'affiche que les TabSets que nous avons vus un peu plus haut que lorsque c'est pertinent. Il lui arrive également de masquer tel ou tel groupe selon les cas. Par exemple, la réplication est une fonctionnalité qui existe dans les anciennes bases de données en .mdb, mais qui a disparu avec le nouveau format accdb. Ainsi, selon le format de votre base de données, le groupe Administrer est visible, ou pas.
Certains contrôles de rubans peuvent être actifs ou inactifs selon les cas. Nous l'avons vu ici. Ainsi, si vous affichez un contrôle idMso dans votre propre ruban, c'est Access et pas vous qui décide si ce contrôle doit être activé ou pas. ainsi, vous aurez beau insister et vouloir absolument afficher et activer la liste des polices de caractères alors qu'elle ne peut pas être utilisée dans le contexte, elle restera désespérément inactive (Référez-vous à nouveau ici).
Créez un nouveau ruban dans F_USYSRibbons. RibbonName : Visibilité et activation
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="TAB" label="Visibilité et activation">
<group id="GRP">
<control idMso="Bold"/> <control idMso="Italic"enabled="true"
/> <control idMso="Underline"enabled="false"
/></group>
</tab>
</tabs>
</ribbon>
</customUI>
Evidemment, lorsque vous n'utilisez pas control, mais button, ou n'importe quel autre contrôle personnalisé, même si l'imageMso correspond à un contrôle existant, on peut tout à loisir les rendre visibles-invisibles-actifs-désactivés.
Vous pourrez utiliser :
Si vous ne précisez pas enabled ni visible, par défaut, le contrôle personnalisé sera activé et visible.
Vous avez la possibilité de télécharger la base de données de ce didacticiel dans l'état ou elle se trouve à ce niveau du didacticiel.
Dans le coin inférieur droit de certains groupes, vous avez un petit bouton très discret qui permet d'afficher une boîte de dialogue avec plein d'autre options :
Ce petit bouton peut se créer dans tous vos groupes personnalisés.
Créez un nouveau ruban dans F_USYSRibbon. RibbonName : Lanceur de boîte de dialogue.
RibbonXML : (DBL = acronyme de "Dialog Box Launcher")
XML<?xml version="1.0" encoding="utf-8" ?> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Lancement boîte dialogue"> <group id="GRP" label="Lanceur de boite de dialogue"> <button id="BDC1" label="Bouton quelconque"/><dialogBoxLauncher>
<button
id="DBLBouton" onAction="DBLBouton_onAction"/></dialogBoxLauncher>
</group> </tab> </tabs> </ribbon> </customUI>
La section dialogBoxLauncher doit être la dernière section du groupe, et contenir un seul bouton.
La procédure de CallBack OnAction se comporte comme un bouton classique. Créez un nouveau module VBA que vous appelerez P_LanceurDeBoiteDeDialogue, dans lequel vous mettez le code suivant :
VBASub DBLBouton_onAction(ElementRuban As IRibbonControl) MsgBox "C'est ici qu'on personnalise les options" End Sub
Si vous testez votre ruban et que vous cliquez sur le dialogBoxLauncher, vous obtiendrez ceci :
Lorsque vous survolez un contrôle prédéfini idMso, une infobulle bien pratique apparaît. On peut personnaliser ces infobulles dans une certaine mesure.
Créez un nouveau ruban dans F_USYSRibbons. RibbonName : Infobulles
RibbonXML :
XML<?xml version="1.0" encoding="utf-8" ?> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Infobulles"> <group id="GRP" label="Infobulles"><!-- idMso prédéfini : pas de tips définis -->
<control idMso= "ImportExcel" size= "large"/><!-- idMso prédéfini : tips définis -->
<control idMso= "ExportExcel" size= "large"supertip= "Je suis Super Tip"
screentip= "Je suis Screen Tip"
/><!-- Bouton personnalisé : pas de tips définis -->
<button id= "BDCFraise" label= "Fraise" size= "large"/><!-- Bouton personnalisé : pas de tips définis -->
<button id= "BDCBanane" label= "Banane" size= "large"supertip= "je suis Super Tip"
screentip= "Je suis Screen Tip"
/> </group> </tab> </tabs> </ribbon> </customUI>
Voici ce que ça donne lorsque vous passez avec la souris (sans cliquer) sur chacun des boutons :
Dans le cas de contrôles prédéfinis idMso, on peut remplacer complètement le screentip (gros titre en gras) et le supertip (explication plus détaillée), mais on ne peut pas se débarasser du message idiot : Appuyez sur F1 pour obtenir de l'aide.
Dans le cas de boutons ou autres contrôles personnalisés, si vous ne précisez pas de screentip, le label du bouton est répété, sinon, on peut, comme pour les contrôles prédéfinis idMso, créer des textes d'aides personnalisés. Gênant : il n'est pas possible de se débarasser du nom du formulaire (ici : F_USYSRibbons), ni de la proposition d'aide (tout aussi idiote puisque F1 ne sert à rien dans notre application personnalisée). Même si vous définissez la propriété Légende de votre formulaire, le nom continuera d'être obstinément utilisé.
Il existe les procédures de CallBack getScreentip et getSupertip, dont vous pourrez retrouver la syntaxe d'utilisation dans la table de votre base de données T_FonctionCallBack.
Il est possible d'écrire du simple texte directement dans le ruban. Créez un nouveau ruban dans F_USYSRibbons. RibbonName : Simple texte
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Simple texte"> <group id="GRP" label="Textes"> <labelControl id="TXT1" label="Tomate haricot" /> <labelControl id="TXT2" label="Orange mandarine melon" /> <labelControl id="TXT3" label="BMW" /> <labelControl id="TXT4" label="Blanc bleu noir gris" /> <labelControl id="TXT5" label="Suisse France" /> <labelControl id="TXT6"getLabel
="TXT6_getLabel" /> </group> </tab> </tabs> </ribbon> </customUI>
Créez un nouveau module VBA, que vous appellerez P_SimpleTexte, dans lequel vous ajoutez la procédure CallBack nécessaire à TXT6 :
VBASub TXT6_getLabel(ElementRuban As IRibbonControl, TexteAEcrire) TexteAEcrire =CurrentProject.Name
End Sub
L'intérêt de ce getLabel est de pouvoir écrire du texte dynamiquement, comme dans cet exemple : nous écrivons le nom de notre base de données.getLabel est une procédure CallBack disponible pour tous les types de contrôles (Boutons, cases à cocher, etc.).
Si vous exécutez ce ruban vous constatez plusieurs choses :
Le CallBack onAction n'existe pas. On ne peut donc pas cliquer sur ces textes. Il n'y a pas d'exemple de ces textes dans les rubans prédéfinis d'Access.
Il est possible d'organiser les différents éléments de ruban plus esthétiquement grâce à box.
Créez un nouveau ruban dans F_USYSRibbons. RibbonName : Sous groupements
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="TAB1" label="Groupements"><!-- sans arrangement : *************************************** -->
<group id="GRP0" label="Sans box"> <button id="BDC01" imageMso="Bold" label="Gras"/> <button id="BDC02" imageMso="Italic"/> <button id="BDC03" imageMso="Underline" label="Souligné"/> <labelControl id="TXT04" label="J'aime les fruits sucrés" /> <checkBox id="CAC05" label ="Content?"/> <button id="BDC06" imageMso="Cut" size="large"/> <button id="BDC07" imageMso="Copy"/> <button id="BDC08" imageMso="Paste"/> </group><!-- box horizontal : *************************************** -->
<group id="GRP2" label="Box horizontal"> <box id="BOX2"boxStyle="horizontal">
<button id="BDC09" imageMso="Bold" label="Gras"/> <button id="BDC10" imageMso="Italic"/> </box> <box id="BOX3"boxStyle="horizontal">
<button id="BDC11" imageMso="Underline" label="Souligné"/> <labelControl id="TXT12" label="J'aime les fruits sucrés" /> <checkBox id="CAC13" label ="Content?"/> </box> <box id="BOX4"boxStyle="horizontal">
<button id="BDC14" imageMso="Cut" size="large"/> <button id="BDC15" imageMso="Copy"/> <button id="BDC16" imageMso="Paste"/> </box> </group><!-- box vertical : *************************************** -->
<group id="GRP3" label="Box vertical"> <box id="BOX5"boxStyle="vertical">
<button id="BDC17" imageMso="Bold" label="Gras"/> <button id="BDC18" imageMso="Italic"/> </box> <box id="BOX6"boxStyle="vertical">
<button id="BDC19" imageMso="Underline" label="Souligné"/> <labelControl id="TXT20" label="J'aime les fruits sucrés" /> <checkBox id="CAC21" label ="Content?"/> </box><!-- Et les derniers sans box : *************************************** -->
<button id="BDC22" imageMso="Cut" size="large"/> <button id="BDC23" imageMso="Copy"/> <button id="BDC24" imageMso="Paste"/> </group> </tab> </tabs> </ribbon> </customUI>
Si vous exécutez ce long ruban, vous verrez trois groupes de contrôles
que je vous détaille ici :
Dans le premier groupe, les contrôles sont alignés en colonne, 3 par 3, et quand il y a un contrôle en size="large", il prend la place de 3 contrôles l'un en dessous de l'autre (Il n'existe pas de contrôle ni de taille prenant la place de deux icones en hauteur) :
boxStyle="horizontal" permet d'obliger le ruban a aligner les contrôles de gauche à droite jusqu'à la fin du box. Ainsi, dans notre exemple, le premier box aligne les deux icones Gras et Italique l'un à côté de l'autre, puis passe "à la ligne" pour le prochaine alignement, et ainsi de suite, comme sur le dessin :
L'alignement vertical revient presqu'au même que de ne pas aligner du tout, puisqu'il aligne en colonne. La différence est qu'on n'est pas obligé d'avoir 3 icones l'une en dessous de l'autre. Ainsi, dans ce cas, en dessous de gras et Italique, il n'y a rien, parce que c'estla fin du box.
A la fin, les 3 dernières icones sont placées sans box, ce qui est strictement équivalent à les avoir groupées toutes en box vertical.
Il existe une alternative à box qui s'appelle buttonGroup, qui est assez équivalente, mais je n'y vois pas d'intérêt, parce que buttonGroup n'accepte que des boutons et des boutons bascules, alors que box permet toutes les sortes de contrôles.
Toujours pour parler de l'organisation des contrôles dans le ruban, vous avez constaté qu'entre chaque groupe, il y a une petite ligne verticale de séparation :
Eh bien, il est possible d'ajouter encore d'autres petites lignes verticales de séparation à l'intérieur même de groupes.
Le ruban suivant :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Séparateurs"> <group id="GRP" label="Groupe séparé en trois"> <button id="BDC1" label="Un"/> <separator
id="SEP1"/> <button id="BDC2" label="Deux"/> <button id="BDC3" label="Troisième bouton"/> <separator
id="SEP2"/> <button id="BDC4" label="Quatre"/> </group> </tab> </tabs> </ribbon> </customUI>
Donnerait ce résultat :
Une zone d'édition est un simple champ de saisie.
Créez un nouveau ruban dans F_USYSRibbon. RibbonName : Edit Box.
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="TAB" label="Zones d'édition"> <group id="GRP"> <editBox
id= "EDIPrenom" label= "Votre prénom" :text= "Dupont"/> </group> </tab></tabs>
</ribbon>
</customUI>
Il n'est pas possible d'y insérer un texte par défaut.
Voici le résultat :
Recourons à une petite astuce pour que l'invitation "Votre prénom : " soit positionnée au dessus de la zone d'édition, et pas à gauche, en utilisant le simple texte (labelControl) Vous vous souvenez ?
Corrigez votre ruban Edit Box comme suit :
XML... <tab id="TAB" label="Zones d'édition"> <group id="GRP"> <labelControl
id= "TXTPrenom" label= "Entrez ici votre prénom :
"/> <editBox id= "EDIPrenom"/> </group> </tab> ...
Résultat :
Il est possible de modifier la largeur de cette zone d'édition (avec sizeString) et le nombre maximum de caractères autorisés (avec maxLength).
Modifiez votre code XML comme suit :
... <tab id="TAB" label="Zones d'édition"><group id="GRP">
<labelControl id= "TXTPrenom"
label= "Entrez ici votre prénom :"/>
<editBox id= "EDIPrenom"/>
</group>
<group id="GRP2"> <editBox id= "EDI1" sizeString= "WWW"/> <editBox id= "EDI2" sizeString= "iii"/> <editBox id= "EDI3" sizeString= "WWWWWWWWWWWWWWWW" maxLength= "3"/> </group> </tab> ...
Voici le résultat :
L'attribut sizeString fonctionne étrangement : au nombre de caracères qu'on lui donne en pâture... Et il voit la différence entre iii et WWW qui ne prennent pas la même largeur. C'est un peu du pifomètre !
Le maxLength permet de préciser le nombre de caractères maximum permis dans un champ (indépendamment de sizeString). Si on essaie de dépasser ce nombre, le message inamovible "L'entrée ne doit pas contenir plus de X caractères" s'affiche obligatoirement : il n'y a pas moyen de le supprimer ou de le personnaliser.
Les editBox s'alignent forcément sur la droite. Il n'existe pas d'attribut de style align="Left", ou alignEditBox="Center".
A part la vérification du nombre de caractères avec maxLength, il est évidemment possible de contrôler finement le contenu de l'editBox grâce aux fonctions CallBack OnChange (Quand on saisis quelque chose dans la zone et qu'on appuie sur ENTER du clavier) et getText (Qui permet d'attribuer une valeur par défaut à cette zone).
Essayons : modifiez le code XML de votre ruban Edit box en ajoutant une zone d'édition comme suit :
XML...
<editBox id= "EDI3"
sizeString= "WWWWWWWWWWWWWWWW"
maxLength= "3"/>
</group>
<group id="GRP3"> <editBox id= "EDIMotDePasse" label= "Mot de passe : "getText
= "EDIMotDePasse_getText
"onChange
= "EDIMotDePasse_onChange
"/> </group></tab>
</tabs>
</ribbon>
</customUI>
Nous allons maintenant écrire "Password?" comme texte par défaut dans notre zone d'édition, et lorsque l'utilisateur va entrer son vrai mot de passe, nous le féliciterons s'il a bien entré "tralala", et sinon,. nous lui dirons que son mot de passe est faux.
Créez un ouveau module VBA, que vous appelerez P_EditBox, dans laquelle vous copiez les deux procédures CallBack suivantes :
VBASub EDIMotDePasse_getText(ElementRuban As IRibbonControl, Texte) Texte = "Password?" End Sub Sub EDIMotDePasse_onChange(ElementRuban As IRibbonControl, Texte) If Texte = "tralala" Then MsgBox "Mot de passe correct" Else MsgBox "Mot de passe erroné" End If End Sub
Si vous exécutez ce ruban, vous verrez que dans la zone d'édition, il sera marqué "Password?" d'entrée de jeu, et si vous effacez ce texte pour écrire "tralala", et que vous appuyez sur ENTER de votre clavier, ou que vous cliquez dans une autre zone (pour valider), vous aurez un message "Mot de passe correct", et si vous écrivez un autre mot, vous aurez "Mot de passe erroné".
je propose que lorsqu'on entre un mot de passe dans cette zone, lorsqu'on valide avec ENTER, non seulement il nous prévient avec un MsgBox que le mot de passe est bon ou mauvais, mais, en plus, selon les cas, à la place de "Password?", il écrive "OK", ou "Invalide" dans cette même zone. Et pour que le mot de passe serve à quelque chose, si le mot de passe est bon, ça affiche carrément un onglet supplémentaire dans le ruban, qui ne sera donc accessible que si on possède le mot de passe..
Nous allons devoir nous replonger dans la notion d'invalidate (vous vous souvenez ?)
Commençons par nous occuper de nos textes. Pour le moment, EDIMotDePasse_getText se contente d'afficher "Password?" une seule fois à l'affichage du ruban, et puis c'est tout.
Commencez par déclarer une variable publique VARMotDePasse, et corrigez EDIMotDePasse_getText de manière à ce qu'il n'affiche "Password?" que dans le cas ou l'utilisateur n'a encore rien essayé :
VBAOption Compare Database PublicVARVerifieMotDePasse
As String Sub EDIMotDePasse_getText(ElementRuban As IRibbonControl, Texte) IfVARVerifieMotDePasse
= "" then Texte = "Password?" End Sub
Si vous testez votre ruban, il va fonctionner exactement comme avant. La seule différence consiste à vérifier si VARMotDePasseOK est égal à "" (vide en fait), et oui, cette variable de type string (texte) est bien vide, puisqu'on l'a déclarée, mais on ne lui a imposé aucune valeur.
Maintenant, cette variable, justement, nous allons lui donner la valeur "Correct" ou "Incorrect", selon que l'utilisateur a entré le bon mot de passe (tralala) ou pas.
Pour ce faire, modifiez EDIMotDePasse_onChange comme suit :
VBASub EDIMotDePasse_onChange(ElementRuban As IRibbonControl, Texte) If Texte = "tralala" Then MsgBox "Mot de passe correct" VARVerifieMotDePasse = "Correct
" Else MsgBox "Mot de passe erroné" VARVerifieMotDePasse = "In
correct" End If End Sub
Maintenant, la variable publique VARVerifieMotDePasse est bien renseignée. Il s'agit maintenant de rappeler la procédure CallBack EDIMotDePasse_getText.
Aïe ! Pour la rappeler, nous avons besoin de la référence au ruban si vous vous rappelez ! Constatez que cet exercice ressemble énormément à celui que nous avons vu ici.
Ajoutez-donc l'indispensable procédure CallBack onLoad de votre ruban Edit box :
XML<customUI xmlns= "http://schemas.microsoft.com/office/2009/07/customui"onLoad="RubanEditBox_onLoad">
Et donc, dans votre VBA, créez la variable publique qui va contenir le ruban, ainsi que la procédure CallBack RubanEditBox_onLoad :
VBAOption Compare Database Public VARVerifieMotDePasse As String PublicVARRubanEditBox As IRibbonUI
Sub RubanEditBox_onLoad(Ruban As IRibbonUI) SetVARRubanEditBox
= Ruban End Sub
Maintenant enfin, nous allons pouvoir demander le rappel de EDIMotDePasse_getText lorsque l'utiliusateur va entrer un mot de passe (EDIMotDePasse_onChange), comme ceci :
VBASub EDIMotDePasse_onChange(ElementRuban As IRibbonControl, Texte)If Texte = "tralala" Then
MsgBox "Mot de passe correct"
VARVerifieMotDePasse = "Correct"
Else
MsgBox "Mot de passe erroné"
VARVerifieMotDePasse = "Incorrect"
End If
VARRubanEditBox.InvalidateControl "EDIMotDePasse" End Sub
Ainsi, dans cette procédure, nous mettons donc bien à jour la variable publique VARVerifieMotDePasse, et ensuite, nous InvalidateControl là zone editBox dont l'id est EDIMotdepasse.
Dernière chose à faire : mettre à jour EDIMotDePasse_onChange pour qu'il affiche "OK" ou "ERREUR!" selon les cas :
VBASub EDIMotDePasse_getText(ElementRuban As IRibbonControl, Texte)' Premier cas : VARVerifieMotDePasse n'est pas encore déterminé
If VARVerifieMotDePasse = "" Then Texte = "Password?"' Lorsque l'utilisateur entre le bon mot de passe tralala :
If VARVerifieMotDePasse = "Correct" Then Texte = "OK"' Lorsque l'utilisateur entre un faux mot de passe :
If VARVerifieMotDePasse = "Incorrect" Then Texte = "ERREUR!" End Sub
Vous pouvez tester : a la base la zone EditBox va afficher "Password?", et si vous y entrez tralala ou un autre mot de passe, vous constaterez que la zone se met bien à jour.
Voici le ruban XML complet (j'ai volontairement omis les autres premiers tests d'EditBox, pour faire plus simple) :
XML<customUI xmlns= "http://schemas.microsoft.com/office/2009/07/customui" onLoad="RubanEditBox_onLoad"
> <ribbon> <tabs> <tab id="TAB" label="Zones d'édition"> <group id="GRP3"> <editBox id= "EDIMotDePasse" label= "Mot de passe : " getText= "EDIMotDePasse_getText"
onChange= "EDIMotDePasse_onChange"
/> </group> </tab> </tabs> </ribbon> </customUI>
Et voici tout le module VBA P_EditBox :
VBAOption Compare Database Public VARVerifieMotDePasse As String Public VARRubanEditBox As IRibbonUI Sub RubanEditBox_onLoad(Ruban As IRibbonUI) Set VARRubanEditBox = Ruban End Sub Sub EDIMotDePasse_getText(ElementRuban As IRibbonControl, Texte) If VARVerifieMotDePasse = "" Then Texte = "Password?" If VARVerifieMotDePasse = "Correct" Then Texte = "OK" If VARVerifieMotDePasse = "Incorrect" Then Texte = "ERREUR!" End Sub Sub EDIMotDePasse_onChange(ElementRuban As IRibbonControl, Texte) If Texte = "tralala" Then MsgBox "Mot de passe correct" VARVerifieMotDePasse = "Correct" Else MsgBox "Mot de passe erroné" VARVerifieMotDePasse = "Incorrect" End If VARRubanEditBox.InvalidateControl "EDIMotDePasse" End Sub
Bien. maintenant, histoire que notre mot de passe serve à quelque chose, nous allons afficher un menu (un onglet) supplémentaire si le mot de passe est correct (ce serait par exemple un menu comportant des options quelque peu confidentielles)
Corrigez votre ruban XML Edit box comme suit :
XML...<editBox id= "EDIMotDePasse"
label= "Mot de passe : "
getText= "EDIMotDePasse_getText"
onChange= "EDIMotDePasse_onChange"/>
</group>
</tab>
<tab id="TABConfidentiel
" label="Options confidentielles"> <group id="GRPConfidentiel"> <button id="BDCBenefice" label="Afficher les bénéfices"/> <button id="BDCPerte" label="Afficher les pertes"/> </group> </tab> </tabs> </ribbon> </customUI>
Si vous exécutez ce ruban, vous aurez simplement un onglet de plus :
Maintenant, cet onglet ne doit apparaître que si le mot de passe tralala a été correctement saisie dans l'onglet Zone d'édition. En d'autres mots : si VARVerifieMotDePasse vaut "Correct".
Pour ce faire, il nous faut ajouter une procédure CallBak getVisible à notre tab, comme ceci :
XML... <tab id="TABConfidentiel" label="Options confidentielles"getVisible="TABConfidentiel_getVisible"
> <group id="GRPConfidentiel"> <button id="BDCBenefice" label="Afficher les bénéfices"/> <button id="BDCPerte" label="Afficher les pertes"/> </group> </tab></tabs>
</ribbon>
</customUI>
Dans VBA, Modifiez le code comme suit :
VBAOption Compare Database Public VARVerifieMotDePasse As String Public VARRubanEditBox As IRibbonUI Sub RubanEditBox_onLoad(Ruban As IRibbonUI) Set VARRubanEditBox = Ruban End Sub Sub EDIMotDePasse_getText(ElementRuban As IRibbonControl, Texte) If VARVerifieMotDePasse = "" Then Texte = "Password?" If VARVerifieMotDePasse = "Correct" Then Texte = "OK" If VARVerifieMotDePasse = "Incorrect" Then Texte = "ERREUR!" End Sub Sub EDIMotDePasse_onChange(ElementRuban As IRibbonControl, Texte) If Texte = "tralala" ThenMsgBox "Mot de passe correct"' (3)
VARVerifieMotDePasse = "Correct" ElseMsgBox "Mot de passe erroné"' (3)
VARVerifieMotDePasse = "Incorrect" End If VARRubanEditBox.InvalidateControl "EDIMotDePasse"VARRubanEditBox.InvalidateControl "TABConfidentiel"
' (2)
End Sub' (1) :
Sub TABConfidentiel_getVisible(ElementRuban As IRibbonControl, OnPeutVoir) If VARVerifieMotDePasse = "Correct" Then OnPeutVoir = True Else OnPeutVoir = False End If End Sub
Et voilà : maintenant, lorsque vous testez le ruban, si vous entrez tralala dans la zone de mot de passe, au moment ou vous tapez sur ENTER, vous verrez le nouvel onglet Options confidentielles apparaître instantanément.
Si vous désirez télécharger la base de données dans son état actuel (et donc avec ce dernier exercice fonctionnel), cliquez ici.
Créez un nouveau ruban dans F_USYSRibbons. RibbonName : Listes déroulantes
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon> <tabs> <tab id="TAB" label="Listes déroulantes"> <group id="GRP"> <comboBox
id="LIDFruit" label="Liste de fruits
"> <item
id="ITEBanane
" label="Banane
"/> <item
id="ITEFraise
" label="Fraise
"/> <item
id="ITEPomme
" label="Pomme
"/> </comboBox
> </group> </tab> </tabs> </ribbon> </customUI>
Voici le résultat :
Lorsque vous choisissez un fruit dans la liste, il ne se passe rien. Pour afficher le fruit en question (ou faire n'importe quoi d'autre), il faut créer la procédure CallBack onChange.
Modifiez votre code XML du ruban Listes déroulantes comme suit :
XML... <group id="GRP"> <comboBox id= "LIDFruit" label= "Liste de fruits" onChange= "LIDFruit_onChange"> <item id="ITEBanane" label="Banane"/> <item id="ITEFraise" label="Fraise"/> <item id="ITEPomme" label="Pomme"/> </comboBox> </group> ...
Créez un nouveau module VBA que vous appelerez P_ListesDeroulantes, dans lequel vous ajoutez le CallBack suivant :
VBSub LIDFruit_onChange(ElementRuban As IRibbonControl, ElementListe) MsgBox ElementListe MsgBox ElementRuban.Id End Sub
Si vous exécutez ce ruban, et que vous choisissez Fraise dans la liste, il vous donnera le résultat suivant :
ElementListe contient bien le contenu de l'élément sélectionné (Fraise et pas ITEFraise), mais si on voulait récupérer ITEFraise, ce ne serait pas possible. En effet, ElementRuban est une réflérence à l'ensemble de la liste. Et pas question d'essayer ElementListe.id : ça ne marche pas parce que ElementListe est juste un simple texte. Autre limitation : on ne peut pas non plus créer de tag : <item id="ITEFraise"
est interdit.tag="Fruit fraise" label="Fraise"/>
On doit ainsi absolument faire avec le simple contenu de la liste. On ne peut pas non plus créer de listes déroulantes à plusieurs colonnes, comme on peut le faire en création de table, avec l'assistant liste de choix :
Si c'est vraiment indispensable, il vous faudra suivre ce didacticiel, mais c'est assez complexe.
Vous pouvez agrémenter votre liste déroulante avec des imageMso, comme ceci :
XML... <comboBox id= "LIDFruit" label= "Liste de fruits" onChange= "LIDFruit_onChange"> <item id="ITEBanane" label="Banane" imageMso="ShapeSmileyFace"/> <item id="ITEFraise" label="Fraise" imageMso="HappyFace"/> <item id="ITEPomme" label="Pomme" imageMso="SadFace"/> </comboBox> ...
Voici le résultat :
Afin de pouvoir poursuivre, il vaut mieux que vous ayez téléchargé les images que j'ai mis à votre disposition ici, et de les placer dans le même dossier que votre base de données.
Il est possible d'ajouter une image à la liste déroulante elle-même, grâce au CallBack getImage :
XML... <comboBox id= "LIDFruit" label= "Liste de fruits" getImage= "LIDFruit_getImage" onChange= "LIDFruit_onChange"> <item id="ITEBanane" label="Banane"/> <item id="ITEFraise" label="Fraise"/> <item id="ITEPomme" label="Pomme"/> </comboBox> ...
Ajoutez ensuite le CallBack idoine dans votre module P_ListesDeroulantes :
VBASub LIDFruit_onChange(ElementRuban As IRibbonControl, ElementListe)
MsgBox ElementListe
MsgBox ElementRuban.Id
End Sub
Sub LIDFruit_getImage(ElementRuban As IRibbonControl,ImageGlobaleListe
) SetImageGlobaleListe
= LoadPicture(CurrentProject.Path & "\IMGPommeRectangleTropGrand
.jpg") End Sub
Voici le résultat :
Il est normalement prévu de pouvoir placer des images personnalisées (comme des imageMso) a chaque élément, et ça devrait s'écrire de cette manière :
XML... <comboBox id= "LIDFruit" label= "Liste de fruits" getImage= "LIDFruit_getImage" getItemImage= "LIDFruit_getItemImage" onChange= "LIDFruit_onChange"> <item id="ITEBanane" label="Banane"/> <item id="ITEFraise" label="Fraise"/> <item id="ITEPomme" label="Pomme"/> </comboBox> ...
Ensuite, il faut ajouter le CallBack correspondant dans le VBA :
VBASub LIDFruit_onChange(ElementRuban As IRibbonControl, ElementListe)
MsgBox ElementListe
MsgBox ElementRuban.Id
End Sub
Sub LIDFruit_getImage(ElementRuban As IRibbonControl, ImageGlobaleListe Set ImageGlobaleListe = LoadPicture(CurrentProject.Path & "\IMGPommeRectangleTropGrand.jpg") End Sub Sub LIDFruit_getItemImage(ElementRuban As IRibbonControl, index As Integer, imageElementListe) Set imageElementListe = LoadPicture(CurrentProject.Path & "\IMGBanane16X16.gif") End Sub
Ici, nous devrions avoir le dessin d'une petite banane à côté de chaque élément, mais ça ne fonctionne pas. Aucune erreur n'est générée, mais la procédure ne semble pas s'exécuter du tout, car si on y ajoute un MsgBox, il ne s'affiche pas.
Une fonctionnalité extrêmement puissante des listes déroulantes est de pouvoir lister tous les éléments d'une table ou d'une requête. Dans la base de données que vous avez téléchargé, vous trouverez une table T_Celebrite, qui va nous permettre de tester ceci.
L'idée est de créer une liste déroulante qui affiche tous les noms de toutes les célébrités, dans le but de, par exemple, nous rendre directement sur 'enregistrement correspondant.
Créez un nouveau ruban dans votre formulaire F_USYSRibbons. RibbonName : Combobox dynamique.
RibbonXML :
XML<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="TAB" label="Liste déroulante dynamique"> <group id="GRP"> <comboBox id= "LIDCelebrite" label= "Choix d'une célébrité" onChange= "LIDCelebrite_onChange"getItemCount
= "LIDCelebrite_getItemCount
"getItemLabel
= "LIDCelebrite_getItemLabel
"> </comboBox> </group> </tab> </tabs> </ribbon> </customUI>
Deux nouvelles procédures CallBack vont être nécessaires : getItemCount, qui va renseigner sur le nombre d'éléments du comboBox, et getItemLabel, qui va être appelé autant de fois qu'il y a d'éléments.
Créez un nouveau module VBA, que vous nommerez P_ComboBoxDynamique, dans lequel vous placez ces deux procédures CallBack :
VBAOption Compare Database
Sub LIDCelebrite_getItemCount(ElementRuban As IRibbonControl, NombreElementListe)NombreElementListe = 3
MsgBox "je viens de renseigner NombreElementListe : 3" End Sub Sub LIDCelebrite_getItemLabel(ElementRuban As IRibbonControl,NumeroEnCours
,ElementListe
) IfNumeroEnCours
=0
ThenElementListe
= "Rouge
" IfNumeroEnCours
=1
ThenElementListe
= "Vert
" IfNumeroEnCours
=2
ThenElementListe
= "Bleu
"If NumeroEnCours = 3 Then ElementListe = "Noir"MsgBox "Je viens d'ajouter à la liste : " &ElementListe
End Sub
C'est seulement lorsque vous cliquerez physiquement sur la petite flèche de la liste déroulante que :
FIN ----------------
XXXXXXX
XXXXXXX
XXXXXXX
XXXXXXX