"on error goto" 故障。如何处理连续错误并忽略最后一行命令

"on error goto" glitch. How to deal with a consecutive error and ignoring last row command

我刚刚在 vba

学习 abc

我一直在使用这段代码,根据另外 2 个自动填充列表。 我有一个客户列表,每个客户都有一个顾问,我需要填充每个客户所属的团队,并设法使用 VLookUp 应用程序关联顾问-经理-团队。

所以当我们有一位新的顾问加入并且还没有被添加到“顾问-经理”列表中时, 显然,我得到了一个错误。我尝试使用“On Error Resume Next”修复它,但它只是使用最后一个有效的团队名称将错误填充到单元格中并继续。 所以我插入了一个处理程序(见下面的代码),让它将单元格留空并继续前进,当出现一个错误时它工作正常,但当出现 2 个连续错误时:

  1. 该宏会将第一个单元格留空,但会使用最后一个有效团队名称在第二个单元格中填充错误。
  2. 即使在列表结束后它也会继续填充,忽略我为循环提供的条件(下面代码中的 NumRows)。

哪位大神能指导一下错误处理流程怎么修改吗?

Sub populateteam()
    Dim wbFollowUp As Workbook
    Dim wbList As Workbook
    
    Set wbFollowUp = ThisWorkbook
    Set wbList = Workbooks.Open("C:\<folders>\CSTeams.xlsx")
    
    Dim wsAkasaka As Worksheet
    Dim wsList As Worksheet
    
    Set wsAkasaka = wbFollowUp.Worksheets("Akasaka")
    Set wsList = wbList.Worksheets("All Japan")
    
    wbFollowUp.Activate
    
    Dim consultant As String
    Dim manager As String
    Dim team As String
    
    Dim x As Integer
    Application.ScreenUpdating = False
    NumRows = Range("b2", Range("b2").End(xlDown)).Rows.Count
    
    For x = 1 To NumRows    
        consultant = wsAkasaka.Range("b" & (ActiveCell.Row)).Value

        On Error GoTo handler:
        manager = Application.VLookup(consultant, wsList.Range("a13:c250"), 3, False)
        team = Application.VLookup(manager, wsList.Range("e2:F11"), 2, False)
        'The name of the manager in the consultant list and in the team list should be exactly the same,
        'including spaces before and after
        
        If IsEmpty(ActiveCell.Value) Then
            ActiveCell.Value = team
            ActiveCell.Offset(1, 0).Select
        End If
    Next

    Application.ScreenUpdating = True
    
handler:
    ActiveCell.Value = ""
    ActiveCell.Offset(1, 0).Select
    Resume Next
End Sub

您的错误处理未按预期进行。如果您阅读 Resume Statement 的文档,它说 Resume Next 执行以下操作:

Execution resumes with the statement immediately following the statement that caused the error.

因此,如果 manager = Application.VLookup(consultant, wsList.Range("a13:c250"), 3, False) 中出现错误,因为找不到 consultant。它将继续使用 next 行,即 team = Application.VLookup(manager, wsList.Range("e2:F11"), 2, False) 但由于 manager 未检索到,这再次进入错误处理程序。然后它再次处理 *next 行,即 If IsEmpty(ActiveCell.Value) Then.

所以实际的问题是你使用了.SelectActiveCell。您可能会从阅读 How to avoid using Select in Excel VBA 中获益。而不是使用 .Select 直接引用您的单元格(参见下面的代码):

Option Explicit

Public populateteam()
    Dim wbFollowUp As Workbook
    Set wbFollowUp = ThisWorkbook
    
    Dim wbList As Workbook
    Set wbList = Workbooks.Open("C:\<folders>\CSTeams.xlsx")
    
    Dim wsAkasaka As Worksheet
    Set wsAkasaka = wbFollowUp.Worksheets("Akasaka")
    
    Dim wsList As Worksheet
    Set wsList = wbList.Worksheets("All Japan")
    
        
    Application.ScreenUpdating = False
    
    Dim LastRow As Long
    LastRow = wsAkasaka.Range("B2").End(xlDown).Row
    
    Dim iRow As Long
    For iRow = 2 To LastRow ' start in row 2 and run to last row if you want to start from the active cells row use `ActiveCell.Row` instead of 2
        Dim consultant As String
        consultant = wsAkasaka.Cells(iRow, "B").Value

        Dim manager As Variant
        manager = Application.VLookup(consultant, wsList.Range("A13:C250"), 3, False)
        
        If Not IsError(manager) Then
            Dim team As Variant
            team = Application.VLookup(manager, wsList.Range("E2:F11"), 2, False)
            'The name of the manager in the consultant list and in the team list should be exactly the same,
            'including spaces before and after
            
            If Not IsError(team) Then
                With wsAkasaka.Cells(iRow, "B")  'replace "B" with the column letter where you want to write your team!
                    If IsEmpty(.Value) Then
                        .Value = team
                    End If
                End With
            End If
        End If
    Next iRow

    Application.ScreenUpdating = True
End Sub

Note that the "B" in the With statement needs to be adjusted to the column where you want to write the team value!

在您看到的代码中,我完全通过像 wsAkasaka.Cells(iRow, "B").Value 这样的完整单元格引用消除了 ActiveCell.Select 它现在使用循环中的索引 iRow

我还删除了错误处理并检查查找是否得出结果(这比错误处理更高效并且更容易完成)。因此,如果查找成功,代码只会继续执行以下步骤。如果发生错误,它会自动处理下一行 Next iRow.

只是一个旁注。 Excel 的行数超过了 Integer 的处理能力。因此需要声明行计数变量 Long。由于 VBA 中有 no benefit in using Integer,我建议始终使用 Long

如果您单步执行代码 line-by-line,您可以自己找到这些问题。事实上,只要错误处理没有像您预期的那样工作,您就应该单步执行代码 line-by-line 以确切了解发生了什么。

对于你的第一期,

The macro would leave the first one in blank but populated the second cell with an error using the last valid team name.

想一想当您有新顾问时您的代码 运行s 发生了什么:

  1. manager = Application.VLookup(consultant, wsList.Range("a13:c250"), 3, False)会抛出一个错误。请注意,manager 的值 不会 更新,因此将保持之前的值。
  2. 您的代码通过 handler 块,用“”填充单元格,移动到下一个单元格,然后 Resume Next 行直接将您带到 team = Application.VLookup(manager, wsList.Range("e2:F11"), 2, False)
  3. 现在,manager 的值与上次 运行 的值相同,因此 team 的值将与上次 [=53] 的值相同=].

我对你的 If IsEmpty(ActiveCell.Value) Then 循环有点困惑,所以这个建议可能不是你想要完成的,但我建议在你的 [=19] 中添加一个 Else 子句=] 语句,然后将行 team = Application.VLookup(manager, wsList.Range("e2:F11"), 2, False) 移动到该 Else 子句下。当使用现有的 consultant.

更新 manager 值时,这只会将 team 写入单元格

关于你的第二期,

It keeps populating even after the list ended, ignoring the condition I gave it for the loop (NumRows in code below).

你检查过NumRows的值了吗?这一行Range("b2", Range("b2").End(xlDown)).Rows.Count的价值比你想象的要大得多:超过100万