UtterAccess HomeUtterAccess Wiki

Welcome Guest ( Log In | Register )

Custom Search
Edit Discussion
> Ribbon Design An Introduction    
Ribbon Design An Introduction

SeeAlso
MSDN Ribbon Design Guidelines
Gunter Avenius' AccessRibbon.de site

Introduction The ribbon, introduced with Access 2007, involves a completely different design approach to the menu system used in earlier versions and which it replaces.

Ribbons are created using Ribbon XML (eXtended Mark-up Language). All the ribbon structures, Tabs, Groups, Menus and commands are defined by the XML in a strictly defined hierarchy. As the XML must be “well formed” it leaves very little room for any errors in the code and often XML editors are used. This is not strictly necessary and it is a good idea to have an understanding of the resultant XML in any case.

All the ribbons can be defined with a single table of your database which is called USysRibbons. This table has the following fields: 1. ID (Primary Key, Autonumber field) 2. RibbonName (Text field, indexed with no duplicates) 3. RibbonXML (Memo Field) 4. Comment (Optional Text field)

The USysRibbons table MUST be held in the front end of your database. NOTE: Once you create the USysRibbons table, it will be regarded as a System table, and will not be visible in the Navigation Pane unless you customize your Navigation Pane to display System Objects.

Each record in the USysRibbons table corresponds to a different ribbon in your database And the RibbonName field defines the name of the field which will be used to reference the ribbon on your forms and reports.

Your VBA code also needs to reference these ribbons but cannot do so directly, you need to create global variables within your VBA code for each ribbon you create. – more later

Structuring Ribbon XML All Ribbon XML code appears within start and end tags, and each object within the ribbon is created with a start and end tag with a hierarchy, of Ribbon, Tabs and Controls.

To define your ribbon

CODE
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="onRibbonLoad1">



</customUI>

The line xmlns=http://schemas.microsoft.com/office/2006/01/customui defines the schema which Access needs to validate the ribbon.

The line onLoad="onRibbonLoad1" Defines the VBA code to be run when the ribbon is loaded, (this is termed a callback); in this case it runs the VBA sub (or function) ‘onRibbonLoad1’ This is normally used to assign the ribbon to its global variable (mentioned above).


Next you need to hide the existing tabs on the ribbon when your custom ribbon is loaded, this is done by adding the statement <ribbon startFromScratch="true" > and its closing tag

The XML then looks like:

CODE
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="onRibbonLoad1">
     <ribbon startFromScratch="true" >

     </ribbon>
</customUI>

Next you need to define the tabs on the ribbon; these also need to be within tags in the XML:

CODE
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="onRibbonLoad1">
     <ribbon startFromScratch="true" >
           <tabs>

           </tabs>
     </ribbon>
</customUI>

and add the first Tab:

CODE
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="onRibbonLoad1">
     <ribbon startFromScratch="true" >
           <tabs>
                 <tab id=“FirstTab” label=“File” >
                 </tab>
           </tabs>
     </ribbon>
</customUI>

And add a second tab

CODE
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="onRibbonLoad1">
     <ribbon startFromScratch="true" >
           <tabs>
                 <tab  id="ThirdTab" label="File" >
                 </tab>

                 <tab id="SecondTab" label="Records" >
                 </tab>
           </tabs>
     </ribbon>
</customUI>

Each ribbon command must appear within a ribbon group’s start and end tags, so adding two groups to each tab gives:

CODE
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="onRibbonLoad1">
     <ribbon startFromScratch="true" >
           <tabs>
                 <tab  id="ThirdTab" label="File" >
                       <group id="grp1" label="Quit" >
                       </group>
                       <group id="grp2" label="Open" >
                       </group>
                 </tab>

                 <tab id="SecondTab" label="Records" >
                       <group id="Tab2grp1" label="Add and Delete" >
                       </group>
                       <group id="Tab2grp2" label="Navigation" >
</group>
                 </tab>
           </tabs>
     </ribbon>
</customUI>


At this point you can add ribbon command controls between the start and end tags of each group.

CODE
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="onRibbonLoad1">
 <ribbon startFromScratch="true" >
   <tabs>
     <tab  id="FirstTab" label="File" >
       <group id="tab1grp1" label="Quit" >
         <button id="btn1" size="large" label="Close" imageMso="FileCloseDatabase" onAction="fFunctionName1"   />
       </group>
       <group id="tab1grp2" label="Open" >
         <button id="btn2" size="large" label="Open File" imageMso="FileOpenDatabase" onAction="fFunctionName2"/>
       </group>
     </tab>
     <tab id="SecondTab" label="Records" >
       <group id="tab2grp1" label="Add and Delete" >
         <button id="btn3"  size="large" label="Delete Record"  imageMso="Delete"  onAction="fFunctionName3"/>
         <button id="btn4"  size="large" label="New Record"  imageMso="GoToNewRecord"  onAction="fFunctionName4" />
       </group>
       <group id="tab2grp2" label="Navigation" >
         <button id="btn5" label="First Record"  imageMso="MailMergeGoToFirstRecord"  onAction="fFunctionName5" />
         <button id="btn6" label="Previous Rcrd"  imageMso="MailMergeGoToPreviousRecord" onAction="fFunctionName6" />
         <button id="btn7" label="Next Record"  imageMso="MailMergeGoToNextRecord" onAction="fFunctionName7" />
         <button id="btn8" label="Last Record"  imageMso="MailMergeGotToLastRecord" onAction="fFunctionName8" />
       </group>
     </tab>
   </tabs>
 </ribbon>
</customUI>


The command line code <button id= " size="" label="" imageMso="" onAction=""/>

‘button’ defines this command line as a button, and will change for each command type, they must be unique in each of your ribbons.

Size= defines the size of the command on the ribbon, it can be size="large" or size="small", large defines that only one command will fit in the vertical space, small will allow three commands in the same vertical space. If omitted 'size' defaults to “small”.

imageMso defines the graphic to be shown on the command button, the Mso part meaning it is a predefined MS Office image, a list of them can be downloaded from http://www.microsoft.com/downloads/details.aspx?familyid=4329d9e9-4d11-46a5-898d-23e4f331e9ae&displaylang=en.

onAction="SomeFnName" defines which VBA function (or callback) is run when the ribbon control is clicked. A VBA routine must exist for the command button to call when it is activates e.g. Sub SomeFnName(ctrl As IRibbonControl)


Ribbon VBA Code Module

CODE
Option Compare Database
Option Explicit

Public gobjRibMain As IRibbonUI     'Create global variable to reference the ribbon

Public Sub onRibbonLoad1(Ribbon As IRibbonUI)
   ' customUI onLoad event handler for ribbon, Assigns ribbon to variable gobjRibMain
    Set gobjRibMain = Ribbon
End Sub

Sub fFunctionName1(ctrl As IRibbonControl)
  If MsgBox("Do you want to close the database?", vbQuestion + vbYesNo + vbDefaultButton2, "Close Database") = vbYes Then Quit
End Sub

Sub fFunctionName2(ctrl As IRibbonControl)
  MsgBox "Command Button: 'Open File' pressed ", vbInformation
End Sub

Sub fFunctionName3(ctrl As IRibbonControl)
   CurrentDb.Execute "DELETE * FROM Table1 WHERE ID=" & Nz(Forms!Form1.Id, 0), dbFailOnError
   Forms!Form1.Requery
End Sub

Sub fFunctionName4(ctrl As IRibbonControl)
   DoCmd.GoToRecord , , acNewRec
End Sub

Sub fFunctionName5(ctrl As IRibbonControl)
   DoCmd.GoToRecord , , acFirst
End Sub

Sub fFunctionName6(ctrl As IRibbonControl)
   DoCmd.GoToRecord , , acPrevious
End Sub

Sub fFunctionName7(ctrl As IRibbonControl)
   DoCmd.GoToRecord , , acNext
End Sub

Sub fFunctionName8(ctrl As IRibbonControl)
   DoCmd.GoToRecord , , acLast
End Sub

In your VBA code window you must add a reference (in the VBA window Menu – Tools – References) to the Microsoft office object library for A2007 this is “Microsoft Office 12 Object Library”, while for A2010 it is “Microsoft Office 14 Object Library”

Finally set the 'RibbonName' property of the form (or report) to the name you entered for the ribbon in the second column of the USysRibbons table.

The database with this ribbon and code functionality is attached Media:RibbonDemo.zip

Compiling and Error Handling with Ribbons Your ribbon XML must be compiled before it will run, this you do by closing and re-opening the database. A useful shortcut for this (suggested to the author by UA’s Albert Kallal), is to use the ‘Compact and Repair Database’ command which can be added to the Quick Access Toolbar, (In 2007 from the Office button, click Access options, select “Customize”, Choose ‘All Commands’ from the drop down box, locate ‘Compact and Repair Database’ and click the ‘Add>>’ button.)

Each ribbon is only ever loaded once, ie you open/run your Access Database, hence it is always worth including error handling as if your database comes across an unhandled error (in the accdb), all variable references, including ribbon variables, are lost and you would have to close and reopen the database to work with the ribbon variables your code uses.


Enabling and Hiding Ribbon Commands In addition to specifying the ID, Label Actions etc shown above you can also enable or disable a control, and hide or unhide a control. This is achieved by means of callbacks.

For each command, group or tab you can add the callback, the XML would be e.g. getEnabled=”cbGetEnable” where “cbGetEnable” is the name of the function to be called which will define the enabled state of the command

The VBA code would look like (e.g.):

CODE
Sub cbGetEnable (ctrl As IRibbonControl, ByRef Enable)
   Enable  = NZ(Forms!FrmMain!cbCompanyID, 0) > 0
End Sub

Similarly you can hide or show a control using a callback:, the XML would be e.g. getVisible =”cbGetVisible” where “cbGetVisible” is the name of the function to be called which will define the visible state of the command

The VBA code would look like (e.g.):

CODE
Sub cbGetEnable (ctrl As IRibbonControl, ByRef Visible)
   Visible = NZ(Forms!FrmMain!cbDepartmentID, 0) > 0
End Sub

There are many different types of control you can add to your ribbon which this article is not intended to cover - check the ‘See also’ references.

But you will also see that if you specify separate callbacks for all of your ribbon controls you will end up with perhaps hundreds of callbacks in your VBA code and XML code that is very difficult to read. Ribbon XML Control Codes describes a method where you can simplify both the Ribbon XML and the resultant VBA callbacks.

Hiding, unhiding, Enabling and Disabling Ribbon Controls When your application is running you may want to change whether a ribbon control is enabled or visible, this is achieved by 'invalidating' the control when it's status is to be updated. Hence, in the above example where a ribbon control is visible dependent on if a department is selected in the cbDepartmentID control on a form, then the invalidate command would be issued in the Afterupdate event of cbDepartmentID control using the structure: gobjRibMain.InvalidateControl "ID of Control You Want To Change", giving for example

CODE
Private Sub cbDepartmentID_AfterUpdate()
 gobjRibMain.InvalidateControl "btn10"

It is also possible to invalidate the whole ribbon (gobjRibMain.Invalidate) , but as every control on the ribbon is invalidated it will take longer to process.

Edit Discussion
Custom Search
Thank you for your support!
This page has been accessed 10,307 times.  This page was last modified 20:03, 12 September 2014 by doctor9. Contributions by BruceM and Pere_de_chipstick  Disclaimers