सिर्फ इसलिए कि आप कुछ कर सकते हैं, इसका मतलब यह नहीं है कि आपको करना चाहिए।
मैं पिछड़ी संगतता की पवित्रता में गहरा विश्वास करता हूं। लेकिन यह एक स्याह पक्ष के साथ आता है। कभी-कभी चीजों को करने के पुराने तरीके पक्ष से बाहर हो जाते हैं। उनका उपयोग इतना रहस्यमय हो जाता है कि हम भूल जाते हैं कि वे मौजूद भी हैं।
तो यह DefType कथनों के साथ जाता है।
जो आप नहीं जानते वह आपको चोट पहुंचा सकता है
कई महीने पहले, मैंने Romke Soldaat के रजिस्ट्री ऑपरेशंस क्लास मॉड्यूल के बारे में एक लेख लिखा था।
मैंने रोमके की एपीआई घोषणाओं में किए गए परिवर्तनों को प्रकाशित किया ताकि कोड को 64-बिट वीबीए के तहत चलाया जा सके। प्रत्येक API कॉल #If VBA7
. में लिपटा हुआ था सशर्त संकलन टैग और PtrSafe
. के साथ अद्यतन कीवर्ड।
केवल एक ही समस्या थी।
मैं रोमके के कोड में मॉड्यूल-स्तरीय घोषणाओं में से एक में किए गए एक महत्वपूर्ण परिवर्तन को शामिल करना भूल गया था। इस परिवर्तन के बिना, रोमके का संशोधित कोड 64-बिट VBA के तहत संकलित नहीं होगा। निम्न पंक्ति पर संकलन त्रुटि हुई:
त्रुटि संदेश था "ByRef तर्क प्रकार बेमेल " और हाइलाइट किया गया वैरिएबल था hCurKey
.
यहाँ Romke के मूल वर्ग मॉड्यूल से कोड की आपत्तिजनक पंक्ति है:
Private hCurKey
संकलन त्रुटि को ठीक करने के लिए, कोड की उपरोक्त पंक्ति को इसमें बदला जा सकता है:
Private hCurKey As Variant
लेकिन रुकिए, आप कहते हैं, क्या कोड की वे दो पंक्तियाँ एक ही काम नहीं कर रही हैं?!?! हर कोई जानता है कि यदि आप वीबीए में एक चर के प्रकार की घोषणा नहीं करते हैं तो इसे एक प्रकार के रूप में घोषित किया जाता है। ... या है?
स्पष्ट, निहित से बेहतर है
तो वास्तव में यहाँ क्या हो रहा है?
समस्या यह है कि उपरोक्त कोड की पहली पंक्ति-Private hCurKey
- hCurKey वैरिएबल को Long
. के रूप में परिभाषित कर रहा था डेटा प्रकार।
यह कैसे हो सकता है?
यह रोमके के क्लास मॉड्यूल के शीर्ष पर इस अजीब लाइन के कारण था:
DefLng H-I, L, N
वह रेखा क्या कर रही है? यह कह रहा है कि वर्तमान मॉड्यूल में प्रत्येक घोषित चर स्पष्ट रूप से घोषित प्रकार के बिना जिसका चर नाम H
से शुरू होता है , I
, L
, या N
, को कंपाइलर द्वारा Long
. के रूप में माना जाएगा डेटा प्रकार।
और इसलिए, लाइन Private hCurKey
निहित रूप से . किया hCurKey चर के लिए एक प्रकार घोषित करें, लेकिन निहित घोषणा एक प्रकार के बजाय एक लंबे डेटा प्रकार के रूप में थी।
क्यों करता है वेरिएंट संकलित करें लेकिन लंबा नहीं है?
जब hCurKey
. है तो कोड क्यों संकलित होता है? एक प्रकार है लेकिन लंबा होने पर विफल हो जाता है, यह 32-बिट से 64-बिट रूपांतरण प्रक्रिया की बात है।
समस्या के स्रोत का पता लगाने के लिए, हमें RegCreateKeyEx API घोषणा के लिए माइग्रेट किए गए कोड की जांच करनी होगी:
#If VBA7 Then
Private Declare PtrSafe Function RegCreateKeyEx _
Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
ByVal hKey As LongPtr, ByVal lpSubKey As String, _
ByVal Reserved As Long, ByVal lpClass As String, _
ByVal dwOptions As Long, ByVal samDesired As Long, _
lpSecurityAttributes As SECURITY_ATTRIBUTES, _
phkResult As LongPtr, lpdwDisposition As Long) As Long
#Else
Private Declare Function RegCreateKeyEx _
Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
ByVal hKey As Long, ByVal lpSubKey As String, _
ByVal Reserved As Long, ByVal lpClass As String, _
ByVal dwOptions As Long, ByVal samDesired As Long, _
lpSecurityAttributes As SECURITY_ATTRIBUTES, _
phkResult As Long, lpdwDisposition As Long) As Long
#End If
जब हम RegCreateKeyEx
. को कॉल करते हैं कोड से, हम hCurKey
. पास कर रहे हैं फ़ंक्शन में दूसरे से अंतिम तर्क के रूप में चर। दूसरे शब्दों में, इसे phkResult
. के रूप में पास किया जा रहा है बहस। ध्यान दें कि प्री-वीबीए7 संस्करण (एक्सेस 2007 और पहले के) में, phkResult
लॉन्ग के रूप में घोषित किया गया है, लेकिन VBA7 संस्करण में इसे LongPtr
के रूप में घोषित किया गया है .
ऐसा इसलिए है क्योंकि phkResult
एक हैंडल प्राप्त करता है बनाई या खोली गई रजिस्ट्री कुंजी के लिए। जब भी आप किसी एपीआई कॉल से जुड़े "हैंडल" शब्द को देखते हैं, तो आप सुरक्षित रूप से इसे अपने सिर में "मेमोरी एड्रेस" में अनुवाद कर सकते हैं। इसलिए तर्क को LongPtr
. के रूप में फिर से परिभाषित किया गया है VBA7 कोड में:32-बिट वातावरण में निष्पादित करते समय, एक LongPtr
एक 32-बिट Long
के रूप में माना जाता है पूर्णांक, लेकिन 64-बिट वातावरण में, एक LongPtr
को 64-बिट LongLong
. के रूप में माना जाता है पूर्णांक।
hCurKey
घोषित करना जैसा कि वैरिएंट एक छोटा सा शॉर्टकट है। निम्नलिखित अनुकूलन भी काम करेगा (और तेजी से प्रदर्शन करेगा, हालांकि गति वृद्धि उपयोगकर्ता के लिए अगोचर होने की संभावना है जब तक कि इसे लूप के अंदर कई बार नहीं कहा जाता है):
#If VBA7 Then
Private hCurKey As LongPtr
#Else
Private hCurKey As Long
#End If
जैसा कि मैंने कहा, उपरोक्त दृष्टिकोण डेवलपर के इरादे को व्यक्त करने में अधिक स्पष्ट है, बेहतर प्रदर्शन करता है, और Private hCurKey As Variant
की तुलना में अधिक संकलन-समय त्रुटियों को बढ़ाएगा। वैकल्पिक।
लेकिन मैं आलसी होने के लिए जाना जाता हूं, और Private hCurKey As Variant
लगभग है बहुत कम टाइपिंग के साथ उतना ही अच्छा।
अपने ज्ञान का उपयोग अच्छे के लिए करें
अब, याद रखें कि मैंने इस लेख की शुरुआत में क्या कहा था?
सिर्फ इसलिए कि आप कुछ कर सकते हैं, इसका मतलब यह नहीं है कि आपको करना चाहिए।
मैंने यह लेख दो कारणों से लिखा है:
- आपको स्पष्ट रूप से के लिए प्रोत्साहित करने के लिए भिन्न चर घोषित करें
As Variant
- वीबीए के एक रहस्यमय पहलू के बारे में जागरूकता बढ़ाने के लिए जो आपको परेशान कर सकता है यदि आप किसी और के कोड को बनाए रख रहे हैं (या कॉपी-पेस्ट कर रहे हैं)
मैंने नहीं किया आपको अपने कोड में DefType कथन लिखने के लिए प्रेरित करने के लिए यह लेख लिखें। ऐसा मत करो!!! याद रखें, सिर्फ इसलिए कि आप कुछ कर सकते हैं इसका मतलब यह नहीं है कि आपको करना चाहिए।