Il est de bon ton de se souhaiter la bonne année. Mais vous, et vous seul, pourrez faire en sorte que cette année soit bonne, meilleure que celle qui vient de s'écouler. Apprenez à ne compter que sur vous, car personne n'est plus qualifié que vous-même pour bâtir, réparer ou améliorer votre propre vie. Personne ne fera les choses à votre place. D'ailleurs, tout ce que les autres peuvent faire, c'est souhaiter que vous le fassiez. Et ne croyez pas que tout ceux qui vous entourent vous apporteront des solutions : certains font juste partie de vos problèmes. Transformez vos résolutions en actes, et dans douze mois, retournez-vous et souriez-vous fièrement : C'était long. C'était difficile. Mais ça y est : 2017 était une bonne année, merci Moi.

Access

Les rubans personnalisés

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
rubanpersocours02.zip
rubanpersocours03.zip
rubanpersocours04.zip
rubanpersocours05.zip
rubanpersocours06.zip
rubanpersocours07.zip
rubanpersocours08.zip
rubanpersocours09.zip
rubanpersocours10.zip

Liens externes

dddd

Utilité

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 :

Base de données de base

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.

Personnalisation du ruban général Access

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.

  1. Dans le tableau de droite, cliquez sur Accueil (sans enlever la coche)
  2. Cliquez sur le bouton Nouvel onglet
  3. Cliquez ensuite sur Nouvel Onglet (Personnalisé), Renommer, et donnez comme nom : Mes fruits :
  4. Maintenant, renommez le groupe en Fruits frais, comme sur cette image, et attribuez-lui l'icone de la petite balance
  5. Après vous êtes assuré que vous avez bien sélectionné fruits frais dans la liste de droite, cliqez sur Enregistrer dans la liste de gauche, et cliquez sur Ajouter>>>
  6. Cliquez sur Ok

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.

Exportation du fichier .exportedUI

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).

Analyse du contenu d'un fichier .exportedUI

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 :

Présentation sommaire de XML

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.

Importation d'un fichier .exportedUI

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 :

  1. Commencez par supprimer votre personnalisation : Fichier/Options Access, et supprimez les personnalisations comme ceci :
  2. Constatez que votre ruban est comme avant (Comme a l'installation d'Access, en fait) :
  3. Et maintenant, "ré"importez votre fichier de personnalisation Les fruits sont bons.exportedui :
  4. Et vous revoici avec votre onglet Fruits, comme avant :

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.

Création de notre premier ruban

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.

Création de USYSRibbons

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 !

 

Tables système masquées

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 :

Premier ruban basique

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.

Chargement de USYSRibbons

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.

Erreurs XML

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 !

Interception des erreurs

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 :

XML invalide et XML mal formé

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 !

Distinction des majuscules/minuscules et espaces

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 à :

  1. remettre le 2ème b de ribbon
  2. fermer et rouvrir la base de données pour vous assurer qu'il n'y a plus d'erreur et que l'onglet de ruban s'affiche à nouveau.

 

Schéma XML pour Office 2007 et Office 2010

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.

Ruban de formulaire/état

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>

 

Création d'un formulaire vide

 

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 :

 

Résumé des endroits de créations de rubans

Vous connaissez maintenant les trois endroits de création de ruban :

Création  de ruban dans un fichier XML externe

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.

Marche à suivre

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 :

Notepad++

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é)

Code VBA pour l'importation d'un fichier XML externe

Créez un nouveau module VBA (Créer/Module)

Recopiez y cette fonction :

VBA
Function 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.

Bobliothèque de gestion de fichiers

    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.

Instruction de chargement de ruban externe

XML
Application.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 :

Rubans inexistants : absence de message d'erreur

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.

Macro Autoexec

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 :

Boutons

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)

Police de caractère adaptée au XML

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 :

Gestion des erreurs trop vague

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.

 

Hiérarchie <tab> - <group> - <button>

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 : "/".

Principe de XML : ouverture et fermeture des balises

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 :

Structure plus complète

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.

Commentaires

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.

Procédures de rappel (callback)

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 : Sub TRALALAyoupi(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.)

  1. Enregistrez votre module VBA sous P_MonPremierClicProcedureRappel.
  2. Fermez votre base de données.
  3. Rouvrez-là
  4. Allez dans votre formulaire F_RubanTest en mode création
  5. définissez que son ruban est maintenant Premier clic bouton
  6. Lancez votre formulaire en mode saisie de données
  7. cliquez sur votre bouton

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 :

VBA
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 :

VBA
Sub 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.

Callback Macros

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.

Macro

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) :

Sous-macros

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 :

Création d'un ruban pour appeler les macros

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.

Commandes prédéfinies idMso

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 :

  1. Aller dans le formulaire en mode création
  2. faire une petite modification dans le formulaire (style colorer en bleu le petit texte "Formulaire de test de rubans")
  3. lancer le formulaire en mode saisie de données
  4. Cliquer sur votre bouton de ruban
  5. Fermer votre formulaire, et constater qu'il ne vous demande pas si vous désirez enregistrer les modifications (la mise en bleu du texte), puisque vous venez de cliquer sur .

base de données dédiée aux test de rubans

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.

Relooking F_USYSRibbons

Voici un exemple de présentation :

Téléchargement de RubanPersoCours

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 :

idMso : 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 :

 

 

Types de contrôles possibles

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> ...

Police de caractères désactivée

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é"

type de contrôle générique : control

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> ...

Redéfinition des actions des idMso

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 :

VBA
Sub BDCFindDialog_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é :

Redéfinition des idMso

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 :

VBA
Sub 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é :

Démarrer à partir d'un ruban vide

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 :

  1. Ca n'a pas effacé le menu Fichier
  2. Ca a effacé la barre d'outils d'accès rapide
    (Quick Access Toolbar - QAT), que vous pouvez voir sur l'image de droite.

Barre d'outils d'accès rapide (QAT)

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".

Images prédéfinies imageMso

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 :

VBA
Function 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 :

VBA
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.

Téléchargement direct du ruban des 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.

Images personnalisées

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 !

.Zip qui contient des images de test

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

Importer les images avec loadImage

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 :

VBA
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 :

Différents formats et dimensions inadéquates

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.

PNG non supporté

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)

Importer les images avec getImage

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 :

VBA
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 :

Un CallBack nécessaire par image

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 :

VBA
Sub 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.

Tag

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 :

VBA
Sub 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.

Case à cocher et bouton bascule

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"/> ...

getPresssed

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 :

VBA
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"/> ...
VBA
Sub ValeurDefautBoutonBascule(ElementRuban As IRibbonControl, EnfonceOuPas) EnfonceOuPas = True End Sub Sub ValeurDefautCaseACocher(ElementRuban As IRibbonControl, EnfonceOuPas) EnfonceOuPas = True End Sub Sub 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.

Actions des cases à cocher et des boutons-bascule

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 :

VBA
Sub ClicSurcaseACocher(ElementRuban As IRibbonControl, Coche As Boolean) If Coche = True Then MsgBox "Vous venez de cocher" Else MsgBox "Vous venez de 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.

Paramètres des CallBack

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à :

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.

Interaction rubans-formulaires

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).

 

Cocher une case du formulaire depuis un ruban

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 :

VBA
Sub 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 :

VBA
Sub 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.

Valeur de la case à cocher du ruban vers le 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 :

Synchronisation d'une case à cocher du formulaire vers le ruban

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 : ElementRuban.CACDecede.Value = True ne fonctionne pas du tout.

 

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 :

VBA
Sub 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 as Boolean)) 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.

Syntaxe complète d'accès aux formulaires

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 :

Premier appel à getPressed

- 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 ?

Rappel du CallBack getPressed

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"/>

Impossibilité de ne rappeler qu'une seule procédure de rappel

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.

CallBack onLoad

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éation d'une variable publique de référence au ruban en cours

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).

 

 

 

 

Utilisation de la méthode Invalidate

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".

Synchronisation d'une coche dans le formulaire vers le ruban

 

 

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.

 

 

Evénement Sur Activation d'un formulaire pour synchroniser les cases à cocher automatiquement

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é :

  1. Le fait de cocher/décocher la case du ruban coche/décoche la case du formulaire
  2. Le fait de cocher/décocher la case du formulaire coche/décoche la case du ruban
  3. Le fait de changer d'enregistrement qui met à jour automatiquement la case à cocher du ruban

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.

Afficher un bouton selon la valeur d'une case à cocher

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 :

VBA
Sub 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 :

VBA
Sub 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 :

VBA
Option Compare Database Public VARRubanAfficheBouton As IRibbonUI Sub RUBAfficheBouton_onLoad(Ruban As IRibbonUI) Set VARRubanAfficheBouton = 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 :

VBA
Option 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 :

variables publiques VARRubanAfficheBouton et VARCocheVisible

Ce sont deux variables publiques que nous allons voir comment utiliser :

Public VARRubanAfficheBouton As IRibbonUI
Public VARCocheVisible As Boolean

Procédure CallBack  de chargement du ruban RUBAfficheBouton_onLoad

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

Procédure CallBack d'affichage ou non des boutons BDC_getVisible

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

Procédure CallBack en cas de clic sur la case à cocher CACAfficheBouton_onAction

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 :

  1. BDC_getVisible du bouton FileSave
  2. BDC_getVisible du bouton MasterViewClose

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 :

VBA et Access sur un même écran

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 :

VBA
Option 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 :

Gestion des onglets (Placement, masquage, activation, ...)

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".

Masquage des onglets

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:

Activation d'un onglet

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 :

VBA
Sub 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 :

VBA
Option Compare Database Public VARRubanFruitLegume As IRibbonUI Sub RUBPlacementOnglet_onLoad(Ruban As IRibbonUI) Ruban.ActivateTab "TABFruit" Set VARRubanFruitLegume = Ruban End Sub Sub BDCChangeOnglet_onChange(ElementRuban As IRibbonControl) VARRubanFruitLegume.ActivateTab "TABLegume" End Sub

Voilà : maintenant, le clic sur le bouton fonctionne :

Limiter les actions de l'utilisateur

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

Autoriser ou non les menus complets

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..

Groupes prédéfinis idMso

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> <tab idMso="TabHomeAccess"> <group id="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 :

Liste complète des onglets et groupes prédéfinis

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>

Tabset Outils de création de formulaires

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 :

  1. Création (idMso = TabFormToolsDesign)
  2. Organiser (idMso = TabFormToolsLayout)
  3. Format (idMso = TabFormControlTools)

Ces onglets contiennent des groupes, qui contiennent eux-mêmes des contrôles (boutons, listes, etc.)

TabSet personnalisé

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 :

Hiérarchie de tous les TabSet > Tab > Group > Control

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.

Principaux groupes des principaux onglets

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é.

Activation et visibilité

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.

Lanceur de boîtes de dialogue (dialogBoxLauncher)

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 :

VBA
Sub 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 :

Infobulles (screenTip et superTip)

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.

Simple texte (labelControl)

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 :

VBA
Sub 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.

Sous-groupes organisés (box)

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.

ButtonGroup

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.

Séparateurs verticaux (separator)

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 :

 

Zone d'édition (editBox)

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 :

XML
... <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 :

VBA
Sub 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é".

Mot de passe permettant l'apparition d'un menu

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é :

VBA
Option Compare Database Public VARVerifieMotDePasse As String Sub EDIMotDePasse_getText(ElementRuban As IRibbonControl, Texte) If VARVerifieMotDePasse = "" 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 :

VBA
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 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 :

VBA
Option Compare Database Public VARVerifieMotDePasse As String Public VARRubanEditBox As IRibbonUI Sub RubanEditBox_onLoad(Ruban As IRibbonUI) Set VARRubanEditBox = 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 :

VBA
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

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 :

VBA
Sub 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 :

VBA
Option 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 :

  1. Ajoutez la procédure CallBack TABConfidentiel_getVisible
  2. Ajoutez le rappel des procéduures CallBack (en fait surtout getVisible) de TABConfidentiel : c'est crucial, car à chaque tentative de mot de passe, le nouvel onglet doit décider s'il s'affiche ou pas
  3. Supprimez les MsgBox qui ne nous apportent finalement plus grand chose
VBA
Option 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" ' (3) VARVerifieMotDePasse = "Correct" Else MsgBox "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.

Liste déroulante (comboBox, DropDown)

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 :

VB
Sub 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" tag="Fruit fraise" label="Fraise"/>est interdit.

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.

ImageMso dans les listes déroulantes

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 :

Ajout d'images personnalisées

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 :

VBA
Sub 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

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 :

VBA
Sub 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.

Liste déroulante dynamique

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 :

VBA
Option 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) If NumeroEnCours = 0 Then ElementListe = "Rouge" If NumeroEnCours = 1 Then ElementListe = "Vert" If NumeroEnCours = 2 Then ElementListe = "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 :

  1. LIDCelebrite_getItemCount sera exécuté une seule fois
  2. LIDCelebrite_getItemLabel sera exécuté NombreElementListe fois (3), avec le paramètre NumeroEnCours qui vaudra :
    - 0 Lors du premier passage
    - 1 Lors du 2ème passage
    - 2 Lors du 3ème passage
    Et donc, la ligne barrée en rouge ne provoquera pas d'erreur, mais ne sera simplement jamais exécutée.

Evidemment, cet exemple est complètement ridicule, puisque dans ce cas, nous aurions eu intérêt à utiliser la première technique montrée plus haut.

Galerie d'icones (Gallery)

Bouton liste déroulante (splitButton)

Menu (dynamicMenu)

Changement d'aspect du ruban lors du rétrécissement (autoScale)

Raccourcis clavier (keyTip)

 

FIN ----------------

 

XXXXXXX

XXXXXXX

XXXXXXX

XXXXXXX