Excel VBA Worksheet_Calculate 不同工作簿的事件触发

vkn*_*les 5 excel vba

附加信息(阅读其余部分后应该有意义):如果我打开 Workbook1.xlsm,然后创建一个新工作簿 (Book1),我可以输入数据和公式,甚至像NOW(),Book1!Sheet1 中那样的易失性函数,而不会触发实例范围的重新计算。我知道这一点是因为我正在观看 Workbook1!SheetX 中的计算事件处理程序。

初步结论:Excel 并不总是自动重新计算所有打开的工作簿中的所有公式。相反,它仅重新计算活动工作表(或者可能是活动工作簿),直到发生某些情况。

在这种情况下,“某些东西”实际上隐藏了计算事件处理程序中的行。我删除了多行代码,发现如果删除这些Me.Rows(x).Hidden = True行,则不会发生实例范围的重新计算。应用过滤器是触发事件的简单方法,但是添加公式将在不使用过滤器的情况下产生相同的结果,因此它似乎与过滤器没有任何关系。

无论如何,隐藏行会以某种方式创建一个导致所有内容重新计算的条件。只有在宏隐藏 SheetX 中的行之后,才会执行 SheetX 中的计算宏,之后,无论我在哪个工作簿或工作表中输入数据,它都会执行。如果我随后通过 Windows 资源管理器打开第三个工作簿,则其中的任何更改都会立即触发计算宏。我可以在 Sheet1 中添加一个事件处理程序,并验证两个处理程序(SheetX 和 Sheet1)是否都在执行,并且 SheetX每次都会首先执行,即使更改是在 Sheet1 中。


注意:请不要因为隐藏行或单元格的更简单或更好的方法而分心。我确信有。我的问题与 Excel 中看似错误的问题有关,因此请重点关注事件的触发,除非问题与宏的编写方式有关。

情况:

Win7下使用Excel 2013。

Workbook1、SheetX 有 VBA 宏 Worksheet_Calculate()。SheetX 已启用数据过滤。

打开工作簿1。

使用“文件” | 打开一个新工作簿 新 | 空白作业簿。它的名字是Book2。

返回 Workbook1 并筛选 SheetX 中的一列(例如,仅显示 A 列中的值 3)。[您可以在 A4:C7 范围内的任意位置输入另一个公式。]

在 Book2 的单元格中输入一个值。

Workbook1 的 Worksheet_Calculate() 事件触发。这可以通过设置断点来演示。

此外,事件触发后,TAB 键在 Book2 中不再起作用,但在 Workbook1 中工作正常。这似乎特定于正在显示的工作表,因为如果您在 Book2 中创建 Sheet2,则 TAB 键将一直有效,直到您在 Sheet2 中输入某些内容,之后它将在 Sheet1 中工作,直到您在其中输入某些内容。反之亦然,令人恶心。

SheetX 包含以下内容。该宏的唯一目的是隐藏第 2 行和第 3 行,这些行在现实生活中包含用户不需要了解的参数。当使用过滤器时,行将变得不隐藏/可见。需要使用 A3 中的公式来确保每当工作表中的任何内容发生更改时都会触发 Worksheet_Calculate 事件。

    A      B      C 
1  data1 data2 data3    
2   
3  =A2      
4  3     A3     C5  
5  4     a3     C6  
6  3     A5     C7  
7  6     a6     C8  
Run Code Online (Sandbox Code Playgroud)

宏在这里:

Private Sub Worksheet_Calculate()

    'Hide rows 2 & 3, which are the rows containing parameters.
    'This is necessary because whenever an autofilter selection is removed,
    ' Excel redisplays hidden rows and rows with 0 height.

    On Error GoTo errHdlr

    'First ensure that the event does not loop.
    Application.EnableEvents = False

    'Have to unprotect and re-protect the sheet to make these changes.
    Me.Unprotect

    Me.Rows(2).Hidden = True
    Me.Rows(3).Hidden = True

    'Have to specify that the user can insert hyperlinks
    ' and use filters.
    Me.Protect , , , , , , , , , , True, , , , True

    'Now restore event handling.
    Application.EnableEvents = True

    Exit Sub

errHdlr:
    MsgBox "Error #" & Err.Number & ":" _
        & vbCrLf & "  " & Err.Description _
        & vbCrLf & "Please inform tech support.", vbCritical + vbOKOnly, _
        "Worksheet_Calculate"

    Resume Next

End Sub
Run Code Online (Sandbox Code Playgroud)

因为我对“Me”对象有点怀疑,所以我用调试器进行了检查,当我在 Book2 中时,这就是我在事件触发时发现的内容:

?我的名字

片X

?我.家长.姓名

工作簿1.xlsm

?activesheet.name

表1

?activesheet.parent.name

书2

很明显,“Me”对象引用 Workbook1 中的 SheetX,即使活动工作表是 Book2 中的 Sheet1。

感谢您的任何想法!

小智 3

application.caller事件在这里没有帮助,唯一的解决方法是在任何单元格中添加一些特定的文本行“My Report123”,例如单元格#A1。

当您调用Worksheet_Calculate()事件时,第一行应该是检查点。

if activesheet.range("A1")<>"My Report123" then exit sub
Run Code Online (Sandbox Code Playgroud)

这样就解决了excel错误的问题。

  • 我确信这是 Excel 中的一个错误,而且我不喜欢错误,这就是为什么我花了这么多时间来解决这个问题。它确实对我的应用程序没有产生重大影响,但我喜欢您关于短路虚假事件处理程序调用的执行的建议。但是,您不需要检查特定文本。您可以使用这种逻辑:`If Me.Name &lt;&gt; Application.ActiveSheet.Name Or Me.Parent.Name &lt;&gt; Application.ActiveSheet.Parent.Name then Exit Sub` (2认同)