From: Guy on
Albert,

Thank you once again for your comprehensive response. Lots of food for
thought... Good work.

I was aware of many of the gotcha's eg. the ribbon load only occurs once and
you never know which ribbon is going to get loaded first because that is
dependant on user action ie. Which form they open.

While I digest your posting… I was also thinking about how you could reduce
the amount of form Ribbons perhaps by using the form activate and deactivate
events.

The activate event would customise the Ribbon for that form and the
deactivate event would remove the customisations, ensuring that the “1”
Ribbon was always left in a consistant state from which the new “active” form
could apply it changes.

However, I haven't put any of my thoughts into code yet so I don't know how
feasible this is.

Still plenty to work to do so I had best get on with it.

Your assistance much appreciated and I'm sure that most developers who read
this thread will have learnt something new.

Kind Regards,
Guy


"Albert D. Kallal" wrote:

> "Guy" <Guy(a)discussions.microsoft.com> wrote in message
> news:AAEC10E1-E16A-47DE-B72E-8E08116A4163(a)microsoft.com...
> > Hi Albert,
> >
> > Thank you for your comprehensive response.
> >
> > I wasn't aware that once the form was loaded/opened the forms public
> > functions would get called in preference to module public functions. This
> > could be useful so I will investigate this aspect further.
>
> Actually, a97 to a2003 worked this way also. So, most of my custom menu bars
> in previous versions DID in fact call code in the current active form.
>
> This does man that some forms did share the same menu bar. However, in all
> practical use, most of my complex forms did have a custom menu bar, but that
> menu bar for the most part did call code in the current active form (it
> makes sense to place code for a form in the form code module).
>
> >
> > Ideally I would like to use just 3 Ribbons:
> >
> > 1) Home - Which allows quick access to key forms, reports and tools such
> > as
> > database backup within the application and is shown only when the Main
> > Menu
> > is active.
>
> I think in the above case, I would simply build a xml ribbon,, and then
> specify this ribbon in the forms "other" tab. This will load up the ribbon
> for you, and you not need any code.
>
> > 2) Form - Which shows for each form the "Home" button which takes you back
> > to the Main Menu and Home Ribbon and the standard Records/Filters/Cut and
> > Paste groups plus custom Command actions that are relevant to that form.
> > So
> > for instance if it was the "Customer Invoice" form you could print the
> > Customer Invoice or if it was the "Budget" form you could export the
> > budget
> > to Excel. Some forms would have many Command actions available.
>
> Sure, to include the standard paste, cut etc, you can either build you own
> "group" that you add to each ribbon. However, it is MUCH easier to include
> the standard cut/paste menu "group" in your ribbon that you build for the
> current form.
>
> To make you "own" clipboard, you could use:
>
> <group id="Clipboard" label="Clipboard">
> <control idMso = "Copy"/>
> <control idMso = "Cut"/>
> <control idMso = "Paste"/>
> </group>
>
> however, it much easier to include the built in ones. For example, lets
> include both built in clipboard, and the "find" and filter group. You can
> go:
>
> <group idMso="GroupClipboard" />
> <group idMso="GroupFindAccess" />
> <group idMso="GroupSortAndFilter" />
>
> So, it is really easy to add the standard cut/copy to your existing ribbon.
>
> >
> > 3) Report - Which shows for each report the "Home" button plus the
> > standard
> > print/export/send mail groups and so on. It is unlikely that many custom
> > Command actions would be required for this Ribbon.
>
> Right...and again, I would build a new ribbon, but simply include some of
> the report groups. You do know how to "find" the above group names? (and as
> I mentioned...remember...they are case sensitive).
>
> To find the id of a command, or group, simply go:
>
> office button->access options (lower right)
> customize
>
> Note in the customizing window if you hold your mouse over a command button,
> you get the isoID of that button (it that last value enclosed in ()).
>
> NOTE VERY clearly how in addition to the buttons, the "groups" for each of
> those buttons are ALSO IN that list. So, you can easily grab the group for
> your report....
>
>
> > Currently I have about 20 individual Form Ribbons, however, in your
> > opinion
> > would it be better to have just 1 Form Ribbon and customise it
> > appropriately
> > when each form becomes active?
>
> I actually think it ok to have a ribbon for each form, especially if that
> ribbon has form specify commands. so, sure, "include" the standard clip
> group, and perhaps a general close button group for each form. but, I would
> certainly continue to build a ribbon for each form.
>
> > Assuming that there are pros/cons to both the above approaches and that we
> > are happy to continue with the multiple Form Ribbon method. The next
> > question
> > is maintaining references to each Ribbon so that we can hide/show or
> > enable/disable etc the Form Command actions.
>
> Ok, this is tough part! I just finished coding a solution that allows me to
> use a collection to "enable" and "disable" a button by name. However, the
> code is not finished, has some problems. However, it is *perfect* for
> migration existing applications, and you can simple code in the form as you
> always done.
>
> eg:
>
> MyRibbon.MyControls("button1").Enabled = True
> or
> MyRibbon.MyControls("button1").Visible = True
> or
> MyRibbon.MyControls("button1").Label = True
>
> The MyContorls collection is actually automatically populated by the ribbon
> load command I have. So, right now, this code is running as I write this,
> but there are still some design issues that need to be addressed.
>
> However, since my code is not ready, then your going to have to write code
> for each button that you want to enable, and disable. And further, you going
> to have to place that code in a standard code module (not the forms code
> module). And, worse, you going to have to setup a piece of code for each
> control that you need to enable and disable. Remember, the ribbon does NOT
> store the state of your enabled/disabled button.
>
> It was easy before, since if you enabled, or displayed a control in a menu
> bar, you could, or change that value at will. In the case of a ribbon, your
> code must hold these values in variables (which is why I love my code
> example...since you don't have to write ANY additional code, but use the
> above familiar syntax.
>
> > As previously stated I have tried to maintain the Ribbon references in a
> > custom Collection which is loaded via the Ribbon "OnLoad" event. However,
> > I
> > am having problems with:
> >
> > 1) Event timing
> > 2) Populating and Accessing the reference in the Collection
>
> Yes. I just wrote that code last night.
>
> A few got ya's that I just learned:
>
> The ribbon load event only fires once, and that is when the form loads.
> Additional loads of the form does NOT fire the load event. so, I do need a
> global collection of ribbons, and further, I need a routine that checks if
> the ribbon is already loaded.
>
> in a standard code module, I have for the global enabled, and disabled, I
> have
>
> Public Sub MyVisible(control As IRibbonControl, _
> ByRef visible As Variant)
> Dim f As Form
>
> If Forms.Count > 0 Then
> Set f = Screen.ActiveForm
> visible = f.MyRibbon.MyControls(control.ID).visible
> End If
>
> End Sub
>
>
> Public Sub MyEnable(control As IRibbonControl, _
> ByRef visible As Variant)
> Dim f As Form
>
> Set f = Screen.ActiveForm
>
> visible = f.MyRibbon.MyControls(control.ID).Enabled
>
>
> End Sub
>
> In addtion, my global load code in this same module is:
>
> Public Sub SetMyRib(frm As Form, Optional strRibbonName As String = "")
>
> Set f = frm
>
> If strRibbonName = "" Then
> strRibbonName = f.name
> End If
>
> f.RibbonName = strRibbonName
> ' the above code causes the ribbom to load, and fires the code below
> End Sub
>
>
> Public Sub MyRibbonLoad(ByRef nribbonUI As Office.IRibbonUI)
>
> Set f.MyRibbon.m_ribbon = nribbonUI
> Set f = Nothing
>
> End Sub
>
> In the above, I should be saving the ribbon into a global collection in
> addition to the "myRibbom"
>
> MyRibbom is a class object I built in code, and every form you make is going
> to define this. So, in each form that needs a custom ribbbom, I go:
>
> Option Compare Database
> Option Explicit
>
> Public MyRibbon As New clsRibbon
>
>
> I leave the ribbon setting in he "other" tab blank, because I need to pass
> the form name (the problem of screen focus).
> (so, the callig code just sets the ribbom value for the form...it less
> code).
>
> So in my forms on-load event, I go:
>
> Call SetMyRib(Me, "test1")
>
> me is the form, and "test1" is the name of the ribbom I want to load
>
> then, I have a class module for the robbom, it simply a colleciton of
> contorls that gets auto built for me
> clsRibbon
>
> Option Compare Database
> Option Explicit
>
> Dim colControls As New Collection
> Public m_ribbon As IRibbonUI
>
>
> Public Property Get MyControls(strC As String) As clsRibContorl
>
> Dim i As Integer
> Dim intGotOne As Integer
> Dim NewControl As New clsRibContorl
>
> ' look for contorl in colleciton, if not in, then add...
> For i = 1 To colControls.Count
> If strC = colControls(i).name Then
> intGotOne = i
> Exit For
> End If
> Next i
>
> If intGotOne = 0 Then
> ' add contorl, set defaults
> NewControl.Enabled = True
> NewControl.visible = True
> NewControl.Label = ""
> NewControl.name = strC
> colControls.Add NewControl, strC
>
> Set MyControls = NewControl
> Else
>
> Set MyControls = colControls(intGotOne)
> Me.m_ribbon.InvalidateControl (strC)
> End If
>
>
> End Property
>
>
> And, for each member of the control collection, we do need to "save" those
> values, so, I built a custom class control
> to STORE values for each ribbom contorl (since the robbion don't store
> them).
>
> it is:
> clsRibContorl
>
> Option Compare Database
> Option Explicit
>
> Dim m_enabled As Boolean
> Dim m_visible As Boolean
> Dim m_Label As String
> Dim m_name As String
>
>
>
> Public Property Let Enabled(bol As Boolean)
>
> m_enabled = bol
>
> End Property
>
> Public Property Get Enabled() As Boolean
>
> Enabled = m_enabled
>
> End Property
>
> '-----------
>
> Public Property Let visible(bol As Boolean)
>