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

如何在Excel VBA中捕获通过复制/粘贴添加的工作表,vba,excel,excel-2003,Vba,Excel,Excel 2003,我正在尝试捕获从其他工作簿复制到工作簿中的工作表。 从另一个工作簿复制工作表时,不会触发Workbook\u NewSheet事件。 仅当用户通过(插入->工作表菜单选项)手动插入工作表时,或当您通过VBA将新工作表作为ThisWorkbook.Worksheets.add添加时,才会触发此选项 我试图捕获的基本上是一个粘贴操作,它将生成一个新的工作表 这可能来自以下任何用户操作: 用户通过按住控制键(添加新图纸)拖动现有图纸来复制该图纸 用户从其他工作簿复制工作表 用户从另一个工作簿中移动了工

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

我试图捕获的基本上是一个粘贴操作,它将生成一个新的工作表

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

  • 用户通过按住控制键(添加新图纸)拖动现有图纸来复制该图纸
  • 用户从其他工作簿复制工作表
  • 用户从另一个工作簿中移动了工作表
  • 或以下任何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中捕获此操作/宏结果的任何方法,这将非常有帮助


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

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


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

    < P>我所暗示的方式是

    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
    

    因此,我的用户将无法重命名、添加或删除工作表。这目前运行得很好。

    复制工作表时,其名称将始终以“(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
    

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

    我正在做类似的工作,但无法阻止任何用户菜单操作。我有一些表格,它们的类型很重要-每一张表格都是主表格或从表格-每一张主表格和它下面的从表格相加,我需要保持这些公式干净

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

    如果工作表已被移动,我将在工作簿中循环,并为每个工作表计算新的主/从索引引用


    当我得到这个合理的稳定性时,我会发布代码,但这似乎是一个在各种情况下都能工作的方案。

    这可能是一个选择。保护工作簿不是一个选项,因为我想为用户提供一个导入某些工作表的选项,因此当执行文件的旧版本复制或移动操作时,它不会添加新工作表,而是使用复制/移动数据中的数据更新文件中的现有工作表。“SheetActivate事件将在所有这些情况下触发”它不。。复制多张图纸时,第一张图纸只会触发一次。。维护一个单独的图纸集合是一件痛苦的事情,所以现在我已经从Ply菜单中选择了禁用“移动/复制图纸”选项,所以用户不能将图纸从文件的一个版本移动到另一个版本。我还处理了New Sheet以阻止添加新的Sheet。所以现在我已经完成了这个工具。但希望在下一版本的Excel中看到比Joel设计的long back更健壮的事件。