क्या VBA में शब्दकोश संरचना है?


जवाबों:


341

हाँ।

MS स्क्रिप्टिंग रनटाइम ('Microsoft स्क्रिप्टिंग रनटाइम') का संदर्भ सेट करें। @ रेगो की टिप्पणी के अनुसार, टूल्स-> संदर्भ पर जाएं और 'Microsoft स्क्रिप्टिंग रनटाइम' के लिए बॉक्स को टिक करें।

संदर्भ विंडो

नीचे दिए गए कोड का उपयोग करके एक शब्दकोश उदाहरण बनाएं:

Set dict = CreateObject("Scripting.Dictionary")

या

Dim dict As New Scripting.Dictionary 

उपयोग का उदाहरण:

If Not dict.Exists(key) Then 
    dict.Add key, value
End If 

Nothingजब आप इसे उपयोग करना समाप्त कर लें तो शब्दकोश को सेट करना न भूलें ।

Set dict = Nothing 

17
यह डेटा संरचना प्रकार स्क्रिप्टिंग रनटाइम द्वारा प्रदान की जाती है, VBA द्वारा नहीं। असल में, VBA व्यावहारिक रूप से किसी भी डेटा संरचना का उपयोग कर सकता है जो COM इंटरफ़ेस के माध्यम से इसके लिए सुलभ है।
डेविड-डब्ल्यू-फेंटन

163
बस पूर्णता के लिए: आपको इसके लिए "Microsoft स्क्रिप्टिंग रनटाइम" को काम (टूल-> संदर्भों पर जाएं) और इसके बॉक्स की जांच करने के लिए संदर्भित करना होगा।
रेजो

7
उह, VBA संग्रह मुख्य हैं। लेकिन शायद हमारी एक अलग परिभाषा है keyed
डेविड-डब्ल्यू-फेंटन

8
मैं Excel 2010 का उपयोग कर रहा हूं ... लेकिन "Microsoft स्क्रिप्टिंग रनटाइम" टूल्स के संदर्भ के बिना - Ref .. बस CreateObject करने से काम नहीं होता है। इसलिए, @मास्टरो को लगता है कि आपकी टिप्पणी ऊपर गलत है। जब तक मुझे कुछ याद नहीं आ रहा है .. तो, दोस्तों टूल्स -> संदर्भ की आवश्यकता है।
इश्तहार

4
FYI के रूप में, आप Dim dict As New Scripting.Dictionaryसंदर्भ के बिना उपयोग नहीं कर सकते । संदर्भ के बिना, आपको CreateObjectइस ऑब्जेक्ट को इंस्टेंट करने की देर से बाध्यकारी विधि का उपयोग करना होगा ।
डेविड ज़ेमेंस 25'13

179

VBA संग्रह वस्तु है:

    Dim c As Collection
    Set c = New Collection
    c.Add "Data1", "Key1"
    c.Add "Data2", "Key2"
    c.Add "Data3", "Key3"
    'Insert data via key into cell A1
    Range("A1").Value = c.Item("Key2")

Collectionवस्तु प्रदर्शन कुंजी आधारित एक हैश का उपयोग कर तो यह जल्दी हो जाता है लुकअप।


आप Contains()किसी विशेष संग्रह में कोई कुंजी है या नहीं यह जांचने के लिए एक फ़ंक्शन का उपयोग कर सकते हैं :

Public Function Contains(col As Collection, key As Variant) As Boolean
    On Error Resume Next
    col(key) ' Just try it. If it fails, Err.Number will be nonzero.
    Contains = (Err.Number = 0)
    Err.Clear
End Function

24 जून 2015 को संपादित करें : Contains()@TWiStErRob के लिए शुक्रिया।

25 सितंबर 2015 को संपादित करें : Err.Clear()@scipilot में धन्यवाद जोड़ा गया ।


5
बिल्ट इन कलेक्शन ऑब्जेक्ट को इंगित करने के लिए किया जाता है, इसका इस्तेमाल एक शब्दकोश के रूप में किया जा सकता है, क्योंकि ऐड विधि में एक वैकल्पिक "कुंजी" तर्क है।
साइमन टेवेसी

8
संग्रह वस्तु के बारे में बुरी बात यह है, कि आप यह नहीं देख सकते हैं कि कोई कुंजी पहले से ही संग्रह में है या नहीं। यह सिर्फ एक त्रुटि फेंक देंगे। यह बड़ी बात है, मुझे संग्रह पसंद नहीं है। (मुझे पता है, कि वर्कअराउंड हैं, लेकिन उनमें से ज्यादातर "बदसूरत" हैं)
MiVoth

5
ध्यान दें कि VBA डिक्शनरी IS hashed में स्ट्रिंग कीज़ (जैसे। C.Item ("Key2")) की खोज की जा रही है, लेकिन पूर्णांक इंडेक्स (जैसे। C.Item (20)) द्वारा लुकअप नहीं है - यह / के लिए एक रैखिक है। शैली खोज और इससे बचना चाहिए। केवल स्ट्रिंग कुंजी लुकअप के लिए या प्रत्येक पुनरावृत्ति के लिए संग्रह का उपयोग करने के लिए सबसे अच्छा है।
बेन मैकइंटायर

4
मुझे एक छोटा मिला Contains: On Error Resume Next_ col(key)_Contains = (Err.Number = 0)
TWiStErRob

5
शायद फ़ंक्शन का नाम होना चाहिए ContainsKey; केवल मंगलाचरण पढ़ने वाला कोई व्यक्ति इसे जाँचने के लिए भ्रमित कर सकता है कि इसमें एक विशेष मूल्य है।
jpmc26

44

VBA में किसी शब्दकोश का आंतरिक कार्यान्वयन नहीं है, लेकिन VBA से आप अभी भी MS Scripting Runtime Library से शब्दकोश ऑब्जेक्ट का उपयोग कर सकते हैं।

Dim d
Set d = CreateObject("Scripting.Dictionary")
d.Add "a", "aaa"
d.Add "b", "bbb"
d.Add "c", "ccc"

If d.Exists("c") Then
    MsgBox d("c")
End If

29

एक अतिरिक्त शब्दकोश उदाहरण, जो घटना की आवृत्ति से युक्त होता है।

पाश के बाहर:

Dim dict As New Scripting.dictionary
Dim MyVar as String

एक लूप के भीतर:

'dictionary
If dict.Exists(MyVar) Then
    dict.Item(MyVar) = dict.Item(MyVar) + 1 'increment
Else
    dict.Item(MyVar) = 1 'set as 1st occurence
End If

आवृत्ति पर जांच करने के लिए:

Dim i As Integer
For i = 0 To dict.Count - 1 ' lower index 0 (instead of 1)
    Debug.Print dict.Items(i) & " " & dict.Keys(i)
Next i

1
एक अतिरिक्त ट्यूटोरियल लिंक है: kamath.com/tutorials/tut009_dEDIA.asp
John M

यह बहुत अच्छा जवाब था और मैंने इसका इस्तेमाल किया। हालाँकि, मैंने पाया कि मैं डिक्टेट नहीं कर सका। मुझे लूप में प्रवेश करने से पहले उन (आइटम सूची और कुंजियों की सूची) को अलग-अलग वेरिएंट में स्टोर करना पड़ता था और फिर उन वैरिएंट्स का उपयोग उन वैल्यूज में करना पड़ता था, जिनकी उन्हें जरूरत थी। जैसे - allItems = companyList.Items allKeys = companyList.Keys allItems (i) यदि नहीं, तो मुझे त्रुटि मिलेगी: "संपत्ति को निर्धारित प्रक्रिया नहीं बताई गई और संपत्ति प्राप्त करने की प्रक्रिया वापस नहीं आई।" कुंजी (i) का उपयोग करते समय आइटम (i) लूप में।
मूलांक

10

Cjrh के उत्तर को बंद करते हुए , हम बिना लेबल की आवश्यकता वाले समसामयिक फ़ंक्शन का निर्माण कर सकते हैं (मुझे लेबल का उपयोग करना पसंद नहीं है)।

Public Function Contains(Col As Collection, Key As String) As Boolean
    Contains = True
    On Error Resume Next
        err.Clear
        Col (Key)
        If err.Number <> 0 Then
            Contains = False
            err.Clear
        End If
    On Error GoTo 0
End Function

मेरी एक परियोजना के लिए, मैंने एक Collectionतरह से अधिक व्यवहार करने के लिए सहायक कार्यों का एक सेट लिखा Dictionary। यह अभी भी पुनरावर्ती संग्रह की अनुमति देता है। आप देखेंगे कि कुंजी हमेशा पहले आती है क्योंकि यह अनिवार्य था और मेरे कार्यान्वयन में अधिक समझ में आता था। मैंने भी केवल Stringकुंजियों का उपयोग किया । आप चाहें तो इसे वापस बदल सकते हैं।

सेट

मैंने इसका नाम बदलकर सेट कर दिया क्योंकि यह पुराने मूल्यों को अधिलेखित कर देगा।

Private Sub cSet(ByRef Col As Collection, Key As String, Item As Variant)
    If (cHas(Col, Key)) Then Col.Remove Key
    Col.Add Array(Key, Item), Key
End Sub

प्राप्त

errसामान के बाद से आप उपयोग कर वस्तुओं से होकर गुजरेगा वस्तुओं के लिए है setबिना और चर। मुझे लगता है कि आप जांच कर सकते हैं कि क्या यह एक वस्तु है, लेकिन मुझे समय के लिए दबाया गया था।

Private Function cGet(ByRef Col As Collection, Key As String) As Variant
    If Not cHas(Col, Key) Then Exit Function
    On Error Resume Next
        err.Clear
        Set cGet = Col(Key)(1)
        If err.Number = 13 Then
            err.Clear
            cGet = Col(Key)(1)
        End If
    On Error GoTo 0
    If err.Number <> 0 Then Call err.raise(err.Number, err.Source, err.Description, err.HelpFile, err.HelpContext)
End Function

है

इस पोस्ट का कारण ...

Public Function cHas(Col As Collection, Key As String) As Boolean
    cHas = True
    On Error Resume Next
        err.Clear
        Col (Key)
        If err.Number <> 0 Then
            cHas = False
            err.Clear
        End If
    On Error GoTo 0
End Function

हटाना

अगर यह मौजूद नहीं है तो इसे फेंके नहीं। बस यह सुनिश्चित करता है कि इसे हटा दिया गया है।

Private Sub cRemove(ByRef Col As Collection, Key As String)
    If cHas(Col, Key) Then Col.Remove Key
End Sub

चांबियाँ

कुंजियों की एक सरणी प्राप्त करें।

Private Function cKeys(ByRef Col As Collection) As String()
    Dim Initialized As Boolean
    Dim Keys() As String

    For Each Item In Col
        If Not Initialized Then
            ReDim Preserve Keys(0)
            Keys(UBound(Keys)) = Item(0)
            Initialized = True
        Else
            ReDim Preserve Keys(UBound(Keys) + 1)
            Keys(UBound(Keys)) = Item(0)
        End If
    Next Item

    cKeys = Keys
End Function

6

स्क्रिप्टिंग रनटाइम शब्दकोश में एक बग है जो उन्नत चरणों में आपके डिज़ाइन को बर्बाद कर सकता है।

यदि शब्दकोश मूल्य एक सरणी है, तो आप शब्दकोष में संदर्भ के माध्यम से सरणी में निहित तत्वों के मूल्यों को अपडेट नहीं कर सकते।


6

हाँ। के लिए VB6 , VBA (एक्सेल), और VB.NET


2
आप प्रश्न को अधिक पढ़ सकते हैं: मैंने वीबीए के बारे में पूछा है: विज़ुअल बेसिक फॉर एप्लिकेशन, वीबी के लिए नहीं, वीबीनेट के लिए नहीं, किसी अन्य भाषा के लिए नहीं।

1
fessGUID: फिर से, आपको उत्तर अधिक पढ़ना चाहिए! यह उत्तर VBA (विशेष रूप से, पहले लिंक) के लिए भी उपयोग किया जा सकता है।
कोनराड रुडोल्फ

5
मैं मानता हूँ। मैंने प्रश्न को बहुत तेजी से पढ़ा। लेकिन मैंने उसे बताया कि उसे क्या पता होना चाहिए।
मैथ्यू फ्लैशेन

5
@ ओरंग, VBA का सबसे बड़ा सबूत VB.NET का एक सबसेट बन गया है, कार्यालय में बैककॉम के नियम - कल्पना करें कि हर एक्सेल मैक्रो को कभी भी लिखे जाने की कोशिश करें।
रिचर्ड गडसेन

2
VBA वास्तव में VB6 का एक सुपरसेट है। यह VB6 के रूप में एक ही कोर DLL का उपयोग करता है, लेकिन फिर Office में विशिष्ट अनुप्रयोगों के लिए सभी प्रकार की कार्यक्षमता को जोड़ता है।
डेविड-डब्ल्यू-फेंटन

4

यदि किसी कारण से, आप अपने Excel में अतिरिक्त सुविधाएँ स्थापित नहीं कर सकते हैं या नहीं करना चाहते हैं, तो आप कम से कम साधारण समस्याओं के लिए सरणियों का भी उपयोग कर सकते हैं। WhatIsCapital के रूप में आप देश का नाम रखते हैं और फ़ंक्शन आपको अपनी पूंजी देता है।

Sub arrays()
Dim WhatIsCapital As String, Country As Array, Capital As Array, Answer As String

WhatIsCapital = "Sweden"

Country = Array("UK", "Sweden", "Germany", "France")
Capital = Array("London", "Stockholm", "Berlin", "Paris")

For i = 0 To 10
    If WhatIsCapital = Country(i) Then Answer = Capital(i)
Next i

Debug.Print Answer

End Sub

1
इस उत्तर की अवधारणा ध्वनि है, लेकिन नमूना कोड लिखित रूप में नहीं चलेगा। प्रत्येक चर अपनी ही जरूरत Dimकीवर्ड, Countryऔर Capitalजरूरत के रूप में प्रकार के उपयोग के कारण घोषित करने Array(), iघोषित किया जाना चाहिए (और अगर होना चाहिए Option Explicitसेट है), और पाश काउंटर बाध्य त्रुटि के बाहर निकालने के लिए जा रहा है - करने के लिए सुरक्षित मूल्य के UBound(Country)लिए उपयोग करें To। यह भी ध्यान देने योग्य है कि जबकि Array()फ़ंक्शन एक उपयोगी शॉर्टकट है, यह VBA में सरणियों की घोषणा करने का मानक तरीका नहीं है।
जेसीबी

3

अन्य सभी ने पहले ही डिक्शनरी क्लास के स्क्रिप्टिंग.रंटाइम संस्करण के उपयोग का उल्लेख किया है। यदि आप इस DLL का उपयोग करने में असमर्थ हैं, तो आप इस संस्करण का उपयोग भी कर सकते हैं, बस इसे अपने कोड में जोड़ सकते हैं।

https://github.com/VBA-tools/VBA-Dictionary/blob/master/Dictionary.cls

यह Microsoft के संस्करण के समान है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.