工作表模块中的VBA调用Public Sub:Sheet和ThisWorkbook模块之间的串扰

时间:2013-11-17 00:54:10

标签: excel vba excel-vba

我很高兴这个有用,我想我会分享它......

它允许我在ThisWorkbook模块中使用通用事件处理程序来启动匿名ActiveSheet中的工作表特定代码。

我使用CalByName函数访问Sheet对象中的用户定义的Public方法。

我正在使用它来重新启动一个被自动恢复保存杀死的计时器,它运行良好。我把它放在两张纸上。

ThisWorkbook模块中:

Private Sub Workbook_AfterSave(ByVal Success As Boolean)
Dim ws As Worksheet
    Set ws = ActiveSheet
    On Error GoTo afterSaveFailed
    CallByName ws, "afterSave", VbMethod
    If debugEvents Then Debug.Print timeStamp & ": " & "AfterSave: afterSave called in sheet: " & ws.Name
    On Error GoTo 0
    Exit Sub
afterSaveFailed:
    If debugEvents Then Debug.Print timeStamp & ": " & "AfterSave: afterSave Failed in sheet: " & ws.Name
    Err.Clear
End Sub

然后在每个适用的工作表模块中:

Public Sub afterSave()
    'sheet specific after save handler
End Sub

2 个答案:

答案 0 :(得分:0)

CallByName是一种非常古老且众所周知的方法。 :)

同样在你的代码中

  1. 什么是debugEvents您可能想要使用Option Explicit
  2. 为什么_AfterSave而不是_BeforeSave?如果afterSave()对工作簿进行了更改,该怎么办?您必须在关闭前再次保存。
  3. 而不是粘贴每个适用工作表中的代码并创建重复代码,为什么不在模块中创建公共代码?

    Public Sub afterSave(oWs as Worksheet)
        With oWs
            'sheet specific after save handler
        End With
    End Sub
    

    最差情况

    假设每个工作表的afterSave不同。您始终可以使用Select Case。这将确保您将代码放在一个位置。您无需四处搜索代码。

    Public Sub afterSave(oWs As Worksheet)
        With oWs
            Select Case .Name
    
            Case "AAA"
    
            Case "BBB"
    
            Case "CCC", "DDD" '<~~ If two or more worksheet have the same code
    
        End With
    End Sub
    

答案 1 :(得分:0)

感谢您的评论。我的回复插入如下:

  

CallByName是一种非常古老且众所周知的方法。 :)

这就是为什么我没有授权帖子“CallByName”。

如果您阅读标题,那就是它的内容。我无法在网上找到解决方案,所以我必须找出自己的方法。我的观点不是关于CallByName,而是关于模块之间的交叉谈话以及使用CallByName达到最大效果,我并不是说CallByName是新颖的。 我想我可以使用RaiseEvents实现相同的目标,但我想这可能更直接。

我很高兴因为VBA让我做了我想做的改变:q

  

同样在你的代码中

What is debugEvents You might want to use Option Explicit

这是控制即时窗口噪声的全局标志。是的我总是使用显式选项,在这种情况下这样做。我认为这是给定的。

Why _AfterSave and not _BeforeSave? What if afterSave() makes a change to the workbook? You will have to save again before closing.

因为我正在做的事情需要在保存完成之后完成,而不是在它开始之前完成。 Autorecovery保存事件会杀死我正在运行的计时器,因此我需要在保存后重新启动它。

  

而不是粘贴每个适用的工作表中的代码   创建重复的代码为什么不在模块中创建公共代码?

     

Public Sub afterSave(作为工作表的oWs)       随着oWs           '保存处理程序后的表单       以End Sub结束

     

最坏情况场景:

因为它的“特定工作表”

  

假设每个工作表的afterSave不同。您   总是可以使用Select Case。这将确保你有你的   代码在一个地方。您无需四处搜索代码。

     

Public Sub afterSave(oWs As Worksheet)       随着oWs           选择Case .Name

    Case "AAA"

    Case "BBB"

    Case "CCC", "DDD" '<~~ If two or more worksheet have the same code

End With End Sub

好的,我会考虑一下:感谢您的建议:)

当我有通用功能时,我更喜欢使用Class Modules来处理它。对我来说这更整洁:我只是在工作表中实例化对象以显示通用功能,并且在您的建议中,我只需要检查一次。我还使用Class_InitializeClass_Terminate事件来透明地管理通用功能的生命周期。我无法使用ThisWorkbook对象中的通用代码执行此操作。

这就是我如何处理一般功能,对于特定于对象的功能,我的偏好是在实际对象中收集特定于对象的代码:我更喜欢害羞的对象。实际上没有必要将这些细节暴露给监管代码。另外,如果我正在处理工作表,我不必跳回到通用模块,我不必尝试记住我放置代码的位置或发明一些约定,因为它就在表单中。

非常感谢你花时间详细回复!