【问题标题】:Resume to a label not working as expected恢复到未按预期工作的标签
【发布时间】:2021-03-11 06:29:18
【问题描述】:

我在使用 Resume 时遇到了问题,虽然我通过使用 On Error GoTo 找到了另一个解决方案,但我仍然对为什么下面的代码不起作用感到困惑。发生初始错误是因为工作表名称“Sheet_1”已被占用。这意味着,在监视窗口中,在执行 Resume NameAgain 之前,err.number 的值为 1004。不是清除错误并跳回标签,而是发生错误 20(无错误恢复),代码移至 End If 行。

鉴于存在活动错误 1004,我无法理解为什么它的行为就像没有错误一样。我已经在该站点上搜索了错误 20 问题,但没有什么能真正为我解决这个问题,也没有让我理解它背后的逻辑。非常感谢任何帮助。

Sub ErrorTest()

Dim i as integer:i=1

NameAgain: On Error Resume Next
Worksheets("Main").Name = "Sheet_" & i
If Err.Number = 1004 Then
  i = i + 1
  Resume NameAgain
End If

End Sub

paxdiablo 评论后更新:

以上是试图复制但简化我遇到的问题的糟糕尝试。我正在使用的代码部分如下:

Activate CheckBook to use ActiveWindow
  CheckBook.Activate
  Set DestSheet = CheckBook.Worksheets.Add(After:=CheckBook.Sheets(1))
  On Error Resume Next
  v = 1
NameAgain:  DestSheet.Name = ExpBookName & "_" & v
                If Err.Number = 1004 Then
                    v = v + 1
                    Resume NameAgain
                End If
            On Error GoTo 0
            ActiveWindow.DisplayGridlines = False
            Set DestCell = DestSheet.Range("A2")

所以解决方法是将 On Error Resume Next 移动到标签行并使用 GoTo 代替 Resume。

【问题讨论】:

  • 没有发生错误。在实际发生错误之前,您无法访问Err。当完全没有错误时,您希望它包含什么?
  • 这一行出现错误:Worksheets("Main").Name = "Sheet_" & i 因为已经有一个名为"Sheet_1"的工作表
  • 抱歉,Ken,我上面提供的代码是我在一个更大的过程中遇到的问题的简化版本的尝试。正如您正确指出的那样,上面提供的代码不会通过 IF 标准。

标签: vba


【解决方案1】:

resume 语句是一种从错误处理程序返回到主(非错误处理)代码中的某个点并继续执行的方法。

在这种情况下,您明确声明您希望在发生错误时自动resume next

这在功能上等同于(类似VB的伪代码):

line:
    on error goto handler
    cause error
    resume line ' not in an error handler at this point '

handler:
    resume next

所以从技术上讲,在您尝试resume 到标签时,您并不是一个错误处理程序。

正确 声明您正在尝试做的事情将是一个简单的goto 而不是resume

【讨论】:

  • 您好 paxdiablo,由于您的评论,我已经编辑了我的帖子,使用 GoTo 确实是解决方案。我刚刚假设使用 Resume 会取代之前的 On Error Resume Next 指令,将 1004 重置为 0 并跳转到标签。仍然是 VBA 的新手,您的解释非常有道理。谢谢你的课!
【解决方案2】:

更正确的解决方案是编写不会故意产生错误或不使用 Goto 的代码。

Public Function GetNextSheetName(ByVal ipWb As Excel.Workbook, ByVal ipStemName As String) As String

    Dim mySheet As Variant
    Dim mySD As Scripting.Dictionary
    Set mySD = New Scripting.Dictionary
    For Each mySheet In ipWb.Sheets
    
        ' mySd.Count is a dummy entry to satisfy
        ' the Key and Item requirements for .Add.
        ' we are only interested in the Keys
        ' for use with the .Exists method later
        mySD.Add mySheet.Name, mySD.Count
        
    Next
    
    Do
    
        DoEvents
        
        Dim myIndex As Long
        myIndex = myIndex + 1
        
        Dim myNextSheetName As String
        myNextSheetName = ipStemName + "_" & CStr(myIndex)
        
    Loop While mySD.Exists(myNextSheetName)
    
    GetNextSheetName = myNextSheetName
       
End Function

现在允许

    Set DestSheet = checkbook.Worksheets.Add(After:=checkbook.Sheets(1))
    DestSheet.Name = GetNextSheetName(checkbook, ExpBookName)
    ActiveWindow.DisplayGridlines = False
    Set DestCell = DestSheet.Range("A2")

【讨论】:

  • 您好,freeflow,感谢您抽出时间介绍另一个使用调用函数的解决方案。我已经完成了 VBA 课程的一半,但我还没有深入了解如何创建函数。能够在我自己的项目中使用您的解决方案将加速我的学习,我非常感谢您的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-04
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多