Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VBA-如何临时禁用工作表。激活事件?_Vba_Excel_Business Objects - Fatal编程技术网

VBA-如何临时禁用工作表。激活事件?

VBA-如何临时禁用工作表。激活事件?,vba,excel,business-objects,Vba,Excel,Business Objects,我正在使用SAP的BusinessObjects Analysis插件编写Excel工作簿。每当工作簿打开时,都会触发变量选择提示,允许用户输入值,然后用于从后端选择数据,并在Excel中以表格格式显示数据(Excel中SAP BW查询的表示形式)。我面临的问题如下。。。 每当提示选择完成且正在处理选择时,如果垃圾邮件单击工作表选项卡,将触发工作表。激活事件。问题在于工作表.Activate处理程序试图使本身尚未设置的ribbon对象无效。我想防止这种情况发生,我希望功能区仅在设置后才失效。问题

我正在使用SAP的BusinessObjects Analysis插件编写Excel工作簿。每当工作簿打开时,都会触发变量选择提示,允许用户输入值,然后用于从后端选择数据,并在Excel中以表格格式显示数据(Excel中SAP BW查询的表示形式)。我面临的问题如下。。。 每当提示选择完成且正在处理选择时,如果垃圾邮件单击工作表选项卡,将触发
工作表。激活
事件。问题在于
工作表.Activate
处理程序试图使本身尚未设置的ribbon对象无效。我想防止这种情况发生,我希望功能区仅在设置后才失效。问题是,当工作表发生更改时,功能区必须无效,以便在功能区中加载对于每个工作表都是唯一的特定按钮。激活工作表时不失效不是一个选项。最好在加载自定义功能区之前,消除更改工作表的可能性

以下是我尝试过但没有成功的方法:

  • 我尝试在提示出现时立即使用
    Application.interactive=False
    禁用交互模式,并在执行
    AOCust\u OnLoad(功能区为IRibbonUI)
    ribbon
    OnLoad
    回调并设置功能区时重新启用该模式

  • 我尝试在提示出现时立即使用
    Application.EnableEvents=False禁用所有事件,并在执行功能区
    onLoad
    回调并设置功能区时重新启用它们

  • 我尝试将以下内容添加到
    工作表中。激活
    回调,但它从未退出无限循环,这可能是预期的,因为ribbon onLoad不是系统事件,因此从未触发

    while ribbon is Nothing
      'waiting for ribbon onload to fire and set the value
      DoEvents
    wend
    
  • 第二种情况令人惊讶的是,据我所知,当事件被禁用时,
    工作表.Activate
    事件是如何触发的

    您知道我如何解决此问题,以便用户在设置功能区之前无法更改工作表吗

    请让我知道您是否希望我在此说明中添加代码段

    谢谢

    编辑-添加代码

    在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
    
    在“自定义功能区”模块中

    在模块“AOCust_回调”中


    当我在提示选择完成且选择仍在处理时立即单击工作表选项卡时,我不再因为if语句而尝试使功能区无效时未设置变量的问题,但问题是未执行onload ribbon函数。

    这可能不是b这是一个最简单的解决方案,但却是一种变通方法

    您可以使用全局变量来处理它

    在模块中放置如下内容

    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
    变量,您可以让代码忽略
    激活
    过程,即使事件已启用


    更新: 你在用Ribbon做什么?这是我过去实现自定义Ribbon的方式,但没有遇到过你的问题:

    在我的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>
    

    加载功能区时,它会将其内存值设置为
    Sheet2
    ,然后在刷新运行
    RefreshRibbon

    的功能区时使用该值重新加载。通过在加载选择提示之前或第一次重新启用问题是SAP决定在BeforeFirstPromptSdisplay上对名为
    的第一个提示使用不同的回调。因此,我对工作簿中的提示回调所做的更改从未真正触发,因为只有在您自己通过工作簿。在实现了
    onbeforefirfirstpromptsdisplay
    后,一切正常。
    感谢您的输入!

    这是一个很好的解决方案,我最初考虑过这一点!我希望通过设置VBA事件属性来实现更健壮的实现,但这会起到作用。如果没有其他更健壮的解决方案,我会将其标记为正确答案。谢谢我以我设置EventsEnabled的方式实现了这一点当提示出现时将其设置为False,并在ribbon onLoad中设置ribbon后将其更改为True。现在的问题是,当我垃圾邮件单击时,ribbon onLoad根本不会执行。您可以发布任何代码吗?自定义ribbon的一个主要问题是它的文档记录非常糟糕。请查看我编辑的帖子-我添加了一些代码。我希望它有帮助。谢谢你这么快的响应。顺便说一句。你能看看我的更新吗。我认为从你的代码来看,问题是当你使它无效时,你正在丢失它的内存分配。调试功能区很难,因为调试器不能真正使用它,尽管我在你的代码中看不到你在哪里设置
    Application.EnableEvents=False
    。拥有一个全局变量
    EnableEvents
    不是一回事。是的,我知道。在发布代码片段之前,我已经去掉了这些代码。
    Private Sub Worksheet_Activate()
        If Not EventsEnabled Then
            ' Do activate code here
        End If
    End Sub
    
    <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>
    
    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