如何通过Excel VBA中的复制/粘贴捕获正在添加的工作表

时间:2009-04-06 17:28:11

标签: excel vba excel-vba excel-2003

我正在尝试捕获从另一个工作簿复制到工作簿中的工作表 从其他工作簿复制工作表时,不会触发Workbook_NewSheet事件。 仅当用户手动插入(Insert-> Worksheet菜单选项)或通过VBA将新工作表添加为ThisWorkbook.Worksheets.Add时,才会触发它。

我想要捕获的内容基本上是粘贴操作,这会导致新的工作表。

这可能来自以下任何用户操作:

  1. 用户通过拖动控制键(添加新工作表)来复制现有工作表
  2. 用户从其他工作簿复制工作表
  3. 用户从其他工作簿移动工作表
  4. 或以下任何VBA代码:

    SourceWorkbook.Sheets(“SourceSheet”).Copy Before:=TargetWorkbook.worksheets(“SheetNameIn Target”) 'copy across workbook'  
    SourceWorkbook.Sheets(“SourceSheet”).Move Before:=TargetWorkbook.worksheets(“SheetNameIn Target”) 'move across workbook'  
    ThisWorkbook. Sheets(“SheetName”).Copy 'copy within workbook'  
    

    如果您知道在VBA中捕获此操作/宏结果的任何方法都会非常有用。

    请注意,我不想避免这样的用户操作(因此我不想保护工作簿)但我想以编程方式处理粘贴的工作表来验证数据,如果类似的工作表已经存在则更新现有的工作表,而不是两张相同的数据。

5 个答案:

答案 0 :(得分:2)

SheetActivate事件将在所有这些情况下触发。显然它也会在很多其他情况下开火。这听起来像是一个皇家的痛苦,但您可以维护自己的工作表集合,并将您的集合与ThisWorkbook.Sheets集合进行比较,以查看是否添加/删除了某些内容。

如果您试图阻止它,可以考虑保护工作簿结构,而不是在代码中进行保护。

答案 1 :(得分:2)

复制工作表时,其名称将始终以“(2)”或“至少”)结尾。你可以像这样查看

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Sh.Name Like "*(2)" Then
        Application.DisplayAlerts = False
        Sh.Delete
        Application.DisplayAlerts = True
    End If
End Sub

答案 2 :(得分:1)

我所拥有的方式是

Private Sub Workbook_WindowActivate(ByVal Wn As Window)
ToggleMenuOptions False, 848, 889
End Sub

Private Sub Workbook_WindowDeactivate(ByVal Wn As Window)
ToggleMenuOptions True, 847, 848, 889
End Sub

Public Function ToggleMenuOptions(bToggle As Boolean, ParamArray ControlID() As Variant) As Boolean
'848 Move or Copy Sheet...
'889 Rename Sheet
'847 Delete Sheet
On Error GoTo lblError
Dim oControl As CommandBarControl, oControls As CommandBarControls, iControl As Integer
If IsMissing(ControlID) Then
    ToggleMenuOptions = False
    Exit Function
End If

For iControl = LBound(ControlID) To UBound(ControlID)
    For Each oControl In Application.CommandBars.FindControls(ID:=ControlID(iControl))
        oControl.Enabled = bToggle
    Next
Next
ToggleMenuOptions = True
Exit Function
lblError:
    If Err.Number Then
        ToggleMenuOptions = False
        Exit Function
    End If
End Function

Private Sub Workbook_NewSheet(ByVal Sh As Object)
MsgBox "Please use Add New Project option in custom Toolbar to add new sheets!!", vbExclamation, "Not Supported"
Application.DisplayAlerts = False
Sh.Delete
Application.DisplayAlerts = True
End Sub

所以我的用户将无法重命名,添加或删除工作表。现在这很好用。

答案 3 :(得分:0)

在不保持单独的工作表集合的情况下,我能想到这样做的唯一方法是维护一个静态的工作表名称(或工作表名称)数组,并在每次SheetActivate事件触发检测时将其与工作簿中的实际工作表进行比较任何补充。如果您不希望/不能将列表保留在数组中,则始终可以使用隐藏表来存储列表。这是否比维持单独的集合更多或更少的痛苦是值得商榷的:)

答案 4 :(得分:0)

我正在处理类似的事情,但无法阻止任何用户菜单操作。我的纸张类型很重要 - 每张纸都是主纸或奴纸 - 每张主纸都在其下面的奴隶纸上总和,我需要保持这些配方干净。

我没有在额外的隐藏工作表中维护工作表列表,而是在每张工作表上定义2个隐藏名称,记录工作表索引与其链接主工作表的偏移量,以及对链接主工作表的引用。因此,如果我的工作表是(例如)来自其主工作表的+2个选项卡,那么在工作表激活/取消激活(不确定哪个在这个阶段更好地跟踪)如果插入,删除或移动任何内容,则此偏移将发生变化。这涵盖了移动或复制工作表所产生的大部分或全部事件。

如果工作表已移动,我会遍历工作簿并为每张工作表计算新的主/从索引参考。

当我得到相当稳定的时候会发布代码,但它似乎是一个可以在各种情况下工作的方案。