Correct implemention of Form ContextTabs and Ribbons (1 Viewer)

cosmarchy

Registered User.
Local time
Today, 08:49
Joined
Jan 19, 2010
Messages
116
I'm looking for some help with the ribbons in my Access database.

Currently there are two forms and each one has its own ContextTab which appears when the form is opened. There is also a main ribbon which is available when the database is opened.

The ribbon XML as defined in USysRibbons are:

MainRibbon
XML:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="OnRibbonLoad" loadImage="LoadImages">
    <ribbon startFromScratch="false">
        <tabs>
            <tab id="MainTab" label="Main Tab">
                <group id="MainTabGroup1" label="Main Tab Group 1">
                    <button id="btnDemo1" size="large" label="Demo 1"/>
                </group>
                <group id="MainTabGroup2" label="Main Tab Group 2">
                    <button id="btnDemo2" size="large" label="Demo 2"/>   
                </group>
                <group id="MainTabGroup3" label="Main Tab Group 3">
                    <button id="btnDemo3" size="large" label="Demo 3"/>
                </group>
            </tab>
        </tabs>
    </ribbon>
</customUI>
this is the main ribbon and is set in Access > Options > Current Database > Ribbon and Toolbar Options > Ribbon Name

Context1
XML:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" loadImage="LoadImages" onLoad="Context1_Load">
    <ribbon startFromScratch="false">
        <contextualTabs>
            <tabSet idMso="TabSetFormReportExtensibility">
                <tab id="ContextualTab1" label="Contextual Tab 1">
                    <group id="ContextualTab1Group1" label="Contextual Tab 1 Group 1">
                    </group>
                    <group id="ContextualTab1Group2" label="Contextual Tab 1 Group 2">
                    </group>
                </tab>
            </tabSet>
        </contextualTabs>   
    </ribbon>
</customUI>
this ContextTab appears when Form1 is opened and is set in Form1 > Ribbon Name

XML:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" loadImage="LoadImages" onLoad="Context2_Load">
    <ribbon startFromScratch="false">
        <contextualTabs>
            <tabSet idMso="TabSetFormReportExtensibility">
                <tab id="ContextualTab2" label="Contextual Tab 2">
                    <group id="ContextualTab2Group1" label="Contextual Tab 2 Group 1">
                    </group>
                    <group id="ContextualTab2Group2" label="Contextual Tab 2 Group 2">
                    </group>
                </tab>
            </tabSet>
        </contextualTabs>   
    </ribbon>
</customUI>
this ContextTab appears when Form2 is opened and is set in Form2 > Ribbon Name

For the VBA code, I have this in a module:
Code:
Private mRibbonUI As IRibbonUI

Public Function onRibbonLoad(ribbonUI As IRibbonUI)
    On Error GoTo errorHandler

    Set mRibbonUI = ribbonUI

errorHandler:
    Exit Function
End Function
this should run when MainRibbon is loaded and sets MRibbonUI

Form1 VBA
Code:
Private mRibbonUI As IRibbonUI

Private Sub Form_Activate()

    mRibbonUI.ActivateTab "ContextualTab1"
    
End Sub

Private Function Context1_Load(ribbonUI As IRibbonUI)
    On Error GoTo errorHandler

    If (mRibbonUI Is Nothing) Then
        Set mRibbonUI = ribbonUI
    End If
    
errorHandler:
    Exit Function
End Function

Form2 VBA code is identical to Form1 other than 1 is replaced by 2!!

Now the issue is that, when I open either Form1 or Form2, I get this error:

1664303746712.png


which then breaks to
Code:
mRibbonUI.ActivateTab "ContextualTab1"

It looks like mRibbonUI variable on the form is not initialised so ActivateTab fails.

So, my question is should the application and all forms all share the same ribbon or should all ribbons and ContextTabs all be in the scope of the form which activates them? As you can see from the code, the MainRibbon uses the mRibbonUI variable in the module and there are no issues here, but the forms have their own private mRibbonUI variable and this is not being set. Setting a break point in Context1_Load, I can see this is not being called hence mRibbonUI not being set.

I have had it suggested that all forms should have their own ribbons, but in order to replace the ribbons (main ribbon and contectTab ribbon) when a form is activated seems to go against what ContextTabs are for in the first place. Everytime a form is activated and deactivated (as would happen navigating between forms) would mean the whole ribbon is replaced.

What is the correct method for handling ContextTabs in a Ribbon application. Seems the mechanisms are there but little information to go with it (most examples deal only with a single ribbon without taking this further).

Thanks
 

theDBguy

I’m here to help
Staff member
Local time
Today, 08:49
Joined
Oct 29, 2018
Messages
21,473
Hi. You're probably not getting the context ribbon load callback to fire maybe because you declared it as Private?

PS. Oh it looks like you have it placed in the Form's module. Maybe try moving it to a Standard Module?

If you need help, maybe consider posting a sample db to demonstrate the problem.
 

cosmarchy

Registered User.
Local time
Today, 08:49
Joined
Jan 19, 2010
Messages
116
Hi @theDBguy

To be honest, it's probably easier to attach the DB rather than try to describe as it properly.

The only reason I declared as private was to try and avoid conflicts across different forms having the same named variables (up until this point, I was not sure whether this was necessary or the correct way or not to do this!!)

In order to see the problem, just open one of the forms 😁
 

Attachments

  • Context Menu.accdb
    548 KB · Views: 119

theDBguy

I’m here to help
Staff member
Local time
Today, 08:49
Joined
Oct 29, 2018
Messages
21,473
Hi. I just tried to fix the first Form. Maybe you could do the second one. Hope that helps...
 

Attachments

  • Context Menu.zip
    35.4 KB · Views: 118

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 23:49
Joined
May 7, 2009
Messages
19,245
What is the correct method for handling ContextTabs in a Ribbon application. Seems the mechanisms are there but little information to go with it (most examples deal only with a single ribbon without taking this further).
i don't believe you can Activate the contextual tab, since it is Not Loaded.
what you can do is Add another "general" purpose tab to your main Ribbon and "switch" to it whenever
you are in a Form/Report.

here "datasheet tools" tab is General purpose tab for all forms/reports.
 

Attachments

  • TR2Materials.accdb
    4.5 MB · Views: 134

MarkK

bit cruncher
Local time
Today, 08:49
Joined
Mar 17, 2004
Messages
8,181
Your ribbon onLoad callback needs to be a Public Sub in a standard module. Class module instance members are not visible to ribbon callbacks, and a form is a class.

Your Form_Activate event is occurring before your context ribbon onLoad callback, and in other cases--it seems--before the ribbon is available to be activated. A workaround is that you can set a timer, and then activate the tab.

If you are working with ribbons, it is worthwhile to write yourself a query called QSysRibbons, with SQL equal to "SELECT * FROM USysRibbons;" which basically mirrors the USysRibbons table as a visible non-system query.

Hope this helps,
 

Attachments

  • Context Menu.accdb
    992 KB · Views: 127

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 23:49
Joined
May 7, 2009
Messages
19,245
A workaround is that you can set a timer
when the two forms are open switching from one form to another has a "rubber band" effect on the ribbon.
 

cosmarchy

Registered User.
Local time
Today, 08:49
Joined
Jan 19, 2010
Messages
116
thanks guys.

I'll take a look at your suggestions once I've got to the weekend :D

Thanks for your help
 

cosmarchy

Registered User.
Local time
Today, 08:49
Joined
Jan 19, 2010
Messages
116
Ok, so we have a partial solution - thanks to all 😁

One of the suggestions relied on a timer which delayed the ribbon, which on the face of it would not have been too disastrous but from first glance appeared to create flickering in the ribbon, so I removed the timer and changed each forms code to activate the tab only if the ribbon is initiaised and then the ribbon is created. This seems to work with one slight annoyance...

Which was that it didn't solve the flickering!!

I initially thought the timer was creating a lag between switching between ribbons (which of course is partially true) but the flicker seems to be something to do with the fact that everytime a form is activated, the ribbon flicks between the home tab and the newly activated tab; so for when switching between form1 and form2, the ribbon starts on Contextural Tab 1, flicks to the Home tab and then to Contextural Tab 2.

It's quite distracting and doesn't do this in other applications (assume this can be stopped in Access too) so I'm wondering whether anyone has any ideas how to stop this happening?

Thanks
 

Attachments

  • Context Menu.accdb
    992 KB · Views: 133

Users who are viewing this thread

Top Bottom