删除行时需要 Excel VBA 运行时错误“424”对象

Posted

技术标签:

【中文标题】删除行时需要 Excel VBA 运行时错误“424”对象【英文标题】:Excel VBA Runtime Error '424' Object Required when deleting rows 【发布时间】:2017-03-07 14:20:12 【问题描述】:

我正在尝试比较 2 张工作表(Sheet1 和 Sheet2)之间的单元格值以查看它们是否匹配,如果它们匹配,请将 Sheet1 中的匹配值移动到预先存在的列表(Sheet3)并删除 Sheet1 中的值之后。

我在 Excel VBA 中使用反向 For 循环,但在我开始使用 newrange1.EntireRow.Delete 删除行之前一切正常。

这会在 VBA 中引发“424”对象需要错误,我已经花了几个小时试图解决这个问题,我不确定为什么会出现这种情况。我是否错误地选择了行?对象?

如果有人能指出正确的方向,将不胜感激。

这是我的代码:

Sub Step2()

    Sheets("Sheet1").Activate

    Dim counter As Long, unsubListCount As Long, z As Long, x As Long, startRow As Long
    counter = 0
    startRow = 2
    z = 0
    x = 0

    ' Count Sheet3 Entries
    unsubListCount = Worksheets("Sheet3").UsedRange.Rows.Count

    Dim rng1 As Range, rng2 As Range, cell1 As Range, cell2 As Range, newrange1 As Range

    ' Select all emails in Sheet1 and Sheet2 (exclude first row)
    Set rng1 = Worksheets("Sheet1").Range("D1:D" & Worksheets("Sheet1").UsedRange.Rows.Count)
    Set rng2 = Worksheets("Sheet2").Range("D1:D" & Worksheets("Sheet2").UsedRange.Rows.Count)

   ' Brute Loop through each Sheet1 row to check with Sheet2
    For z = rng1.Count To startRow Step -1
        'Cells(z, 4)
        Set cell1 = Worksheets("Sheet1").Cells(z, "D")
        For x = rng2.Count To startRow Step -1
            Set cell2 = Worksheets("Sheet2").Cells(x, "D")

            If cell1.Value = cell2.Value Then ' If rng1 and rng2 emails match
                counter = counter + 1
                Set newrange1 = Worksheets("Sheet1").Rows(cell1.Row)

                newrange1.Copy Destination:=Worksheets("Sheet3").Range("A" & unsubListCount + counter)
                newrange1.EntireRow.Delete
            End If
        Next
    Next
End Sub

这是我得到的错误:

【问题讨论】:

对我来说看起来不错。 newrange1 在本地窗口中包含什么? a) 你的内部循环产生了很多不必要的工作。 Application.Match 更好。 只是一个想法,因为我曾经遇到过一个有点相关的问题:插入新的代码行,例如 Set cell1 = NothingSet newrange1 = Nothing 之前将它们重新分配给新的范围(可能在...下一个...之前的循环结束。 ... 并在执行.EntireRow.Delete 之前在即时窗口中检查? newrange1.Address。 excelcampus.com/vba/vba-immediate-window-excel @GSerg @Ralph 看来@Ryan 可能已经解决了我的问题——我想差不多了——我需要将newrange1 设置为Nothing,然后将cell1 重置为下一个单元格。谢谢大家! 【参考方案1】:

您的内部循环会产生大量分步工作,最好使用Application.Match 完成。使用.UsedRange 检索 D 列中值的范围,最好从下往上查找最后一个值。

Option Explicit

Sub Step2()

    Dim z As Long, startRow As Long
    Dim rng2 As Range, wk3 As Worksheet, chk As Variant

    startRow = 2
    z = 0
    Set wk3 = Worksheets("Sheet3")

    ' Select all emails in Sheet1 and Sheet2 (exclude first row)
    With Worksheets("Sheet2")
        Set rng2 = .Range(.Cells(2, "D"), .Cells(.Rows.Count, "D").End(xlUp))
    End With

    With Worksheets("Sheet1")
        For z = .Cells(.Rows.Count, "D").End(xlUp).Row To startRow Step -1
            chk = Application.Match(.Cells(z, "D").Value2, rng2, 0)
            If Not IsError(chk) Then
                .Cells(z, "A").EntireRow.Copy _
                    Destination:=wk3.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
                .Cells(z, "A").EntireRow.Delete
            End If
        Next
    End With
End Sub

正如Ryan Wildry 所指出的,您最初的问题是继续循环并在删除行后进行比较。这可以通过在newrange1.EntireRow.Delete 之后添加Exit For 来避免,以便在找到匹配项后跳出内部循环。我认为您不应该“重置 cell1”,因为这可能会破坏循环迭代。

【讨论】:

干杯——我将把它集成到我的代码中。非常感谢!【参考方案2】:

我认为正在发生的事情是当您删除行时,您将丢失对范围 Cell1 的引用。所以我在删除完成后重置了它,并删除了对 newRange1 的引用。试一试,我已经完成了。我也稍微格式化了代码。

Option Explicit

Sub Testing()

    Dim counter         As Long: counter = 0
    Dim z               As Long: z = 0
    Dim x               As Long: x = 0
    Dim startRow        As Long: startRow = 2
    Dim Sheet1          As Worksheet: Set Sheet1 = ThisWorkbook.Sheets("Sheet1")
    Dim Sheet2          As Worksheet: Set Sheet2 = ThisWorkbook.Sheets("Sheet2")
    Dim Sheet3          As Worksheet: Set Sheet3 = ThisWorkbook.Sheets("Sheet3")
    Dim rng1            As Range: Set rng1 = Sheet1.Range("D1:D" & Sheet1.UsedRange.Rows.Count)
    Dim rng2            As Range: Set rng2 = Sheet2.Range("D1:D" & Sheet2.UsedRange.Rows.Count)
    Dim unsubListCount  As Long: unsubListCount = Sheet3.UsedRange.Rows.Count
    Dim cell1           As Range
    Dim cell2           As Range
    Dim newrange1       As Range

   ' Brute Loop through each Sheet1 row to check with Sheet2
    For z = rng1.Count To startRow Step -1
        Set cell1 = Sheet1.Cells(z, 4)
        For x = rng2.Count To startRow Step -1
            Set cell2 = Sheet2.Cells(x, 4)
            If cell1 = cell2 Then
                counter = counter + 1
                Set newrange1 = Sheet1.Rows(cell1.Row)
                newrange1.Copy Destination:=Sheet3.Range("A" & unsubListCount + counter)
                newrange1.EntireRow.Delete
                Set newrange1 = Nothing
                Set cell1 = Sheet1.Cells(z, 4)
            End If
        Next
    Next
End Sub

【讨论】:

要注意,基本上在newrange1.EntireRow.Delete之后添加这两行Set newrange1 = NothingSet cell1 = Sheet1.Cells(z, 4)就解决了。谢谢! @KyleYeo 我猜你在这方面错过了我的 cmets:***.com/questions/42650672/… 那么我们本可以早点解决它。 RyanWildry:感谢您对此做出全面的答复。 @Ralph 是的,我意识到——同时进来的 cmets 太多了......

以上是关于删除行时需要 Excel VBA 运行时错误“424”对象的主要内容,如果未能解决你的问题,请参考以下文章

Excel VBA:运行时错误 424,需要对象

在excel vba上划分sql查询

excel vba 运行时错误

在Excel VBA中,如何测试Excel.Range对象变量是否丢失其引用而不会引发运行时错误424 ..?

VBA背面运行Python的权限错误

代码运行时未调用 Excel VBA 功能区 getEnabled