【问题标题】:Excel VBA multiple error handling in the same procedureExcel VBA 在同一程序中处理多个错误
【发布时间】:2016-02-25 21:54:16
【问题描述】:

我之前在 VBA 中成功使用过错误处理,但是在尝试使用多个错误处理块时,我不知道该怎么做。

我写的代码是这样的:

...

  On Error GoTo ErrorHandler1
  shpArrow1.Left = shpLine.Left + shpLine.Width * Min(Sqr(Calculations.Range("cVolProduct").value / Calculations.Range("cVolRefIndices").value), 2) / 2 - shpArrow1.Width / 2
  shpTag1.Left = shpLine.Left + shpLine.Width * Min(Sqr(Calculations.Range("cVolProduct").value / Calculations.Range("cVolRefIndices").value), 2) / 2 - shpTag1.Width / 2
  shpArrow2.Left = shpLine.Left + shpLine.Width * Min(Sqr(Calculations.Range("cVolUnderlyings").value / Calculations.Range("cVolRefIndices").value), 2) / 2 - shpArrow2.Width / 2
  shpTag2.Left = shpLine.Left + shpLine.Width * Min(Sqr(Calculations.Range("cVolUnderlyings").value / Calculations.Range("cVolRefIndices").value), 2) / 2 - shpTag2.Width / 2
  shpIndexLine.Left = shpLine.Left + shpLine.Width / 2 - shpIndexLine.Width / 2
  GoTo NoError1
ErrorHandler1:
  shpArrow1.Left = shpLine.Left - shpArrow1.Width / 2
  shpTag1.Left = shpLine.Left - shpTag1.Width / 2
  shpArrow2.Left = shpLine.Left - shpArrow2.Width / 2
  shpTag2.Left = shpLine.Left - shpTag2.Width / 2
  shpIndexLine.Left = shpLine.Left + shpLine.Width / 2 - shpIndexLine.Width / 2
  errorRelativeRisk = 1
NoError1:
  On Error GoTo 0

  On Error GoTo ErrorHandler2
  Output.ChartObjects("ChartHistoryUnderlyings").Activate
  ActiveChart.Axes(xlValue).CrossesAt = ActiveChart.Axes(xlValue).MinimumScale
  ActiveChart.Axes(xlCategory).CrossesAt = ActiveChart.Axes(xlCategory).MinimumScale
  GoTo NoError2
ErrorHandler2:
  errorHistUnderl = 1
NoError2:
  On Error GoTo 0

...

第二个错误处理块不起作用。我猜我没有正确退出第一个错误处理块。试图找到适合我但没有成功的答案。

非常感谢您的帮助!

【问题讨论】:

  • ... 分别代表Private Sub DoSomething()End Sub,还是有更多含义?我认为如果您在每个“块”之外extracted a method,您的代码可能更容易理解,每个“块”都有自己的错误处理;基本上你需要解开这个GoTo Mess
  • 是的,... 代表 sub 的开始和结束,但是有一些更简单的计算不应该影响错误处理。如果我只使用其中一个,基本上这两个错误处理块都可以工作,但是要同时使用这两个块,我可能必须通过制作两个短子来“隐藏”代码。

标签: excel vba error-handling


【解决方案1】:

在一个过程中有两个或多个错误处理子例程绝对是一种设计味道;这不是 VBA 错误处理的工作方式。

基本上你有这个:

Sub Foo()
    On Error GoTo ErrHandler1
    '(code)

ErrHandler1:
    '(error handling code)

    On Error GoTo ErrHandler2
    '(code)

ErrHandler2:
    '(error handling code)

End Sub

当第一个块发生错误时,VBA 跳转到ErrHandler1当它到达第二个块时仍然认为它处于错误处理子程序中

您需要在某个地方 Resume 告诉 VBA“我已经处理了我必须处理的所有事情”。

因此,您的ErrorHandler1 子例程应该以Resume 跳转结束,而不是“直接进入”NoError1 子例程:

Resume NoError1

ErrorHandler2 也应该以 Resume 跳转结束:

Resume NoError2

这样 VBA 就知道它已退出“错误处理模式”并返回“正常执行”。

但我强烈建议考虑单独的方法/过程而不是标记的子例程。

【讨论】:

    【解决方案2】:

    我认为你应该在每个错误处理代码之后输入End Sub

    【讨论】:

    • 你的意思是Exit Sub
    【解决方案3】:

    解决方案是申请On Error GoTo -1。 它重置了 VBA 中的错误处理,以便您可以使用多个 On Error GoTo 语句。

    >   Sub Asd()
        Range(Cells(7, 1), Cells(LastRow, 2)).Select
        On Error GoTo hello
        Selection.SpecialCells(xlCellTypeBlanks).Select
        Application.CutCopyMode = False
        Selection.FormulaR1C1 = "=R[-1]C"
    hello: 
    Cells(1, 1).Value = "Error 1"
    On Error GoTo -1
     Range(Cells(7, 4), Cells(LastRow, LastColumn)).Select
    On Error GoTo Hell
        Selection.SpecialCells(xlCellTypeBlanks).Select
        Application.CutCopyMode = False
        Selection.FormulaR1C1 = "0"
    Hell: 
    Cells(1, 1).Value = "Error 2"
    
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-04
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多