【问题标题】:VBA error handling queryVBA 错误处理查询
【发布时间】:2012-03-03 22:00:36
【问题描述】:

我希望有人可以帮我看看并整理一下;我不得不说错误处理不是我的强项。我有下面的代码块,我一直在玩一些错误句柄,但这并不是我真正想要的。

我要做的是确保如果在任何时候出现错误,我打开的工作簿和 excel 实例都会正常关闭。

我确信有比我想出的更好、更简单的方法来实现这一点。

Sub QOScode()

On Error GoTo Fail

Dim app As New Excel.Application
app.Visible = False 'Visible is False by default, so this isn't necessary
Dim book As Excel.Workbook
Set book = app.Workbooks.Add(ActiveWorkbook.Path & "\QOS DGL stuff.xlsx")
'set up error handeling so if any thing happens the instance of excel with QOS sheets is closed gracefully

On Error GoTo Closebook
' MsgBox book.Sheets("ACLS").Cells(3, 3)
'Do what you have to do
' 

Closebook:
On Error Resume Next
book.Close SaveChanges:=False
app.Quit
Set app = Nothing
On Error GoTo 0
Fail:
End Sub

我想要的是一个单一的 On 错误 - 关闭应用程序并退出子程序。

任何人都可以提供一个示例,说明执行此操作的最佳做​​法是什么?

干杯

亚伦

所以下面这段代码,当工作表不存在时会报错,为什么不跳过“book.close”语句,我知道这会报错,但我希望它忽略它?

Sub QOScode()

On Error GoTo Closebook

Dim app As New Excel.Application
app.Visible = False
Dim book As Excel.Workbook
Set book = app.Workbooks.Add(ActiveWorkbook.Path & "\QOaS DGL stuff.xlsx") 'this sheet does not exist
'
MsgBox book.Sheets("ACLS").Cells(3, 3)
'Do what you have to do
'

Closebook:
Err.Clear
On Error Resume Next
book.Close SaveChanges:=False  'Object variable or with block variable not set (error 91)
app.Quit
Set app = Nothing
On Error GoTo 0

End Sub

【问题讨论】:

  • 那么,您当前的代码到底有什么问题?你希望什么不会发生?
  • 好吧,没什么 :) 当然,除非出于某种原因,一个错误过早地关闭了工作簿,然后调用了“on error GOTO Closebook”。即使使用“GOTO next”语句,它仍然会在 book.close SaveChanges:=False 上退出,并出现对象不存在的错误。有没有办法检查“书”是否存在,所以我可以做“如果书存在,那么 book.close”
  • 但是On Error Goto Next 将使它进入下一个语句,即app.Quit,此时一切都如你所愿......
  • 对不起,我的意思是在我当前的代码中输入“on error resume Next”,如果由于任何原因应用程序或工作簿意外关闭(没有它们的实例)。 “book.close”行中的代码错误我预计“继续下一个”它会跳过该行。我认为可能是 err.clear 可能是我需要的。

标签: vba error-handling excel


【解决方案1】:

我不太确定我是否理解您的目标。如果我这样做,我可能会不同意。

这是您正在开发的代码吗?我几乎从不在我正在开发的代码中使用错误处理。我希望解释器停止给出错误的语句。我想了解为什么会发生该错误。我可以做些什么来避免错误?我没有检查文件是否存在?我没有检查路径是否可访问?在我做任何其他事情之前,我会添加缺少的代码。

当您完成开发时,您应该计划不会出现未包含正确代码的错误情况。当然,这是不可能的;你不能让你的代码万无一失,因为傻瓜太聪明了。您发布给用户的版本必须包含错误处理。

但是您不能将此代码发布给用户,因为它会在没有警告的情况下停止。用户会猜测宏出了什么问题,或者他们会认为这是应该发生的事情吗?如果他们认为宏失败了,他们会对你说什么? “它没有达到我的预期,我不知道为什么。”你要回什么话? “你在做什么?”我认为我从未让用户对他们在失败时所做的事情给出可信的描述。至少你想要:

Call MsgBox("Sorry I have had an unrecoverable error within QOScode()." & _
            " Please record: " & Err.Number & " " & Err.Description & _
            " and report to extension 1234")

有了这个,用户就不会怀疑是否出了问题,并且您知道哪里出了问题,如果幸运的话,您知道为什么。

【讨论】:

  • 我正在调用第二个隐藏的应用程序,因此在开发时(确实在最终代码中)如果发生任何事情,我想要一个可以优雅地关闭它的例程,否则每次我运行调试并且发生了一些意想不到的事情,代码退出,我留下隐藏的应用程序仍在运行。所以就像你说的那样,涵盖所有可能性很重要,拥有可以优雅地关闭应用程序的代码,这意味着我对其余子程序的其他错误代码,我可以确定这总是被调用,在错误消息之后已显示,或已写入日志。
【解决方案2】:

为了巧妙地处理可预见的问题,您可以使用简短的错误处理来测试 Workbook 是否确实存在(即 If Not Wb Is Nothing Then,如果存在,则使用共同的结尾(即销毁对象)

第二个示例展示了如何在打开工作簿后为不可预见的错误添加额外的处理。我使用Err.Raise 故意创建错误,让用户可以选择如何继续(在出现错误后立即关闭工作簿或使工作簿可见)

顺便说一句,不要同时使用Dim 和New。我重写了
Dim app As New Excel.Application
转入
Dim xlApp As Excel.Application
Set xlApp = New Excel.Application

1.处理无工作簿问题

Sub QOScode()
    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application
    Dim Wb As Excel.Workbook
    On Error Resume Next
    Set Wb = xlApp.Workbooks.Add(ActiveWorkbook.Path & "\QOaS DGL stuff.xlsx")    'this sheet does not exist
    On Error GoTo 0    '

    If Not Wb Is Nothing Then
        MsgBox Wb.Sheets("ACLS").Cells(3, 3)
        'Do what you have to do
        Wb.Close False
    End If

    xlApp.Quit
    Set xlApp = Nothing
End Sub

2。处理没有工作簿和其他可能导致工作簿打开的不可预见的错误

Sub QOScode2()
    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application
    Dim Wb As Excel.Workbook
    Dim lngChk As Long
    On Error Resume Next
    Set Wb = xlApp.Workbooks.Add(ActiveWorkbook.Path & "\QOaS DGL stuff.xlsx")    'this sheet does not exist
    On Error GoTo 0    '

    If Not Wb Is Nothing Then
        On Error GoTo ProblemHandler
        MsgBox Wb.Sheets("ACLS").Cells(3, 3)
        'Do what you have to do

        'Deliberate error
        Err.Raise 2000, "test code", "Sample Error"
        Wb.Close False
    Else
        MsgBox "Workbook not found,code will now exit"
    End If

    xlApp.Quit
    Set xlApp = Nothing
    Exit Sub

ProblemHandler:
    'Test to see if workbook was still open when error happened
    If Not Wb Is Nothing Then
        lngChk = MsgBox("The code encountered an error" & vbNewLine & Err.Number & vbNewLine & "Do you want to close the file?", vbYesNo, Err.Description)
        If lngChk = vbYes Then
            'close book. Code will proceed to destroy app
            Wb.Close False
        Else
            'make workbook visible and leave code
            Wb.Visible = True
            Exit Sub
        End If
    Else
        MsgBox "The code encountered an error - the file was already closed at this point" & vbNewLine & "Error number " & Err.Number & vbNewLine, Err.Description
    End If
    'destroy app (either if the workbook was closed, or user chose to close it)
    xlApp.Quit
    Set xlApp = Nothing

End Sub

【讨论】:

  • 这将解决我遇到的问题,但有谁知道为什么我的代码即使使用“resume next 语句也会出错?为什么它不只是忽略“book.close False”在我的原始代码中添加一行?
  • 为提示干杯,我喜欢检查工作簿是否存在然后对其采取行动的想法,这就是我正在寻找的,因为我认为用逻辑处理可预见的错误并离开非常好对不可预见的事情进行错误处理。
【解决方案3】:

我在错误处理方面的 2 美分。

您应该始终进行错误处理。

一些原因

1)您不希望您的应用出现故障并让您的用户挂起!想象一下这会给他们带来的挫败感。

2)错误处理并不意味着您试图忽略错误。

3) 错误处理既不是防御性编程也不是攻击性编程。恕我直言,这是主动编程。

4) 很少有人知道您可以找出导致错误的行。我所说的属性是 ERL。考虑这个例子

Sub Sample()
    Dim i As Long
    Dim j As Long, k As Long

10  On Error GoTo Whoa

20  i = 5
30  j = "Sid"
40  k = i * j

50  MsgBox k

60  Exit Sub
Whoa:
70  MsgBox "Description  : " & Err.Description & vbNewLine & _
    "Error Number : " & Err.Number & vbNewLine & _
    "Error at Line: " & Erl
End Sub

5) 在工作表更改事件等子事件中,必须进行错误处理。想象一下,您已将 Enable Event 设置为 False 并且您的代码中断了!在您将事件设置回 true 之前,代码下次不会运行

6) 我可以继续下去 :-) 会推荐这个链接

主题:“犯错”是人之常情

链接:http://www.siddharthrout.com/2011/08/01/to-err-is-human/

提示:

使用MZ Tools。它是免费的!

我会这样写你的代码。

Sub QOScode()
    Dim app As New Excel.Application
    Dim book As Excel.Workbook

10  On Error GoTo Whoa

20  Set book = app.Workbooks.Open(ActiveWorkbook.Path & "\QOS DGL stuff.xlsx")

30  MsgBox book.Sheets("ACLS").Cells(3, 3)

    '
    'Do what you have to do
    '
LetsContinue:
40  On Error Resume Next
50  book.Close SaveChanges:=False
60  Set book = Nothing
70  app.Quit
80  Set app = Nothing
90  On Error GoTo 0
100 Exit Sub
Whoa:
110 MsgBox "Description  : " & Err.Description & vbNewLine & _
           "Error Number : " & Err.Number & vbNewLine & _
           "Error at Line: " & Erl
120 Resume LetsContinue
End Sub

【讨论】:

  • +1。 MZ Tools 在编写主要代码时非常有用,尤其是在公开发布时。
  • 是的。我经常使用的 MZ Tools 的一个有用功能是给我的代码行编号。 :)
  • +1 “很少有人知道 Erl” 是的,据我所知,这可能与它完全没有文档有关。微软很好地隐藏了这一点。
  • 你好,我同意你的说法而且你的 Whoa: 块是我会使用的那种想法(在生产代码中挑衅)。我的问题是即使在您的代码中也是如此。说“30”行会导致工作簿崩溃并抛出一个错误,称为“哇:”。代码仍然会在“book.close”行出错,脚本将停止而不是继续下一行“app.quit”
  • @DevilWAH:不,它不会停止 :) 你试过上面的代码吗?我刚刚通过创建一个名为 QOS DGL stuff.xlsx 的新工作簿对其进行了测试。错误发生在第 30 行,因为没有名为“ACLS”的工作表。它给出了错误消息并优雅地退出:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-13
  • 2014-05-01
  • 2014-02-20
相关资源
最近更新 更多