【问题标题】:VBA Entirerow.Delete does not delete last cell in For EachVBA Entirerow.Delete 不会删除 For Each 中的最后一个单元格
【发布时间】:2021-05-27 09:29:10
【问题描述】:

如果 Excel 中的行早于所选日期,我有一些代码会删除它们。该函数有效,但不会删除最后一个值。

例如,如果我运行此代码:

Dim count As Long
count = 0
Dim searchRng As Range: Set searchRng = Range("Q9:Q5000")
Dim Cell As Range

For Each Cell In searchRng
    If ((Cell.Value < CDate(TextBoxDelete.Value)) And (Cell.Value <> "")) Then              
    
    count = count + 1
    
     Debug.Print ("Cell " & count & ": " & Cell.Value & " txtbox: " & TextBoxDelete.Value)      
    
     'Cell.EntireRow.Delete  ' This line deletes the Row                                                                    
    
End If

    Next Cell

如果我运行此代码,我会得到以下输出:

Cell 1: 03.03.2021 txtbox: 04.03.2021
Cell 2: 03.03.2021 txtbox: 04.03.2021
Cell 3: 03.03.2021 txtbox: 04.03.2021
Cell 4: 03.03.2021 txtbox: 04.03.2021

这是正确的,这些是比 TextBox.Value 更早的 4 个单元格

现在,当我使用相同的函数并在 DELETE 部分中添加注释时,输出如下所示:

Cell 1: 03.03.2021 txtbox: 04.03.2021
Cell 2: 03.03.2021 txtbox: 04.03.2021

代码是相同的,但你可以看到它现在只找到 2 个值 - 而不是 4 个!

找到的 2 个单元格被删除,但其他 2 个单元格没有被删除。

有没有人遇到过类似的行为?

编辑:在回答部分的所有帮助之后,我想出了这个:

For j = searchRng.count To 1 Step -1
    If ((searchRng(j).Value < CDate(TextBoxDelete.Value)) And (searchRng(j).Value <> "")) Then
    
    count = count + 1
    
    Debug.Print ("Cell " & count & ": " & searchRng(j).Value & " txtbox: " & TextBoxDelete.Value)
     
    searchRng(j).EntireRow.Delete                                                                           ' Delete Call for the Row
     
    End If
     
    Next j

这是有效的代码还是有任何缺陷?运行它正是我需要的。

【问题讨论】:

  • 这是一个常见问题。您正在删除要迭代的范围内的行。这意味着 for each 会混淆。您需要更改循环设计,以便向后迭代,以便删除不会影响即将发生的事情您可以通过使用常规的 for next 循环来做到这一点,例如对于 myItem = myItems.count 到 1 步 -1 等
  • 那么在我的情况下你会如何修改它?我们可以为 searchRange.Count -1 中的每个单元格做些什么吗?
  • 这能回答你的问题吗? VBA Excel delete rows with specific value
  • 这个问题已经很常见了。检查两个答案

标签: excel vba foreach


【解决方案1】:

你正在修改你正在迭代的东西。所以一旦你删除了第一行,第二行就变成了你已经处理过的第一行,所以迭代在原来的第 3 行继续,现在是迭代中的第二项。

有同样的问题,但在 java 中有一些很好的答案here

【讨论】:

    【解决方案2】:

    如果使用循环,您通常需要使用For i = x to 1 Step -1 类型的循环来删除行。另一种方法是使用Application.Union建立一个删除范围,然后一次性删除所有内容。

    以下是您应该如何调整代码的示例(未经测试);

    Sub ExampleDelete()
        Dim SearchRng As Range: Set SearchRng = Range("Q9:Q5000")
        Dim i As Long, Cell As Range
        
        For i = SearchRng.Cells.count To 1 Step -1
            Set Cell = Application.WorksheetFunction.Index(SearchRng, i)
            If ((Cell.Value < CDate(TextBoxDelete.Value)) And (Cell.Value <> "")) Then
                Debug.Print ("Cell " & i & ": " & Cell.Value & " txtbox: " & TextBoxDelete.Value)
                'Cell.EntireRow.Delete  ' This line deletes the Row
            End If
        Next Cell
    End Sub
    

    【讨论】:

    • 我认为这与我的编辑非常相似,它必须是 SearchRng.Cells 还是我可以立即使用 .Count 吗?
    • 不确定你的意思。 SearchRng.Cells.Count 只是给出了 For 循环的下限,如果您将来更改搜索范围,应该仍然可以按预期运行
    • 我的意思是,如果您查看我的代码,它几乎相同,不同之处在于我调用的是 SearchRng.Count 而不是 SearchRng.Cells.Count - 但它似乎没有更改,因为代码运行没有问题。我只是好奇^^
    • 如前所述:它未经测试,所以我只是在编辑我认为可行的内容。所以是的 - 如果 SearchRng.Count 给出所需的结果,你似乎可以使用它
    【解决方案3】:

    您可以通过收集单元格然后一次性删除它们来从上到下遍历您的 Range:

    Option Explicit
    
    Sub test1()
        Dim toDel As Range, Cell As Range
        Dim searchRng As Range: Set searchRng = Range("Q9:Q5000")
        
        ' debug var; remove it and replace it further with TextBoxDelete.Value
        Dim txtBoxValue: txtBoxValue = #5/10/2021#
        
        For Each Cell In searchRng
            If Cell < CDate(txtBoxValue) And Not IsEmpty(Cell) Then
                'collect matched cells into toDel
                If toDel Is Nothing Then
                    Set toDel = Cell
                Else
                    Set toDel = Union(toDel, Cell)
                End If
             Debug.Print ("Cell " & toDel.Cells.count & ": " & Cell.Text & " txtbox: " & txtBoxValue)
            End If
        Next Cell
        ' next statement deletes all the rows at once
        If Not toDel Is Nothing Then toDel.EntireRow.Delete
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多