确定在Excel VBA中插入或删除行/单元格时

时间:2016-03-14 01:13:26

标签: excel vba excel-vba worksheet

我试图找出如何确定在 Worksheet_Change 事件期间使用VBA在Excel中插入或删除行(或列)的时间,并遇到主题here。但是,在工作表中插入或删除行时,所提出的建议答案并未完全捕获所有实例,包括:

  1. 虽然它们捕获了插入或删除整个行的实例,但是它们不会捕获仅插入或删除一组单元格的实例,这些实例将向下或向上移动单元格向下或向上移动。

  2. 虽然它们捕获在USEDRANGE中插入或删除的行的实例,但它们不会捕获您在所使用范围之外插入的实例(例如,在输入数据的位置下方插入一行)。

  3. 鉴于上述陈述,我搜索了更多选项,但找不到任何选项。然后,我提出了我自己的解决方案,我在这里提供帮助。我也希望在同一时间获得有关任何缺陷或改进领域的反馈。

2 个答案:

答案 0 :(得分:1)

以下Excel VBA代码将确定用户是否插入或删除了整个行或一组单元格(向上或向下移动单元格)所有范围内或之外的所有单元格。

这是代码(也可以为列转换):

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Cells(Target.Row + Target.Rows.Count, Target.Item(1, 1).Column).ID = Target.Address
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Item(1, 1).ID <> "" Then
        MsgBox "deleted row"
    Else
        MsgBox "inserted row"
    End If
    Target.Item(1, 1).ID = ""
    Cells(Target.Row + Target.Rows.Count, Target.Item(1, 1).Column).ID = Target.Address
End Sub

实际上非常简单,并使用单元格标记来跟踪用户操作,然后您可以使用它来确定是否发生了插入或删除。

“等待?”你可能会说。 “有一种标记细胞的方法吗?”或者......“什么是细胞标记”。

嗯,单元格确实没有“tag”属性,但您可以改进“Cell.ID”属性并将其用作单元格的标记。将Excel文件另存为webform时,将使用“Cell.ID”属性的原始意图,但如果您不打算创建webforms,它也可以作为标记工作。唯一的缺点是当您关闭并保存文件时,无法使用工作簿保存它的值。但是,这是可以的,因为无论如何你都不需要保存标签值。

无论如何,我认为它运作良好。但是,如果您发现任何需要改进或缺陷的地方,请告诉我。

唯一的问题我可以想到,如果你点击它的话,它会不断地标记细胞,如果你最终没有对细胞进行更改,就会留下大量剩余的垃圾。但是,关闭工作簿时不会保存此文件,只有在文件打开时才会保存。

答案 1 :(得分:1)

好的,我回来了。还在测试,但到目前为止这是我的状态。它变得更加复杂,因为你必须跟踪一个额外的标签并清理自己。这是跟踪Excel对标记单元格的作用(它们是向下移动,向上移动等等)的问题。一旦该模式被弄清楚并完全陷入困境,那么我认为这应该有效。手指交叉。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Call TagCellManager(Target)
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim CurCel As Range, CurRow As Range
    Dim TagCel As Range, TagRow As Range
    Dim NxtCel As Range, NxtRow As Range

    Set CurCel = Target.Item(1, 1)
    Set CurRow = Cells(CurCel.Row, 1)
    Set TagCel = Cells(CurCel.Row + Target.Rows.Count, CurCel.Column)
    Set TagRow = Cells(CurCel.Row + Target.Rows.Count, 1)
    Set NxtCel = TagCel.Offset(Target.Rows.Count, 0)
    Set NxtRow = TagRow.Offset(Target.Rows.Count, 0)

    If TagCel.ID <> "" And TagRow.ID <> "" Then
        'ignore me. i'm entering data
    ElseIf NxtCel.ID <> "" Or NxtRow.ID <> "" Then
        MsgBox "row inserted"
        Set Target = Range(NxtCel.ID)
        Call TagCellManager(Target)
    ElseIf CurCel.ID <> "" Or CurRow.ID <> "" Then
        MsgBox "row deleted"
        Set Target = Range(CurCel.ID)
        Call TagCellManager(Target)
    End If
End Sub

Sub TagCellManager(Target As Range)
    Dim CurCel As Range, CurRow As Range
    Dim TagCel As Range, TagRow As Range
    Dim NxtCel As Range, NxtRow As Range

    Set CurCel = Target.Item(1, 1)
    Set CurRow = Cells(CurCel.Row, 1)
    Set TagCel = Cells(CurCel.Row + Target.Rows.Count, CurCel.Column)
    Set TagRow = Cells(CurCel.Row + Target.Rows.Count, 1)
    Set NxtCel = TagCel.Offset(Target.Rows.Count, 0)
    Set NxtRow = TagRow.Offset(Target.Rows.Count, 0)

    CurCel.ID = ""
    CurRow.ID = ""
    TagCel.ID = Target.Address
    TagRow.ID = Target.Address
    NxtCel.ID = ""
    NxtRow.ID = ""
End Sub