खोज…


त्रुटि की स्थिति से बचना

जब कोई रनटाइम त्रुटि होती है, तो अच्छे कोड को संभालना चाहिए। सबसे अच्छी त्रुटि से निपटने की रणनीति कोड लिखना है जो त्रुटि स्थितियों की जांच करता है और बस रन कोड को निष्पादित करने से बचता है जिसके परिणामस्वरूप रनटाइम त्रुटि होती है।

रनटाइम त्रुटियों को कम करने में एक प्रमुख तत्व, छोटी प्रक्रियाओं को लिख रहा है जो एक काम करते हैं । कम कारणों वाली प्रक्रियाओं को विफल करना पड़ता है, एक पूरे के रूप में कोड को डीबग करना आसान होता है।


रनटाइम त्रुटि से बचना 91 - ऑब्जेक्ट या ब्लॉक चर के साथ सेट नहीं:

यह त्रुटि तब उठाई जाएगी जब किसी ऑब्जेक्ट का उपयोग उसके संदर्भ को असाइन करने से पहले किया जाता है। एक प्रक्रिया हो सकती है जो एक वस्तु पैरामीटर प्राप्त करती है:

Private Sub DoSomething(ByVal target As Worksheet)
    Debug.Print target.Name
End Sub

यदि target को कोई संदर्भ नहीं दिया गया है, तो उपरोक्त कोड में एक त्रुटि होगी जो आसानी से जाँच से बच जाएगी यदि ऑब्जेक्ट में एक वास्तविक ऑब्जेक्ट संदर्भ है:

Private Sub DoSomething(ByVal target As Worksheet)
    If target Is Nothing Then Exit Sub
    Debug.Print target.Name
End Sub

यदि target को एक संदर्भ नहीं सौंपा गया है, तो बिना बताए संदर्भ का उपयोग कभी नहीं किया जाता है, और कोई त्रुटि नहीं होती है।

किसी एक या अधिक पैरामीटर के मान्य नहीं होने पर किसी प्रक्रिया को जल्दी से समाप्त करने का यह तरीका गार्ड क्लॉज कहलाता है।


रनटाइम त्रुटि से बचने 9 - सीमा से बाहर सदस्यता:

यह त्रुटि तब उठाई जाती है जब किसी सरणी को उसकी सीमाओं के बाहर एक्सेस किया जाता है।

Private Sub DoSomething(ByVal index As Integer)
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

ActiveWorkbook में वर्कशीट की संख्या से अधिक एक इंडेक्स को देखते हुए, उपरोक्त कोड रनटाइम त्रुटि को बढ़ाएगा। एक साधारण गार्ड क्लॉज इससे बच सकता है:

Private Sub DoSomething(ByVal index As Integer)
    If index > ActiveWorkbook.Worksheets.Count Or index <= 0 Then Exit Sub
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

अधिकांश क्रम त्रुटियों ध्यान से मूल्यों इससे पहले कि हम उन्हें इस्तेमाल हम प्रयोग कर रहे पुष्टि करने, और तदनुसार एक सरल का उपयोग करते हुए एक और निष्पादन पथ पर शाखाओं में से बचा जा सकता If में गार्ड खंड में कोई धारणाएं बनाता है कि और एक प्रक्रिया के मानकों की पुष्टि करता है, या यहाँ तक - बयान बड़ी प्रक्रियाओं का शरीर।

त्रुटि कथन पर

यहां तक कि गार्ड क्लॉस के साथ, कोई भी वास्तविक रूप से हमेशा सभी संभावित त्रुटि स्थितियों के लिए जिम्मेदार नहीं हो सकता है जो एक प्रक्रिया के शरीर में उठाए जा सकते हैं। जब भी कोई अनपेक्षित त्रुटि रनटाइम पर होती है, तो On Error GoTo स्टेटमेंट VBA को एक लाइन लेबल पर कूदने और "एरर हैंडलिंग मोड" दर्ज करने का निर्देश देता है। एक त्रुटि को संभालने के बाद, कोड फिर से शुरू हो सकता है "सामान्य" निष्पादन में Resume से Resume

लाइन लेबल सबरूटीन्स निरूपित: क्योंकि सबरूटीन्स विरासत बुनियादी कोड से ही शुरू और का उपयोग करता है GoTo और GoSub कूदता है और Return "मुख्य" दिनचर्या में वापस कूद करने के बयान, यह काफी आसान स्पेगेटी कोड मुश्किल से पालन लिखने के लिए अगर चीजें कड़ाई से संरचित नहीं कर रहे हैं । इस कारण से, यह सबसे अच्छा है:

  • एक प्रक्रिया में एक और केवल एक त्रुटि-हैंडलिंग सबरूटीन है
  • त्रुटि से निपटने सबरूटिन केवल एक त्रुटि स्थिति में चलता है

इसका मतलब है कि एक प्रक्रिया जो अपनी त्रुटियों को संभालती है, उसे इस तरह संरचित किया जाना चाहिए:

Private Sub DoSomething()
    On Error GoTo CleanFail

    'procedure code here

CleanExit:
    'cleanup code here
    Exit Sub

CleanFail:
    'error-handling code here
    Resume CleanExit
End Sub

रणनीतियों को संभालने में त्रुटि

कभी-कभी आप विभिन्न कार्यों के साथ विभिन्न त्रुटियों को संभालना चाहते हैं। उस स्थिति में आप वैश्विक Err ऑब्जेक्ट का निरीक्षण करेंगे, जिसमें उस त्रुटि के बारे में जानकारी होगी जिसे उठाया गया था - और तदनुसार कार्य करें:

CleanExit:
    Exit Sub

CleanFail:
    Select Case Err.Number
        Case 9
            MsgBox "Specified number doesn't exist. Please try again.", vbExclamation
            Resume
        Case 91
            'woah there, this shouldn't be happening.
            Stop 'execution will break here
            Resume 'hit F8 to jump to the line that raised the error
        Case Else
            MsgBox "An unexpected error has occurred:" & vbNewLine & Err.Description, vbCritical
            Resume CleanExit
    End Select
End Sub

एक सामान्य दिशानिर्देश के रूप में, संपूर्ण सबरूटीन या फ़ंक्शन के लिए त्रुटि हैंडलिंग चालू करने पर विचार करें, और इसके दायरे में आने वाली सभी त्रुटियों को संभाल सकते हैं। यदि आपको कोड के छोटे सेक्शन में केवल त्रुटियों को संभालने की आवश्यकता है - एक ही स्तर पर त्रुटि हैंडलिंग चालू और बंद करें:

Private Sub DoSomething(CheckValue as Long)

    If CheckValue = 0 Then
        On Error GoTo ErrorHandler   ' turn error handling on
        ' code that may result in error
        On Error GoTo 0              ' turn error handling off - same level
    End If

CleanExit:
    Exit Sub

ErrorHandler:
    ' error handling code here
    ' do not turn off error handling here
    Resume

End Sub

पंक्ति संख्याएँ

VBA विरासत-शैली (जैसे QBASIC) पंक्ति संख्याओं का समर्थन करता है। अंतिम त्रुटि को उठाने वाले लाइन नंबर की पहचान करने के लिए Erl हिडन प्रॉपर्टी का उपयोग किया जा सकता है। यदि आप लाइन नंबर का उपयोग नहीं कर रहे हैं, तो Erl केवल 0 पर वापस लौटेगा।

Sub DoSomething()
10 On Error GoTo 50
20 Debug.Print 42 / 0
30 Exit Sub
40
50 Debug.Print "Error raised on line " & Erl ' returns 20
End Sub

यदि आप लाइन नंबरों का उपयोग कर रहे हैं , लेकिन लगातार नहीं, तो त्रुटि को उठाने वाले निर्देश से पहले Erl अंतिम पंक्ति संख्या वापस कर देंगे।

Sub DoSomething()
10 On Error GoTo 50
   Debug.Print 42 / 0
30 Exit Sub

50 Debug.Print "Error raised on line " & Erl 'returns 10
End Sub

ध्यान रखें कि Erl केवल Integer परिशुद्धता है, और चुपचाप अतिप्रवाह होगा। इसका मतलब यह है कि पूर्णांक सीमा के बाहर लाइन संख्या गलत परिणाम देगी:

Sub DoSomething()
99997 On Error GoTo 99999
99998 Debug.Print 42 / 0
99999
      Debug.Print Erl   'Prints 34462
End Sub

लाइन नंबर काफी प्रासंगिक नहीं है क्योंकि यह कथन त्रुटि का कारण बना, और नंबरिंग लाइन जल्दी थकाऊ हो जाती है और काफी रखरखाव के अनुकूल नहीं है।

कीवर्ड फिर से शुरू करें

त्रुटि से निपटने वाला सबरूटीन या तो होगा:

  • प्रक्रिया के अंत तक, जिस स्थिति में निष्पादन कॉलिंग प्रक्रिया में शुरू होता है।
  • या, उसी प्रक्रिया के अंदर निष्पादन को फिर से शुरू करने के लिए Resume कीवर्ड का उपयोग Resume

Resume कीवर्ड का उपयोग कभी-कभी उप-त्रुटि से निपटने में त्रुटि के अंदर किया जाना चाहिए, क्योंकि यदि VBA त्रुटि स्थिति में बिना Resume , तो रनटाइम त्रुटि 20 "त्रुटि के बिना फिर से शुरू करें" को उठाया जाता है।

एक त्रुटि से निपटने वाले सबरूटीन को Resume से Resume कीवर्ड का उपयोग करने के कई तरीके हो सकते हैं:

  • अकेले उपयोग किया गया Resume , उस कथन पर निष्पादन जारी है जो त्रुटि का कारण बना । यदि वास्तव में ऐसा करने से पहले त्रुटि को नियंत्रित नहीं किया जाता है, तो उसी त्रुटि को फिर से उठाया जाएगा, और निष्पादन एक अनंत लूप में प्रवेश कर सकता है।
  • Resume Next उस स्टेटमेंट पर तुरंत स्टेटमेंट जारी करता है, जो उस त्रुटि के कारण होता है। यदि वास्तव में ऐसा करने से पहले त्रुटि को नियंत्रित नहीं किया जाता है, तो निष्पादन को संभावित रूप से अमान्य डेटा के साथ जारी रखने की अनुमति मिलती है, जिसके परिणामस्वरूप तार्किक त्रुटियां और अप्रत्याशित व्यवहार हो सकता है।
  • Resume [line label] निर्दिष्ट लाइन लेबल (या लाइन नंबर, यदि आप विरासत शैली लाइन संख्या का उपयोग कर रहे हैं) पर निष्पादन जारी है। यह आमतौर पर प्रक्रिया से बाहर निकलने से पहले कुछ सफाई कोड को निष्पादित करने की अनुमति देता है, जैसे कि कॉल करने वाले के लौटने से पहले डेटाबेस कनेक्शन बंद करना सुनिश्चित करता है।

त्रुटि फिर से शुरू पर

On Error स्टेटमेंट में ही VBA रनटाइम को सभी त्रुटियों को प्रभावी रूप से अनदेखा करने के लिए Resume से Resume करने के लिए Resume कीवर्ड का उपयोग किया जा सकता है।

यदि वास्तव में ऐसा करने से पहले त्रुटि को नियंत्रित नहीं किया जाता है, तो निष्पादन को संभावित रूप से अमान्य डेटा के साथ जारी रखने की अनुमति मिलती है, जिसके परिणामस्वरूप तार्किक त्रुटियां और अप्रत्याशित व्यवहार हो सकता है

ऊपर दिए गए जोर पर पर्याप्त जोर नहीं दिया जा सकता है। त्रुटि को फिर से शुरू करें पर सभी त्रुटियों को प्रभावी ढंग से अनदेखा करता है और उन्हें कालीन के नीचे धक्का देता है । एक प्रोग्राम जो रनटाइम त्रुटि के साथ अमान्य इनपुट देता है, एक से एक बेहतर प्रोग्राम है जो अज्ञात / अनजाने डेटा के साथ चलता रहता है - केवल इसलिए कि बग अधिक आसानी से पहचाने जाने योग्य है। On Error Resume Next आसानी से कीड़े छिपा सकते हैं।

On Error स्टेटमेंट प्रक्रिया-स्कोप है - इसीलिए आम तौर पर केवल एक ही होना चाहिए, एक दिए प्रक्रिया में सिंगल On Error स्टेटमेंट।

हालाँकि कभी-कभी एक त्रुटि स्थिति से बचा नहीं जा सकता है, और एक त्रुटि-हैंडलिंग सबरूटीन पर कूदना केवल Resume Next से Resume Next करने के लिए है बस सही नहीं लगता है। इस विशिष्ट मामले में, ज्ञात-से-संभवतया-विफल कथन को दो On Error बीच लपेटा जा सकता है:

On Error Resume Next
[possibly-failing statement]
Err.Clear 'resets current error
On Error GoTo 0

On Error GoTo 0 अनुदेश वर्तमान प्रक्रिया में त्रुटि से निपटने में रीसेट करता है, जैसे कि रनटाइम त्रुटि पैदा करने वाला कोई भी निर्देश उस प्रक्रिया के भीतर बंद हो जाएगा और इसके बजाय कॉल स्टैक को पारित कर दिया जब तक कि यह एक सक्रिय त्रुटि हैंडलर द्वारा पकड़ा न जाए। यदि कॉल स्टैक में कोई सक्रिय त्रुटि हैंडलर नहीं है, तो इसे एक अनहेल्ड अपवाद के रूप में माना जाएगा।

Public Sub Caller()
    On Error GoTo Handler
    
    Callee
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Caller."
End Sub

Public Sub Callee()
    On Error GoTo Handler
    
    Err.Raise 1     'This will be handled by the Callee handler.
    On Error GoTo 0 'After this statement, errors are passed up the stack.
    Err.Raise 2     'This will be handled by the Caller handler.    
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Callee."
    Resume Next
End Sub

कस्टम त्रुटियां

अक्सर एक विशेष वर्ग लिखते समय, आप चाहते हैं कि यह अपनी विशिष्ट त्रुटियों को बढ़ाए, और आप अपनी कस्टम त्रुटियों को संभालने के लिए उपयोगकर्ता / कॉलिंग कोड के लिए एक स्वच्छ तरीका चाहते हैं। एक समर्पित Enum प्रकार को परिभाषित करके इसे प्राप्त करने का एक साफ तरीका है:

Option Explicit
Public Enum FoobarError
    Err_FooWasNotBarred = vbObjectError + 1024
    Err_BarNotInitialized
    Err_SomethingElseHappened
End Enum

vbObjectError निर्मित निरंतर का उपयोग करना सुनिश्चित करता है कि कस्टम त्रुटि कोड आरक्षित / मौजूदा त्रुटि कोड के साथ ओवरलैप न हो। केवल स्पष्ट रूप से निर्दिष्ट किया जा करने के लिए पहली enum मूल्य की जरूरत है, प्रत्येक के अंतर्निहित मूल्य के लिए Enum सदस्य है 1 , पिछले सदस्य से बड़ा तो के अंतर्निहित कीमत Err_BarNotInitialized परोक्ष है vbObjectError + 1025

अपनी स्वयं की रनटाइम त्रुटियों को उठाना

Err.Raise स्टेटमेंट का उपयोग करके रनटाइम त्रुटि को उठाया जा सकता है, इसलिए कस्टम Err_FooWasNotBarred त्रुटि को निम्नानुसार उठाया जा सकता है:

Err.Raise Err_FooWasNotBarred

Err.Raise पद्धति कस्टम Description और Source पैरामीटर भी ले सकती है - इस कारण से यह एक अच्छा विचार है कि प्रत्येक कस्टम त्रुटि का विवरण रखने के लिए स्थिरांक को परिभाषित करना भी है:

Private Const Msg_FooWasNotBarred As String = "The foo was not barred."
Private Const Msg_BarNotInitialized As String = "The bar was not initialized."

और फिर प्रत्येक त्रुटि को बढ़ाने के लिए एक समर्पित निजी विधि बनाएं:

Private Sub OnFooWasNotBarredError(ByVal source As String)
    Err.Raise Err_FooWasNotBarred, source, Msg_FooWasNotBarred
End Sub

Private Sub OnBarNotInitializedError(ByVal source As String)
    Err.Raise Err_BarNotInitialized, source, Msg_BarNotInitialized
End Sub

तब वर्ग का कार्यान्वयन त्रुटि को बढ़ाने के लिए इन विशिष्ट प्रक्रियाओं को कॉल कर सकता है:

Public Sub DoSomething()
    'raises the custom 'BarNotInitialized' error with "DoSomething" as the source:
    If Me.Bar Is Nothing Then OnBarNotInitializedError "DoSomething"
    '...
End Sub

क्लाइंट कोड तब Err_BarNotInitialized को संभाल Err_BarNotInitialized क्योंकि यह अपनी त्रुटि-हैंडलिंग Err_BarNotInitialized अंदर कोई अन्य त्रुटि होगी।


नोट: विरासत Error कीवर्ड का उपयोग Err.Raise स्थान पर भी किया जा सकता है, लेकिन यह अप्रचलित / अस्वीकृत है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow