【问题标题】:Case loop terminates before deleting all values案例循环在删除所有值之前终止
【发布时间】:2014-07-09 22:35:44
【问题描述】:

我是 VBA 的新手,我试图让我的代码循环遍历 K 行中大约 10,000 行整数并根据值删除行,我的代码可以工作,但一次只会做一小部分。请指教。

'Delete unwanted accounts
Dim Lcell As Long
Application.ScreenUpdating = False
Lcell = TransSheet.Cells(Rows.Count, "K").End(xlUp).Row
For a = 1 To Lcell Step 1
   Select Case Cells(a, 11).Value
      Case "1200", "652", "552"
         Cells(a, 11).EntireRow.Delete
   End Select
Next a
Application.ScreenUpdating = True

【问题讨论】:

标签: vba excel


【解决方案1】:

您可以对所有已识别的行执行一次删除:

'Delete unwanted accounts
Dim rngDel as range
Dim Lcell As Long, v

Lcell = TransSheet.Cells(Rows.Count, "K").End(xlUp).Row

For a = 1 To Lcell 
   v = Cells(a, 11).Value
    If v = "1200" or v = "652" or v = "552" Then
        If Not rngDel is Nothing Then
            Set rngDel = Application.Union(rngDel, Cells(a, 11).EntireRow)
        Else
            Set rngDel = Cells(a, 11).EntireRow    
        End If
    End If
Next a

If Not rngDel Is Nothing Then rngDel.Delete

【讨论】:

  • 使用Application.Union()的美丽一步
【解决方案2】:

从最后一行尝试到第一行。您正在删除行,因此您的编号被丢弃:

'Delete unwanted accounts
Dim Lcell As Long
Application.ScreenUpdating = False
Lcell = TransSheet.Cells(Rows.Count, "K").End(xlUp).Row
For a = Lcell To 1 Step -1
   Select Case Cells(a, 11).Value
      Case "1200", "652", "552"
         Cells(a, 11).EntireRow.Delete
   End Select
Next a
Application.ScreenUpdating = True

【讨论】:

    【解决方案3】:

    将此行添加到您的代码中

    Cells(a, 11).EntireRow.Delete
    a = a - 1
    

    这将处理由于行消失而发生的移位。


    附带说明,我个人使用以下方法删除多行。例如我要删除的行存储在Variant 数组DelRows() 中。您可以在运行时动态获取它们。这里我手动分配了一些随机行。

    Sub DeleteRows()
        Dim DelRows() As Variant
        ReDim DelRows(1 To 3)
    
        DelRows(1) = 15
        DelRows(2) = 18
        DelRows(3) = 21
    
        '--- How to delete them all together?
    
        Dim i As Long
        For i = LBound(DelRows) To UBound(DelRows)
            DelRows(i) = DelRows(i) & ":" & DelRows(i)
        Next i
    
        Dim DelStr As String
        DelStr = Join(DelRows, ",")
    
        ' DelStr = "15:15,18:18,21:21"
    
        ActiveSheet.Range(DelStr).Delete
    End Sub
    

    【讨论】:

    • 更喜欢向后迭代而不是操纵迭代器变量:)
    • 我认为这是一种有效的方法:递减增量变量使其与行集合保持同步(每个 .Delete.Count 减少 1)但我认为它效率低下(不必要的额外循环内操作),也可能是一个坏习惯,因为我们经常做一个 For i = ... 并使用一个迭代器 i 作为索引来并行对多个对象执行不同的操作,在这种情况下,您可能会得到不希望的结果-- 除非你为每个被迭代的对象添加另一个变量。
    • 当然这是另一种方法,但我个人不会使用它。 For/Each 构造是通用的,因此无论您是删除工作表中的行还是删除字典中的键或集合中的项目等,您都可以使用相同/相似的方法。此外,除非您事先知道需要删除什么,无论如何,您似乎都必须对集合进行迭代。
    • 是的,因此,与此示例不同,生产代码首先通过工作表创建要删除的行的通用字符串,然后在单个操作中将其删除。这比逐行执行要复杂一些,但删除在 Excel 中是一项非常昂贵的操作,对于性能密集型的东西,它有时会有所帮助。但是 +1 就在 For/Each 构造上。
    • 你看到蒂姆·威廉姆斯的回答了吗?这是另一种巧妙的方法。
    猜你喜欢
    • 2021-10-31
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-30
    • 1970-01-01
    • 2017-04-14
    • 2021-09-18
    相关资源
    最近更新 更多