我正在使用SAP的BusinessObjects Analysis插件的Excel工作簿。每当工作簿打开时,都会触发变量选择提示,并允许用户输入值,然后使用这些值从后端选择数据并在Excel中以表格格式显示(Excel中的SAP BW查询的表示)。我面临的问题是以下问题......
每当提示选择完成并且正在处理选择时,如果您是垃圾邮件,请单击工作表选项卡以触发Worksheet.Activate
事件。问题是Worksheet.Activate
处理程序尝试使尚未设置的功能区对象无效。我想阻止它,我希望功能区只有在设置后才会失效。问题是,更改工作表时,功能区必须无效,以便加载功能区中的特定按钮,这些按钮对于每个工作表都是唯一的。激活工作表时无效无效。在加载自定义功能区之前,最好省去更改工作表的可能性。
这是我尝试过但没有取得任何成功:
我尝试在出现提示后立即使用Application.Interactive = False
禁用交互模式,并在执行AOCust_OnLoad(ribbon As IRibbonUI)
功能区onLoad
回调并设置功能区时重新启用它
我尝试在出现提示后立即使用Application.EnableEvents = False
停用所有事件,并在执行功能区onLoad
回调并设置功能区时重新启用它们。
我尝试将以下内容添加到Worksheet.Activate
回调中,但它永远不会退出可能需要的无限循环,因为功能区onLoad不是系统事件,因此永远不会被触发。
while ribbon is Nothing
'waiting for ribbon onload to fire and set the value
DoEvents
wend
第二种情况令人惊讶的是,根据我的理解,当事件被禁用时,如何触发Worksheet.Activate
事件。
您是否知道如何解决此问题,以便用户在设置功能区之前无法更改工作表?
如果您希望我在此说明中添加代码段,请与我们联系。
由于
编辑 - 添加代码
在ThisWorkbook中的Microsoft Excel对象
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If EnableEvents = True Then
Debug.Print "invalidate"
Call AOCust_Callbacks.AOCust_InvalidateRibbon
End If
End Sub
在模块“Custom_Ribbon”
中'Callback for Selections data onAction
Sub PROMPT(control As IRibbonControl)
EnableEvents = False
'more prompt-related code
End Sub
在模块'AOCust_Callbacks'中
Public EnableEvents As Boolean
'Callback for Ribbon OnLoad
Sub AOCust_OnLoad(ribbon As IRibbonUI)
Debug.Print "setting the ribbon"
'Start Highlighting for Workbook
StartHighlighting
Set AOCustRibbon = ribbon
Debug.Print "the ribbon is now set"
EnableEvents = True
End Sub
当我垃圾邮件时,一旦提示选择完成并且选择仍在处理时单击工作表选项卡,当我因为if语句尝试使功能区无效时,我不再遇到未设置变量的问题,但问题是没有执行onload功能。
答案 0 :(得分:0)
这可能不是最佳解决方案,但可以解决这个问题。
您可以使用全局变量来处理它。
在模块中放置如下内容
Public EventsEnabled As Boolean
Public Sub ModuleWithDisabledEvents()
EventsEnabled = False
Debug.Print EventsEnabled
EventsEnabled = True
Debug.Print EventsEnabled
End Sub
然后在您的工作表上激活将Activate
代码包装在查看此变量的if块中
Private Sub Worksheet_Activate()
If Not EventsEnabled Then
' Do activate code here
End If
End Sub
通过更改EventsEnabled
变量,即使启用了事件,您也可以让代码忽略Activate
程序。
<强>更新强>: 你在用丝带做什么?这就是我过去实施自定义色带的方式,并且没有经历过您的问题:
在我的XML文件中,我有以下内容:
<customUI onLoad="RibbonOnLoad" xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="customTab" label="Custom Tab">
<group id="customGroup" label="Custom Group">
<button id="customButton" label="Custom Button" imageMso="HappyFace" size="large" onAction="Callback" getVisible="GetVisible" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
然后在我的文件中,我有一个名为&#39; Ribbon&#39;其中包含:
Option Explicit
Option Private Module
Dim rib As IRibbonUI
Private Declare Function ShellExecute _
Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hWnd As Long, _
ByVal Operation As String, _
ByVal Filename As String, _
Optional ByVal Parameters As String, _
Optional ByVal Directory As String, _
Optional ByVal WindowStyle As Long = vbMinimizedFocus _
) As Long
#If VBA7 Then
Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
#Else
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
#End If
#If VBA7 Then
Function GetRibbon(ByVal lRibbonPointer As LongPtr) As Object
#Else
Function GetRibbon(ByVal lRibbonPointer As Long) As Object
#End If
Dim objRibbon As Object
CopyMemory objRibbon, lRibbonPointer, LenB(lRibbonPointer)
Set GetRibbon = objRibbon
Set objRibbon = Nothing
End Function
Public Sub RibbonOnLoad(ribbon As IRibbonUI)
Set rib = ribbon
Debug.Print "ribbon:-", ObjPtr(ribbon)
Sheet2.Cells(1, 1).Value = ObjPtr(ribbon)
End Sub
Public Sub RefreshRibbon()
On Error GoTo RibbonError
If rib Is Nothing Then
Set rib = GetRibbon(Sheet2.Cells(1, 1).Value)
If rib Is Nothing Then GoTo RibbonError
Else
rib.Invalidate
Exit Sub
End If
Exit Sub
RibbonError:
Debug.Print "There is an issue with the menu bar. Please restart the tool"
End Sub
Public Sub GetVisible(control As IRibbonControl, ByRef visible)
visible = True
End Sub
当功能区加载时,它会将其内存值设置为Sheet2
,然后当它刷新正在运行的功能区RefreshRibbon
答案 1 :(得分:0)
通过在选择提示加载之前使用Application.interactive = False
禁用鼠标事件或第一次禁用鼠标事件并在功能区加载时重新启用它们来解决问题。问题是SAP决定对第一个名为onBeforeFirstPromptsDisplay
的提示使用不同的回调。结果,我对工作簿中的提示回调的更改从未实际触发,因为只有在触发时才会执行回调通过工作簿提示自己。实施onBeforeFirstPromptsDisplay
之后一切正常。
感谢您的投入!