我在 Word 中有一个自定义功能区选项卡,它是使用 CustomUI 编辑器创建的,其中包含许多可以正常工作的按钮。我试图找出是否可以在打开 Word 文档时设置此自定义选项卡的焦点。[或创建新文档时。]
目前,它默认只显示主页选项卡。我找到了打开和关闭自定义选项卡的方法,但不是“设置焦点”。
有任何想法吗?
您可以通过 Microsoft Active Accessibility 实现此目的,我已包含以下网页中的代码,但如果您想了解更多信息,请检查是否退出。(样本位于页面底部)。
http://www.wordarticles.com/Shorts/RibbonVBA/RibbonVBADemo.php
在一个新模块中,您拥有接受可访问性 API 的代码:
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
' Definitions and Procedures relating to Accessibility, used by the Ribbon VBA '
' Demonstration UserForm. The constants have been lifted from oleacc.h, and are '
' just a subset of those available. '
' '
' Tony Jollans, August 2008. '
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
Option Explicit
Public Const CHILDID_SELF As Long = &H0&
Public Const STATE_SYSTEM_UNAVAILABLE As Long = &H1&
Public Const STATE_SYSTEM_INVISIBLE As Long = &H8000&
Public Const STATE_SYSTEM_SELECTED As Long = &H2&
Public Enum RoleNumber
ROLE_SYSTEM_CLIENT = &HA&
ROLE_SYSTEM_PANE = &H10&
ROLE_SYSTEM_GROUPING = &H14&
ROLE_SYSTEM_TOOLBAR = &H16&
ROLE_SYSTEM_PAGETAB = &H25&
ROLE_SYSTEM_PROPERTYPAGE = &H26&
ROLE_SYSTEM_GRAPHIC = &H28&
ROLE_SYSTEM_STATICTEXT = &H29&
ROLE_SYSTEM_TEXT = &H2A&
ROLE_SYSTEM_BUTTONDROPDOWNGRID = &H3A&
ROLE_SYSTEM_PAGETABLIST = &H3C&
End Enum
Private Enum NavigationDirection
NAVDIR_FIRSTCHILD = &H7&
End Enum
Private Declare Function AccessibleChildren Lib "oleacc.dll" _
(ByVal paccContainer As Object, ByVal iChildStart As Long, ByVal cChildren As Long, _
rgvarChildren As Variant, pcObtained As Long) _
As Long
Public Function GetAccessible _
(Element As IAccessible, _
RoleWanted As RoleNumber, _
NameWanted As String, _
Optional GetClient As Boolean) _
As IAccessible
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
' This procedure recursively searches the accessibility hierarchy, starting '
' with the element given, for an object matching the given name and role. '
' If requested, the Client object, assumed to be the first child, will be '
' returned instead of its parent. '
' '
' Called by: RibbonForm procedures to get parent objects as required '
' Itself, recursively, to move down the hierarchy '
' Calls: GetChildren to, well, get children. '
' Itself, recursively, to move down the hierarchy '
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
Dim ChildrenArray(), Child As IAccessible, ndxChild As Long, ReturnElement As IAccessible
If Element.accRole(CHILDID_SELF) = RoleWanted And Element.accName(CHILDID_SELF) = NameWanted Then
Set ReturnElement = Element
Else ' not found yet
ChildrenArray = GetChildren(Element)
If (Not ChildrenArray) <> True Then
For ndxChild = LBound(ChildrenArray) To UBound(ChildrenArray)
If TypeOf ChildrenArray(ndxChild) Is IAccessible Then
Set Child = ChildrenArray(ndxChild)
Set ReturnElement = GetAccessible(Child, RoleWanted, NameWanted)
If Not ReturnElement Is Nothing Then Exit For
End If ' Child is IAccessible
Next ndxChild
End If ' there are children
End If ' still looking
If GetClient Then
Set ReturnElement = ReturnElement.accNavigate(NAVDIR_FIRSTCHILD, CHILDID_SELF)
End If
Set GetAccessible = ReturnElement
End Function
Private Function GetChildren(Element As IAccessible) As Variant()
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
' General purpose subroutine to get an array of children of an IAccessible '
' object. The returned array is Variant because the elements may be either '
' IAccessible objects or simple (Long) elements, and the caller must treat '
' them appropriately. '
' '
' Called by: GetAccessible when searching for an Accessible element '
' Calls: AccessibleChildren API '
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
Const FirstChild As Long = 0&
Dim NumChildren As Long, NumReturned As Long, ChildrenArray()
NumChildren = Element.accChildCount
If NumChildren > 0 Then
ReDim ChildrenArray(NumChildren - 1)
AccessibleChildren Element, FirstChild, NumChildren, ChildrenArray(0), NumReturned
End If
GetChildren = ChildrenArray
End Function
然后在您的ThisTemplate
orThisDocument
模块中:
Option Explicit
Private Sub Document_New()
SwitchTab "MyTab"
End Sub
Private Sub Document_Open()
SwitchTab "MyTab"
End Sub
Private Sub SwitchTab(TabName As String)
Dim RibbonTab As IAccessible
'Get the Ribbon as an accessiblity object and the
Set RibbonTab = GetAccessible(CommandBars("Ribbon"), ROLE_SYSTEM_PAGETAB, TabName)
'If we've found the ribbon then we can loop through the tabs
If Not RibbonTab Is Nothing Then
'If the tab state is valid (not unavailable or invisible)
If ((RibbonTab.accState(CHILDID_SELF) And (STATE_SYSTEM_UNAVAILABLE Or _
STATE_SYSTEM_INVISIBLE)) = 0) Then
'Then we can change to that tab
RibbonTab.accDoDefaultAction CHILDID_SELF
End If
End If
End Sub
给出的答案是不必要的复杂。最简单的解决方案是山姆回答的一部分。
您在自定义 XML 的自定义 UI 根节点中添加引用方法名称的“onLoad”-callback 属性。例如:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<ribbon startFromScratch="false">
<tabs>
<tab id="customTab" label="Custom Tab">
</tab>
</tabs>
</ribbon>
</customUI>
然后,您将具有正确签名的回调方法添加到文档中的模块。在此方法中,您将可以访问 IRibbonUI 对象,该对象可用于激活选项卡 - 无论是自定义选项卡还是内置选项卡。以下示例激活了一个 id 等于“customTab”的自定义选项卡:
Sub Ribbon_Load(ribbon As IRibbonUI)
ribbon.ActivateTab "customTab"
End Sub
我想通过简单地将所有代码复制到您工作的文档的模块中来对 CubeChase 的出色答案进行补充,该答案在 32 位实例上对我有用。
但是,当您处理 64 位实例时,需要更改一些代码。
而不是私有声明函数......只要:
Private Declare Function AccessibleChildren Lib "oleacc.dll" _
(ByVal paccContainer As Object, ByVal iChildStart As Long, ByVal cChildren As Long, _
rgvarChildren As Variant, pcObtained As Long) _
As Long
您需要声明Private Declare PtrSafe Function ... As LongPtr。因此函数变为:
Private Declare PtrSafe Function AccessibleChildren Lib "oleacc.dll" _
(ByVal paccContainer As Object, ByVal iChildStart As Long, ByVal cChildren As Long, _
rgvarChildren As Variant, pcObtained As Long) _
As LongPtr
另请参阅此网站以获取更多说明。
请注意,我使用此代码在 Excel 2016 中获取SolverStudio工作。我被http://solverstudio.org/using-studio/提到了这个页面
在您的自定义功能区选项卡被绘制到功能区后,您可以向模型发送密钥,如下所示:
Application.SendKeys "%keytosend%"
要找出需要发送的密钥,请打开工作簿并按Alt
。您会注意到键图标显示在选项卡上。
例如,要加载Page Layout
选项卡,您可以像这样发送密钥:
Application.SendKeys "%P%"
注意:您可能必须告诉自定义功能区代码要调用什么宏onLoad
。这可以在 XML 中使用Custom UI Editor
. 加载包含自定义功能区代码的工作簿,然后将onLoad
属性添加到<customUI></customUI>
标记,如下所示:
添加后,您必须创建一个与onLoad
您定义的函数匹配的 VBA 函数(在本例中为ribbonLoad)。在该函数中,您可以发送适当的密钥:
Sub ribbonLoad(ctl As IRibbonUI)
Application.SendKeys "%Y1%"
End Sub
我无法让 Sendkeys 解决方案足够可靠地工作。Active Accessibility 解决方案似乎有效,但需要的时间比我多一点。稍后我一定会回顾这种方法。
我确实发现如果自定义选项卡是选项卡列表中的第一个选项卡,则可以显示它。我使用了这些设置:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="customTab" insertBeforeMso="TabHome" label="CustomTabName">
感谢您的替代品。非常感激。