La mise en oeuvre est (un peu) plus complexe que pour un commndbar.
Au niveau du fichier xml du ruban
Variabilisation du ruban
Il faut prévoir de récupérer le ruban dans une variable publique. Cela s'effectue par une fonction CallBack qui est appelée au chargement du ruban grâce à la propriété onLoad. Le xml doit prévoir cela dans la balise customUI:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="RibbonInitialize">
Propriétés du combobox
Au niveau du combobox, il faut prévoir trois propriétés qui renseigneront les procédures CallBack pour gérer l'alimentation du combobox et récupérer le choix opéré:
1 2 3 4 5 6
| <comboBox
id="cb1"
onChange="cbChange"
getItemLabel="cbGetLabel"
getItemCount="cbGetCount"
/> |
Voici le xml de base pour la gestion d'un combobox par vba
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="RibbonInitialize">
<ribbon startFromScratch="false">
<tabs>
<tab id="ribMain" label="Test" visible="true">
<group id="grActions" visible="true" label="Actions">
<comboBox
id="cb1"
onChange="cbChange"
getItemLabel="cbGetLabel"
getItemCount="cbGetCount"
/>
</group>
</tab>
</tabs>
</ribbon>
</customUI> |
Au niveau du code VBA
- On prévoit une variable publique qui récupère le ruban passé par la CallBack;
- On crée les macros renseignées dans le onLoad du ruban ainsi que dans les trois propriétés du combobox onChange, getItemLabel et getItemCount.
Ces macros seront écrites dans un module standard. On peut bien entendu prévoir un seul cbGetCount etcbGetItemLabel pour tous les combo à gérer avec un Select Case sur l'ID du control récupéré, comme pour les onAction des boutons.
Voici un exemple pour charger les noms des feuilles hormis la feuille active dans le combo et pour récupérer le nom choisi dans le combo. On remarque que le chargement s'effectue en deux temps:
- déterminer le nombre d'items du combobox (cbGetItemCount);
- charger chaque item (cbGetItemLabel). cbGgetItemLabel sera appelé le nombre de fois renseigné lors de l'exécution de cbGetItemCount.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| Option Explicit
Public MainRibbon As IRibbonUI
Sub RibbonInitialize(Item As IRibbonUI)
Set MainRibbon = Item
End Sub
Sub cbChange(control As IRibbonControl, text As String)
MsgBox text
End Sub
Sub cbGetCount(control As IRibbonControl, ByRef count)
count = Worksheets.count - 1
End Sub
Sub cbGetLabel(control As IRibbonControl, index As Long, label)
If index >= ActiveSheet.index - 1 Then
label = Worksheets(index + 2).Name
Else
label = Worksheets(index + 1).Name
End If
End Sub |
cbGetItemCount puis cbGetitemLabel seront appelés lors du rafraichissement du ruban grâce à MainRibbon.Invalidate. On pourrait aussi prévoir de ne rafraichir que le combobox avec MainRibbon.InvalidateControl "cb1". Dans l'exemple repris ci-dessus, on invoquera le rafraichissement du ruban lors d'un changement de feuille avec ce code, placé dans le module ThisWorkbook
1 2 3
| Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If Not MainRibbon Is Nothing Then MainRibbon.InvalidateControl "cb1"
End Sub |
Deux choses importantes:
- Le XML est sensible à la casse. Il faut être particulièrement attentif aux codages des propriétés: onChange <> onchange!!
- MainRibbon est une variable publique qui est valorisée UNIQUEMENT lors du chargement du ruban, c'est-à-dire AVANT le Workbook_Open. On ne sait pas le recharger par la suite, de sorte que si le code est arrêté suite à un débogage, la variable est réinitialisée. Cela veut dire qu'il faut prévoir le coup au niveau de Invalidate (avec un If Not MainRibbon Is Nothing Then ) et que le ruban ne sera plus dynamique après plantage, obligeant à fermer puis ouvrir le classeur pour le recharger. Il faut donc être particulièrement attentif à une gestion blindée des erreurs avec On Error...
Partager