Запрос обработки ошибок VBA - PullRequest
1 голос
/ 12 февраля 2012

Я надеялся, что кто-нибудь может посмотреть и привести в порядок это для меня;Я должен сказать, что обработка ошибок не является моей сильной стороной.У меня есть блок кода ниже, и я играл с некоторыми обработчиками ошибок, но это не так, как я действительно хочу.

То, что я пытаюсь сделать, - это убедиться, что если в какой-то момент произойдет ошибка, открытая книга и экземпляр 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

Мне нужно одно сообщение об ошибке - закройте приложение и выйдите из подпрограммы.

Может ли кто-нибудь предоставить пример того, что считается наилучшей практикой для этого?

Приветствия

Аарон

Таким образом, этот код ниже, когда лист не существует, вызовет ошибку, почему он не пропускает оператор "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

Ответы [ 3 ]

9 голосов
/ 12 февраля 2012

Мои 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

enter image description here

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
5 голосов
/ 12 февраля 2012

Чтобы аккуратно обработать предвиденную проблему, вы можете использовать краткую обработку ошибок, чтобы проверить, действительно ли существует Рабочая книга (т. Е. If Not Wb Is Nothing Then, если так с ней работает, с общим окончанием (т.е. уничтожением объекта)

Во втором примере показано, как добавить дополнительную обработку для непредвиденных ошибок после открытия рабочей книги. Я использовал Err.Raise для создания преднамеренной ошибки, чтобы дать пользователю выбор в отношении действий (закройте рабочую книгу сразу после ошибки или сделать рабочую книгу видимой)

В качестве отступления не используйте вместе Dim и New. Я переписал
Dim app As New Excel.Application
в
Dim xlApp As Excel.Application<br> 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
5 голосов
/ 12 февраля 2012

Я не совсем уверен, что понимаю вашу цель. Если бы я это сделал, я бы, вероятно, не согласился.

Этот код вы разрабатываете? Я почти никогда не использую обработку ошибок в разрабатываемом коде. Я хочу, чтобы интерпретатор остановился на утверждении, которое выдает ошибку. Я хочу понять, почему произошла эта ошибка. Что я мог сделать, чтобы избежать ошибки? Я не смог проверить, существует ли файл? Не удалось проверить доступность пути? Я добавлю отсутствующий код, прежде чем делать что-либо еще.

К тому времени, когда вы закончите разработку, вы должны планировать, чтобы не было условия ошибки, для которого вы не включили надлежащий код. Конечно, это невозможно; Вы не можете сделать свой код безошибочным, потому что дураки настолько изобретательны. Версия, которую вы выпускаете для пользователей, должна содержать обработку ошибок.

Но вы не могли предоставить этот код пользователям, так как он остановился бы без предупреждения. Будет ли пользователь догадываться, что что-то пошло не так с макросом, или он предположит, что это должно было произойти? Если они решат, что макрос не удался, что они скажут вам? «Он не сделал то, что я ожидал, и я не знаю, почему». Что ты собираешься сказать в ответ? "Что ты делал?" Я не думаю, что у меня когда-либо был пользователь, дающий правдоподобное описание того, что он делал во время сбоя. По крайней мере, вы хотите:

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

При этом пользователь не задается вопросом, если что-то пошло не так, и вы знаете, где оно пошло не так и, если повезет, почему.

...