VBA
VBA रन-टाइम त्रुटियां
खोज…
परिचय
कोड जो संकलित कर सकता है वह रन-टाइम पर, त्रुटियों में भी चल सकता है। यह विषय सबसे आम लोगों, उनके कारणों और उनसे बचने के तरीके को सूचीबद्ध करता है।
रन-टाइम त्रुटि '3': GoSub के बिना लौटें
गलत कोड
Sub DoSomething()
GoSub DoThis
DoThis:
Debug.Print "Hi!"
Return
End Sub
यह काम क्यों नहीं करता है?
निष्पादन में प्रवेश करती है DoSomething
प्रक्रिया, करने के लिए कूदता है DoThis
, प्रिंट लेबल "हाय!" डीबग आउटपुट के लिए, GoSub
कॉल के तुरंत बाद निर्देश पर लौटता है, "Hi!" फिर से, और फिर एक Return
स्टेटमेंट का सामना करता है, लेकिन अब वापस लौटने के लिए कहीं नहीं है, क्योंकि हम यहां GoSub
स्टेटमेंट के साथ नहीं GoSub
।
सही कोड
Sub DoSomething()
GoSub DoThis
Exit Sub
DoThis:
Debug.Print "Hi!"
Return
End Sub
यह काम क्यों करता है?
DoThis
लाइन लेबल से पहले एक Exit Sub
इंस्ट्रक्शन पेश करके, हमने DoThis
सबरूटीन को बाकी प्रक्रिया शरीर से अलग कर दिया है - DoThis
सबरूटीन को निष्पादित करने का एकमात्र तरीका GoSub
कूद है।
अन्य नोट
GoSub
/ Return
को हटा दिया जाता है, और वास्तविक प्रक्रिया कॉल के पक्ष में इससे बचा जाना चाहिए। एक प्रक्रिया में त्रुटि हैंडलर के अलावा, सबरूटीन शामिल नहीं होना चाहिए।
यह रन-टाइम त्रुटि '20' के समान है: त्रुटि के बिना फिर से शुरू करें ; दोनों स्थितियों में, समाधान यह सुनिश्चित करने के लिए है कि सामान्य निष्पादन पथ एक स्पष्ट कूद के बिना एक उप-रूटीन (एक लाइन लेबल द्वारा पहचाना गया) में प्रवेश नहीं कर सकता है (यह मानकर On Error GoTo
को एक स्पष्ट कूद माना जाता है)।
रन-टाइम एरर '6': ओवरफ्लो
गलत कोड
Sub DoSomething()
Dim row As Integer
For row = 1 To 100000
'do stuff
Next
End Sub
यह काम क्यों नहीं करता है?
Integer
डेटा प्रकार एक 16-बिट हस्ताक्षरित पूर्णांक है जिसमें अधिकतम मूल्य 32,767 है; इससे बड़ी चीज को सौंपना, इस प्रकार के अतिप्रवाह और इस त्रुटि को बढ़ाएगा।
सही कोड
Sub DoSomething()
Dim row As Long
For row = 1 To 100000
'do stuff
Next
End Sub
यह काम क्यों करता है?
इसके बजाय एक Long
(32-बिट) पूर्णांक का उपयोग करके, हम अब एक लूप बना सकते हैं जो काउंटर चर के प्रकार को ओवरफ्लो किए बिना 32,767 से अधिक बार पुनरावृत्त करता है।
अन्य नोट
अधिक जानकारी के लिए डेटा प्रकार और सीमाएँ देखें।
रन-टाइम त्रुटि '9': सीमा से बाहर सदस्यता
गलत कोड
Sub DoSomething()
Dim foo(1 To 10)
Dim i As Long
For i = 1 To 100
foo(i) = i
Next
End Sub
यह काम क्यों नहीं करता है?
foo
एक सरणी है जिसमें 10 आइटम हैं। जब i
लूप काउंटर 11 के मान पर पहुंच जाता है, तो foo(i)
सीमा से बाहर हो जाता है । यह त्रुटि तब होती है जब कोई सरणी या संग्रह एक अनुक्रमणिका के साथ एक्सेस किया जाता है जो उस सरणी या संग्रह में मौजूद नहीं होता है।
सही कोड
Sub DoSomething()
Dim foo(1 To 10)
Dim i As Long
For i = LBound(foo) To UBound(foo)
foo(i) = i
Next
End Sub
यह काम क्यों करता है?
क्रमशः एक सरणी की निचली और ऊपरी सीमाओं को निर्धारित करने के लिए LBound
और UBound
फ़ंक्शन का उपयोग करें।
अन्य नोट
जब सूचकांक एक स्ट्रिंग है, उदाहरण के लिए ThisWorkbook.Worksheets("I don't exist")
, इस त्रुटि का अर्थ है कि आपूर्ति नाम क्वेरिड संग्रह में मौजूद नहीं है।
वास्तविक त्रुटि हालांकि कार्यान्वयन-विशिष्ट है; Collection
रन-टाइम त्रुटि 5 उठाएगा "इसके बजाय अमान्य प्रक्रिया कॉल या तर्क":
Sub RaisesRunTimeError5()
Dim foo As New Collection
foo.Add "foo", "foo"
Debug.Print foo("bar")
End Sub
रन-टाइम त्रुटि '13': टाइप बेमेल
गलत कोड
Public Sub DoSomething()
DoSomethingElse "42?"
End Sub
Private Sub DoSomethingElse(foo As Date)
' Debug.Print MonthName(Month(foo))
End Sub
यह काम क्यों नहीं करता है?
VBA "42?"
को रूपांतरित करने के लिए वास्तव में कठिन प्रयास कर रहा है "42?"
Date
मान में तर्क। जब यह विफल हो जाता है, तो DoSomethingElse
कॉल निष्पादित नहीं किया जा सकता है, क्योंकि VBA को पता नहीं है कि किस तारीख को पास होना है, इसलिए यह रन-टाइम त्रुटि 13 प्रकार के बेमेल उठाता है, क्योंकि तर्क का प्रकार अपेक्षित प्रकार से मेल नहीं खाता है (और कर सकते हैं) 'या तो स्पष्ट रूप से रूपांतरित न हों)।
सही कोड
Public Sub DoSomething()
DoSomethingElse Now
End Sub
Private Sub DoSomethingElse(foo As Date)
' Debug.Print MonthName(Month(foo))
End Sub
यह काम क्यों करता है?
एक में उत्तीर्ण होकर Date
एक प्रक्रिया है जो एक उम्मीद करने के लिए तर्क Date
पैरामीटर, कॉल सफल होने के कर सकते हैं।
रन-टाइम त्रुटि '91': ऑब्जेक्ट वेरिएबल या ब्लॉक वेरिएबल के साथ सेट नहीं है
गलत कोड
Sub DoSomething()
Dim foo As Collection
With foo
.Add "ABC"
.Add "XYZ"
End With
End Sub
यह काम क्यों नहीं करता है?
ऑब्जेक्ट चर एक संदर्भ रखते हैं , और Set
कीवर्ड का उपयोग करके संदर्भ सेट करने की आवश्यकता होती है। यह त्रुटि तब होती है जब भी किसी सदस्य को किसी ऑब्जेक्ट पर कॉल किया जाता है जिसका संदर्भ Nothing
। इस मामले में foo
एक Collection
संदर्भ है, लेकिन इसे प्रारंभ नहीं किया गया है, इसलिए संदर्भ में Nothing
- और हम कॉल नहीं कर सकते। Nothing
पर .Add
करें।
सही कोड
Sub DoSomething()
Dim foo As Collection
Set foo = New Collection
With foo
.Add "ABC"
.Add "XYZ"
End With
End Sub
यह काम क्यों करता है?
ऑब्जेक्ट कीवर्ड को Set
कीवर्ड का उपयोग करके एक वैध संदर्भ निर्दिष्ट करके, .Add
कॉल सफल होती है।
अन्य नोट
अक्सर, एक फ़ंक्शन या प्रॉपर्टी एक ऑब्जेक्ट संदर्भ लौटा सकती है - एक सामान्य उदाहरण एक्सेल की Range.Find
विधि, जो एक Range
ऑब्जेक्ट लौटाता है:
Dim resultRow As Long
resultRow = SomeSheet.Cells.Find("Something").Row
हालांकि फ़ंक्शन बहुत अच्छी तरह से Nothing
लौटा सकता है (यदि खोज शब्द नहीं मिला है), तो यह संभावना है कि जंजीर। .Row
सदस्य कॉल विफल हो जाती है।
ऑब्जेक्ट सदस्यों को कॉल करने से पहले, सत्यापित करें कि संदर्भ एक If Not xxxx Is Nothing
साथ सेट If Not xxxx Is Nothing
है:
Dim result As Range
Set result = SomeSheet.Cells.Find("Something")
Dim resultRow As Long
If Not result Is Nothing Then resultRow = result.Row
रन-टाइम त्रुटि '20': त्रुटि के बिना फिर से शुरू करें
गलत कोड
Sub DoSomething()
On Error GoTo CleanFail
DoSomethingElse
CleanFail:
Debug.Print Err.Number
Resume Next
End Sub
यह काम क्यों नहीं करता है?
यदि DoSomethingElse
प्रक्रिया एक त्रुटि उठाती है, तो निष्पादन CleanFail
लाइन लेबल पर कूदता है, त्रुटि संख्या को प्रिंट करता है, और Resume Next
से Resume Next
निर्देश Resume Next
निर्देश पर वापस जाता है कि तुरंत उस पंक्ति का अनुसरण करता है जहां त्रुटि हुई थी, जो इस मामले में Debug.Print
निर्देश: त्रुटि से निपटने वाला सबरूटीन त्रुटि संदर्भ के बिना निष्पादित हो रहा है, और जब रिज्यूमे Resume Next
इंस्ट्रक्शन पहुँच जाता है, तो रन-टाइम एरर २० उठाया जाता है क्योंकि फिर से शुरू करने के लिए कहीं नहीं है।
सही कोड
Sub DoSomething()
On Error GoTo CleanFail
DoSomethingElse
Exit Sub
CleanFail:
Debug.Print Err.Number
Resume Next
End Sub
यह काम क्यों करता है?
CleanFail
लाइन लेबल से पहले एक Exit Sub
इंस्ट्रक्शन पेश करके, हमने CleanFail
एरर-हैंडलिंग सबरूटीन को बाकी प्रक्रिया बॉडी से अलग कर CleanFail
है - एरर-हैंडलिंग सबरूटीन को निष्पादित करने का एकमात्र तरीका On Error
जंप के माध्यम से है; इसलिए, कोई निष्पादन पथ त्रुटि संदर्भ के बाहर Resume
निर्देश तक नहीं पहुंचता है, जो रन-टाइम त्रुटि 20 से बचा जाता है।
अन्य नोट
यह रन-टाइम त्रुटि '3' के समान है: GoSub के बिना लौटें ; दोनों स्थितियों में, समाधान यह सुनिश्चित करने के लिए है कि सामान्य निष्पादन पथ एक स्पष्ट कूद के बिना एक उप-रूटीन (एक लाइन लेबल द्वारा पहचाना गया) में प्रवेश नहीं कर सकता है (यह मानकर On Error GoTo
को एक स्पष्ट कूद माना जाता है)।