2016-02-28 52 views
3

一些背景資料:在錯誤退出子,並返回錯誤子調用錯誤子

前體:我有在其他錯誤處理的問題向四周看了看,但我一直沒能充分將答案應用於我的情況。我覺得像Err.Raise是我將如何完成我將在下面描述。但是,我不確定如何以我需要的方式實現它。如果我要使用Err.Raise如何在主子文件中引發錯誤代碼之前先退出Sub1-15?

話雖這麼說,

我有一個執行不同的程序過多大的Excel VBA項目。我選擇從一個主程序調用所有程序,以便日後維護各個程序。我在主分支中有一個On Error處理程序,如果在從該主例程中調用的任何例程中引發錯誤,我都會觸發該處理程序。

有沒有一種辦法:

  1. 記錄發生
  2. 錯誤消息
  3. 子是引發錯誤的
    • 錯誤類型
  4. 上的錯誤退出該子返回到主子,然後
    • 提起剛剛發生在其他子使得NotifyandRepair調用錯誤處理程序的錯誤?

我有以下的情況

Sub MainSub() 
    On Error GoTo NotifyandCorrect 
    Call Sub1 
    Call Sub2 
    ... 
    Call Sub15 
    Exit Sub 
NotifyandCorrect: 
    'Send copy of faulty file, the error code and Sub that caused it 
    'Then stop macro execution completely 
End Sub 

Sub Sub1() 
    On Error Exit Sub1 and raise current Error in MainSub(?) 
    'Perform data checks 
End Sub 

Sub Sub2() 
    On Error Exit Sub2 and raise current Error in MainSub(? 
    'Modify data groups 
End Sub 

Sub Sub15() 
    On Error Exit Sub15 and raise current Error in MainSub(? 
    'Clean up work 
End Sub 

反正我可不必像做下面的每個Sub1的-SUB15的?

Sub MainSub() 
     On Error GoTo NotifyandCorrect 
     Call Sub1 
     Call Sub2 
     ... 
     Call Sub15 
     Exit Sub 
    NotifyandCorrect: 
     'Send copy of faulty file, the error code and Sub that caused it 
     'Then stop macro execution completely 
    End Sub 
    ... 
    ... 
Sub Sub15() 
    On Error Goto HaltExecution 
    'Clean up work 
    Exit Sub 
HaltExecution: 
    'Note Error message & type 
    'Note that Sub15 is where error occurred 
    End Sub 

關閉問題

  1. 這是在所有可能的?
  2. 如果這是不可能的,我應該如何處理這個事情來完成我所描述的事情?你會有什麼建議(請提供例子,如果你可以)

回答

3

您需要處理在你的「孩子」方法中的錯誤,並讓他們「重新拋出「錯誤(在錯誤處理子程序中使用Err.Raise),以便調用者可以看到它 - 當重新拋出時,將方法名稱指定爲」源「。下面的代碼產生這樣的輸出:

5   Invalid procedure call or argument  DoSomething1 
9   Subscript out of range  DoSomething2 
Public Sub MainSub() 
    On Error GoTo ErrHandler 

    DoSomething1 
    DoSomething2 

    Exit Sub 
ErrHandler: 
    Debug.Print Err.Number, Err.Description, Err.Source 
    Resume Next 
End Sub 

Private Sub DoSomething1() 
    On Error GoTo ErrHandler 

    Err.Raise 5 

    Exit Sub 
ErrHandler: 
    Err.Raise Err.Number, "DoSomething1", Err.Description 
End Sub 

Private Sub DoSomething2() 
    On Error GoTo ErrHandler 

    Err.Raise 9 

    Exit Sub 
ErrHandler: 
    Err.Raise Err.Number, "DoSomething2", Err.Description 
End Sub 

反正我可不必像做下面的每個Sub1的-SUB15的?

不是。每個過程都必須處理運行時錯誤,這是沒有辦法解決的。


在硬編碼字符串中指定方法名稱很煩人。

模塊1

Option Explicit 

Public Sub MainSub() 
    On Error GoTo ErrHandler 

    RunCommand New DoSomething1 
    RunCommand New DoSomething2 

    Exit Sub 
ErrHandler: 
    Debug.Print Err.Number, Err.Description, Err.Source 
    Resume Next 
End Sub 

Private Sub RunCommand(ByVal command As ICommand) 
    command.Execute 
End Sub 

的ICommand(類模塊)

:通過封裝每道工序到自己的對象(比如,一些 ICommand實現),你可以通過利用 TypeName功能實現同樣的結果
Public Sub Execute() 
End Sub 

DoSomething1(類模塊)

Option Explicit 
Implements ICommand 

Private Sub ICommand_Execute() 
    On Error GoTo ErrHandler 

    Err.Raise 5 

ErrHandler: 
    Err.Raise Err.Number, TypeName(Me), Err.Description 
End Sub 

了doSomething2(類模塊)

Option Explicit 
Implements ICommand 

Private Sub ICommand_Execute() 
    On Error GoTo ErrHandler 

    Err.Raise 9 

ErrHandler: 
    Err.Raise Err.Number, TypeName(Me), Err.Description 
End Sub 

ICommand接口是不是真的需要,但各正規化命令DoSomething被調用的方式。這個想法是有一個對象來實現每個過程 - 這樣你可以有TypeName(Me)作爲你的錯誤源,並且永遠不需要硬編碼一個字符串。您將在15個專用類模塊中使用15個方法,而不是單個標準模塊中的15個方法。

+0

所以'Err.Raise'不僅會回憶錯誤,還會導致代碼移回原始的子/主例程以觸發'NotifyandRepair'? – CaffeinatedCoder

+0

是的。在錯誤處理子例程中發生的任何錯誤都需要由調用者處理。請注意,調用沒有任何參數的'Err.Raise' *將有效地「重新拋出」發生的確切錯誤,調用者需要處理 - 您只需指定參數,因爲您想在此處指定「源」。 –

+0

我不知道「Err.Raise」能夠像你所描述的那樣傳遞參數。這對我的情況非常合適,謝謝!不幸的是必須將錯誤處理放在每個子文件中,但是我認爲這是一個很小的代價,對吧? – CaffeinatedCoder

0

你可以使用Err.NumberErr.Description獲得有關錯誤的信息。

接下來,我會建議創建一個臨時文件string並在每次輸入新的子文件時進行更新。如:

Sub Sub1() 
temp= "sub1" 
... 
End Sub 

Sub Sub2() 
temp= "sub2" 
... 
End Sub 

所以每當一個錯誤的處理,該字符串臨時持有它發生在子的價值

+0

但是,當錯誤發生時,我將如何返回到MainSub並提出NotifyandRepair Error Handler? – CaffeinatedCoder

+0

我想你只需要刪除主子上的'Exit Sub',然後每當sub1或sub2發生錯誤,你立即回到主子部分的NotifyandCorrect。 – David912