VBA专题10-21:使用VBA操控Excel界面之禁用和启用控件、组和选项卡
内置控件
通过分别使用enabled属性和getEnabled属性,可以在设计时永久地或者在运行时动态地禁用(和启用)内置控件。被禁用的控件在功能区中显示的是灰色。
例如,下面的示例XML代码禁用“复制”、“剪切”、“加粗”和“下划线”控件:

下图显示了功能区中被禁用的“复制”、“剪切”、“加粗”和“下划线”控件已变成灰色:

虽然在功能区中被禁用的控件是灰色的,但你仍然可以通过快捷键组合执行它们中的一些命令。例如,按Ctrl+C复制,按Ctrl+X剪切,但是不会执行Ctrl+B加粗和Ctrl+U加下划线。
也可以设置自已的条件来在运行时决定是否禁用某个内置控件。例如,下面的XML代码和VBA代码能够在运行时满足某条件时使“加粗”和“下划线”控件禁用(和启用):

注意,两个command元素的getEnabled属性都引用相同的getEnabledBU过程,当打开工作簿或者其中一个或两个控件被无效时调用这个过程。
在标准VBA模块中的代码:
Public myRibbon As IRibbonUI
'Callback for customUI.onLoad
Sub Initialize(ribbon As IRibbonUI)
Set myRibbon = ribbon
End Sub
'Callback for Bold getEnabled
Sub getEnabledBU(control As IRibbonControl, ByRef returnedVal)
returnedVal = ActiveSheet.Name ='Sheet1'
End Sub
在getEnabledBu过程中,如果活动工作表的名字是Sheet1则参数Enabled被设置为True。这使无效的控件启用。否则,这些控件被禁用。
在ThisWorkbook模块中的SheetActivate事件处理代码:
Private Sub Workbook_SheetActivate(ByVal Sh As Object) '在Excel 2010及以后版本中,使用下面的代码语句: myRibbon.InvalidateControlMso 'Bold' myRibbon.InvalidateControlMso 'Underline' '由于Excel 2007没有InvalidateControlMso方法, '使用下面的语句使功能区无效 'myRibbon.InvalidateEnd Sub
当激活不同的工作表时,SheetActivate事件处理使“加粗”和“下划线”控件无效。随后,调用相同的getEnabledBU过程,如果活动工作表的名字是Sheet1,那么两个控件都被启用,否则被禁用。
内置组和自定义组、内组选项卡和自定义选项卡(不允许)
不能够禁用控件和选项卡组,因为group和tab元素没有允许你这样做的enabled属性和getEnabled属性。
自定义控件
通过使用getEnabled属性禁用(和启用)自定义控件的方法与使用getVisible属性隐藏(和取消隐藏)自定义控件的方法相同。为了避免重复,这里介绍如何基于其ids禁用(和启用)某个自定义控件。
示例XML代码:

在Excel中打开该工作簿时,自动执行Initialize回调和GetEnabledAttnSh回调。
在Custom UI Editor中保存该文件,首次在Excel中打开该文件时,将会出现关于Initialize和GetEnabledAttnSh过程提示的错误消息,因为在标准的VBA模块中仍然没有这两个回调过程。单击“确定”关闭这些错误消息。
在标准VBA模块中的代码:
Public myRibbon As IRibbonUI
Public myID As String
'Callback for customUI.onLoad
Sub Initialize(ribbon As IRibbonUI)
Set myRibbon = ribbon
End Sub
'Callback for BtnInsert0 onAction
Sub Insert0(control As IRibbonControl)
MsgBox 'Insert 0 被单击.'
End Sub
'Callback for BtnInsert0 getEnabled
Sub GetEnabledAttnSh(control As IRibbonControl, ByRef returnedVal)
If control.ID Like myID Then
returnedVal = True
Else
returnedVal = False
End If
End Sub
'Callback for BtnInsert1 onAction
Sub Insert1(control As IRibbonControl)
MsgBox 'Insert 1 被单击.'
End Sub
'Callback for BtnUpdateRed onAction
Sub UpdateRed(control As IRibbonControl)
MsgBox 'Update Red 被单击.'
End Sub
要基于其在XML代码中的id禁用(和启用)某自定义控件,在现有的标准VBA模块或者新的标准VBA模块中包括下面的代码:
Sub EnableAll() Call RefreshRibbon('*')End Sub Sub DisableAll() Call RefreshRibbon('')End Sub Sub EnableInsert() Call RefreshRibbon('*Insert*')End Sub Sub EnableInsert1() Call RefreshRibbon('*Insert1')End Sub
执行上面的每个过程,看看效果。每个过程都调用RefreshRibbon过程来使所有的三个控件无效。参见下面的RefreshRibbon过程。是否启用(或禁用)某控件取决于在RefreshRibbon中参数传递的值。一旦使这些控件无效,就调用GetEnabledAttnSh过程,遍历共享这个相同回调的所有无效的控件。如果控件的id与参数值匹配,就启用该控件。否则,禁用该控件。
Sub RefreshRibbon(ID As String)
myID = ID
'Invalidate all controls on the Ribbon
'myRibbon.Invalidate
'Alternatively,it is best to invalidateonly the three controls
myRibbon.InvalidateControl 'BtnInsert0'
myRibbon.InvalidateControl 'BtnInsert1'
myRibbon.InvalidateControl 'BtnUpdateRed'
End Sub
如果要在活动工作表是标准工作表时启用全部三个控件,在活动工作表不是标准工作表时禁用这三个控件,只需在ThisWorkbook模块中包括下面的事件处理代码:
Private Sub Workbook_SheetActivate(ByVal Sh As Object) If TypeName(Sh) = 'Worksheet'Then Call EnableAll Else Call DisableAll End IfEnd Sub
下图展示了在执行EnableInsert过程后两个启用控件的Attn Sh组的情况:

同样,也可以基于tag属性而不是id属性来禁用(和启用)指定的自定义控件。
说明:本专题系列大部分内容学习整理自《Dissectand Learn Excel VBA in 24 Hours:Changingworkbook appearance》,仅供学习研究。注:如果你有兴趣,你可以到知识星球App的完美Excel社群下载这本书的完整中文版电子书。