遗憾的是 Excel 并没有提供处理重命名工作表的事件,但是经过测试,在修改工作表名称时唯一能触发的事件是 Application.AfterCalculate 事件,这就为重命名工作表事件提供了可行的方法。我们可以声明一个 Application 级别事件来解决此问题,详细课程参考:使用 Application 级别事件。
示例:禁止重命名工作表
修改工作表名称,可能会产生一连串的问题,比如在其他的工作簿中对该工作表的引用将会失效,通过工作表名称引用工作表的代码也将出错。当然,在 VBA 中,我们可以使用工作表代码名称来避免引用失败,或者采取隐藏工作表标签或者保护工作簿的方法来禁止重命名工作表,但这些方法或多或少都有一定局限性,使用下面的 VBA 代码能完美解决这些问题。
以下示例在用户更改工作表名称时,弹出提示,提醒用户不要更改工作表名称,之后将工作表重命名为原始名称。将以下代码放于 ThisWorkbook 下。
'-------------------- ThisWorkbook --------------------
Public WithEvents App As Application
Public CurrentSheet As Worksheet
Public CurrentSheetName As String
Private Sub Workbook_Open()
Set App = Application
Set CurrentSheet = ActiveSheet
CurrentSheetName = CurrentSheet.Name
End Sub
Private Sub App_SheetActivate(ByVal Sh As Object)
Set CurrentSheet = Sh
CurrentSheetName = CurrentSheet.Name
End Sub
Private Sub App_AfterCalculate()
If CurrentSheetName <> CurrentSheet.Name Then
MsgBox "请勿更改工作表名称!"
' 触发工作表重命名事件后,需要执行的代码 - 例如,将工作表重命名为原始名称。
MsgBox "恢复工作表名称至原始名称!"
Application.EnableEvents = False '禁用事件以便我们可以更改工作表名称
CurrentSheet.Name = CurrentSheetName
Application.EnableEvents = True
End If
End Sub
示例:更改工作表名称时调用子过程
以下示例在用户更改工作表名称时调用子过程。
将以下代码放于 ThisWorkbook 下。
'-------------------- ThisWorkbook --------------------
Public WithEvents App As Application
Public CurrentSheet As Worksheet
Public CurrentSheetName As String
Private Sub Workbook_Open()
Set App = Application
Set CurrentSheet = ActiveSheet
CurrentSheetName = CurrentSheet.Name
End Sub
Private Sub App_SheetActivate(ByVal Sh As Object)
Set CurrentSheet = Sh
CurrentSheetName = CurrentSheet.Name
End Sub
Private Sub App_AfterCalculate()
If CurrentSheetName <> CurrentSheet.Name Then
MsgBox "工作表名称已更改!调用 RunAfterCalculate 子过程。"
CurrentSheetName = CurrentSheet.Name '还原工作表名称
Call RunAfterCalculate '调用 RunAfterCalculate 子过程
End If
End Sub
将以下代码放于模块下,添加你自己的代码,确保子过程只调用一次。
Public RunningAfterCalculate As Boolean
Public Sub RunAfterCalculate()
'确保子过程只调用一次
If Not RunningAfterCalculate Then
RunningAfterCalculate = True
' 在这里添加你的过程代码
MsgBox "调用 RunAfterCalculate 子过程一次 ..."
RunningAfterCalculate = False
End If
End Sub