Makale Scripting Dictionary

Bu Makale Yararlı Oldu mu?

  • Evet

  • Hayır


Sonuçlar yalnızca oylamadan sonra görülebilir.

Admin

Yönetici
Site Yöneticisi
Katılım
25 May 2018
Mesajlar
1,055
En İyi Yanıtlar
77
Beğeniler
858
Puanları
113
Konum
İstanbul
#1
Scripting Dictionary bir koleksiyon nesnedir. Sözlük olarak adlandırılır.
İçerisine sayı, metin, tarih, dizi, aralık gibi her türlü veriyi alabilir.
Sözlük'teki her öğe kendi benzersiz anahtarını alır.
Sözlük, bir Collection kullanımına kıyasla avantajlı olabilecek, .Keys, .Items ve .RemoveAll gibi bazı özelliklere, fonksiyonlara ve metotlara sahiptir.

Geçici olarak bellekte depolandığından, verilere kolay ve hızlı erişim sağlamak için her türlü veriyi bir Sözlükte gruplayabilirsiniz.
Hiçbir ekran tazelemesi ve otomatik hesaplama yapmadığı için arka plan yedeği gerekli değildir, bu nedenle kodunuzu önemli ölçüde hızlandıracaktır. Genel olarak, ortak bir özelliği ( key ) olan verileri depolamak/gruplamak için Sözlük nesnesini kullanabilirsiniz. Dağınık verileri de kolayca birleştirebilirsiniz. .keys benzersiz dizeler, sayılar veya tarihlerin bir listesini oluşturmak için tasarlanmamış olsa da, kullanım özelliği bakımından güzel bir fonksiyondur.

Sözlük standart VBA kitaplığının bir parçası değildir.
Microsoft Scripting Runtime kitaplığındaki bir sınıftır.
Yani kütüphane bu dosyada (C:\Windows\system32\scrrun.dll) veya benzer dizinde bulunur.
Microsoft Scripting Runtime referansı etkinleştirerek bu kitaplığa bir başvuru yapabilirsiniz.

Not: Collection nesnesi ve Dictionary nesnesi arasındaki önemli bir fark, Item özelliğinin davranışıdır.
Collection nesnesinde var olmayan bir anahtarı referans almak için Item özelliğini kullanırsanız, bir hata alırsınız.
Dictionary'de var olmayan bir anahtarı referans almak için Item özelliğini kullanırsanız, sözlüğe bu anahtar eklenir.
Bir anahtarın bir sözlükte bulunup bulunmadığını belirlemek için ise Exists yöntemini kullanırız.

Dictionary nesnesini üç farklı yöntemle başlatabiliriz.
  • Late Binding yöntemiyle, yani geç bağlanma yöntemiyle referans eklemeye gerek kalmadan.
  • Early Binding yöntemiyle, yani erken bağlanma yöntemiyle referans ekleyerek.
  • Late Binding yöntemiyle, ama herhangi bir tanımlama yapmadan sadece With ile başlayarak.
Şimdi bu tanımlama işlemlerine bir bakalım.
Late Binding yöntemiyle bu şekilde sözlüğü tanımlayabiliriz;
VBA:
Dim sozluk as Object
Set sozluk = CreateObject("Scripting.Dictionary")
Early Binding yöntemiyle bu şekilde sözlüğü tanımlayabiliriz;
VBA:
Dim sozluk As Scripting.Dictionary
Set sozluk = New Scripting.Dictionary
Bu kodla Microsoft Scripting Runtime referansını seçtirebilir ve kullanabilirsiniz.
VBA:
Sub Scripting_Referansını_Sec()
    On Error Resume Next
    ThisWorkbook.VBProject.References.AddFromFile "C:\windows\system32\scrrun.dll"
End Sub

With ifadesiyle başlayarak bu şekilde sözlüğü tanımlayabiliriz;
VBA:
With CreateObject("Scripting.Dictionary")
    'kodlar'
End With
Dictionary nesnesini kodlarımızda kullanmanın en kolay biçimi budur.

Metotlar/Fonksiyonlar

Özellikler

Add

CompareMode

Exists

Count

Items

Key

Keys

Item

Remove

 

RemoveAll

 


Şimdi bu metot ve özellikleri görelim;..

Add Metodu
Sözlüğe yeni bir anahtar ve öğe eklemek için kullanılır.
sozluk.Add Key, Item
VBA:
.Add "Tarih", Date
Exists Metodu
Bir anahtarın var olup olmadığını belirlemek için kullanılır.
If sozluk.Exists(Key) Then
Eğer anahtar yoksa demek için If Not ile başlayabilirsiniz.
If Not sozluk.Exists(Key) Then

Items Metodu
Add
metoduyla eklenen tüm öğeleri taşır.
Gerektiğinde sozluk.Items ile dışarıya aktarılır veya içindeki öğeler döndürülür.

Keys Metodu
Add
metoduyla eklenen tüm anahtarları taşır.
Gerektiğinde sozluk.Keys ile dışarıya aktarılır veya içindeki anahtarlar döndürülür.

Remove Metodu
Anahtarları sözlük koleksiyonundan kaldırmak için kullanılır.
sozluk.Remove Key
VBA:
sozluk.Add "Excel", "Turkey"
sozluk.Add "Murat", "OSMA"
sozluk.Remove "Murat"
RemoveAll Metodu
Tüm anahtarları sözlük koleksiyonundan kaldırır.
sozluk.RemoveAll
VBA:
sozluk.Add "Excel", "Turkey"
sozluk.Add "Murat", "OSMA"
sozluk.RemoveAll
CompareMode Özelliği
Anahtar karşılaştırması yaparken küçük büyük harf duyarlılığını belirtmek için kullanılır.
Bu özellik belirtilmezse 'Büyük/Küçük Harfe Duyarlı olarak verileri alır.
sozluk.CompareMode = vbBinaryCompare 'Büyük/Küçük Harfe Duyarlı
sozluk.CompareMode = vbTextCompare 'Büyük/Küçük Harfe Duyarsız

Count Özelliği
Sözlük koleksiyonundaki anahtarların sayısını verir.
sozluk.Count
VBA:
sozluk.Add "Excel", "Turkey"
sozluk.Add "Murat", "OSMA"
MsgBox sozluk.Count
Key Özelliği
Sözlüğe eklenen anahtarı ifade eder.
sozluk.Add "Excel", "Turkey" buradaki Excel kelimesi Key olarak alınır, Turkey kelimesi de Item olarak alınır.

Item Özelliği
Sözlüğe eklenen her bir anahtar için belirtilen öğeyi ifade eder.
sozluk.Item("Turkey") = Date
VBA:
sozluk.Add "Excel", "Turkey"
sozluk.Item("Turkey") = Date
MsgBox sozluk.Item("Turkey")
Şimdiye kadar öğrendiklerimizle şöyle bir örnek yapalım; A1:B10 hücre aralığında birtakım verilerimiz olsun, A sütunundaki verileri Dictionary nesnesinin Key özelliğine, B sütunundakileri de Item özelliğine alalım ve Key'de oluşan benzersiz verilerimize göre C1 ve D1'den itibaren koleksiyondaki verileri aktaralım.
VBA:
Sub ExcelTurkey()
    Dim a&, sayi&
    With CreateObject("Scripting.Dictionary")
        For a = 1 To 10
            sayi = Cells(a, 1).Value
            If Not .Exists(sayi) Then
                .Add sayi, Cells(a, 2).Value
            End If
        Next a
        Range("C1").Resize(.Count, 1).Value = Application.Transpose(.Keys)
        Range("D1").Resize(.Count, 1).Value = Application.Transpose(.Items)
    End With
    sayi = Empty: a = Empty
End Sub
Evet.. gördüğünüz gibi A sütunundaki benzersiz verilere göre bir liste oluşturup başka bir yerde listelenmesini sağladık.
Benzersiz verileri başka bir yerde listeleyecekseniz Sözlük nesnesini kullanmanızı öneririm. Yukarıda bu nesnenin yapılacak işlemi, hızlandıracağından bahsetmiştim. Diğer standart döngülere göre çok daha hızlı dönüş alırsınız.

Şimdi benzer kodları kullanıp, Item özelliğinde aynı olan verilerin toplanmasını sağlayarak hücrelere aktarma ile ilgili bir örnek yapalım.
A sütununda mükerrer biçimde Ay isimlerinin olduğunu, yani; aynı ay isimlerinden birden fazla olabildiğini düşünün.
B sütununda da o aylara ait bazı satış tutarlarımız olsun.

Yapacağımız iş; A sütunundaki ay isimlerinin benzersiz bir listesini oluşturup B sütunundaki satış tutarlarını da toplamını almak olacak.
Bir nevi özet tablo oluşturacağız.

Bu tabloyu kopyalayıp A1 hücresine yapıştırın.

Aylar

Tutar

Ocak

331

Şubat

449

Şubat

342

Nisan

210

Ocak

284

Haziran

449

Temmuz

230

Mart

449

Eylül

320

Nisan

301

Kasım

114

Aralık

164


Bahsettiğimiz işi yapabilmemiz için bu kodları kullanabilirsiniz. Bu işte, yukarıda kullandığımız kodlara ek olarak sadece bu iki satırı ilave ettik.
Else
.Item(sayi) = .Item(sayi) + Cells(a, 2).Value

VBA:
Sub ExcelTurkey()
    Dim a&, sayi$
    With CreateObject("Scripting.Dictionary")
        For a = 1 To 12
            sayi = Cells(a, 1).Value
            If Not .Exists(sayi) Then
                .Add sayi, Cells(a, 2).Value
                    Else
                .Item(sayi) = .Item(sayi) + Cells(a, 2).Value
            End If
        Next a
        Range("D1").Resize(.Count, 1).Value = Application.Transpose(.Keys)
        Range("E1").Resize(.Count, 1).Value = Application.Transpose(.items)
    End With
    sayi = Empty: a = Empty
End Sub
F8 ile adım adım giderek Locals Window'dan gözlemleyebilirsiniz.

Sonuç olarak bu tablonun oluştuğunu göreceksiniz.

Aylar

Tutar

Ocak

615

Şubat

791

Nisan

511

Haziran

449

Temmuz

230

Mart

449

Eylül

320

Kasım

114




Şimdi başka bir konuya geçelim..

Verileri koleksiyon içine alırken önemli bir ayrıntı da küçük/büyük harf eşleşmesi/duyarlılığıdır.
Karşılaştırma modu (Compare Mode) kullanılmazsa, aynı veri büyük ve küçük harfle ayrı ayrı yazılmışsa, 2 ayrı veri olacak şeklinde koleksiyona alınır. Bu bazı hatalara veya istemediğimiz durumlara yol açabilir. Bu özelliğin sabitlerini yukarıda görmüştük. Şimdi nasıl çalıştığını anlamanız için üç örnek yapacağız.

İlk örnekte CompareMode özelliğini kullanmadan sonucu görelim.
VBA:
Sub ExcelTurkey()
    With CreateObject("Scripting.Dictionary")
        For Each bak In Array("aa1", "AA1", "Aa1", "aA1", "bb1", "BB1", "Bb1", "bB1")
            al = .Item(bak)
        Next bak
        MsgBox .Count
        MsgBox Join(.Keys, vbLf)
    End With
End Sub
İkinci örnekte CompareMode özelliğini 0 yani BinaryCompare şeklinde kullanarak sonucu görelim.
VBA:
Sub ExcelTurkey()
    With CreateObject("Scripting.Dictionary")
        .CompareMode = 0
        For Each bak In Array("aa1", "AA1", "Aa1", "aA1", "bb1", "BB1", "Bb1", "bB1")
            al = .Item(bak)
        Next bak
        MsgBox .Count
        MsgBox Join(.Keys, vbLf)
    End With
End Sub
Bu iki örneğin de aynı sonucu verdiğini görmüş olmalısınız. Yani bu özellik belirtilmez ise varsayılan 0 olarak kabul edilir.

Üçünü örnekte CompareMode özelliğini 1 yani TextCompare şeklinde kullanarak sonucu görelim.
VBA:
Sub ExcelTurkey()
    With CreateObject("Scripting.Dictionary")
        .CompareMode = 1
        For Each bak In Array("aa1", "AA1", "Aa1", "aA1", "bb1", "BB1", "Bb1", "bB1")
            al = .Item(bak)
        Next bak
        MsgBox .Count
        MsgBox Join(.Keys, vbLf)
    End With
End Sub
Kodları denediyseniz, gördüğünüz gibi .CompareMode = 1 ifadesi ile küçük/büyük harf ayırımı olmaksızın, yani büyük de yazılsa küçük de yazılsa tek bir metin olarak kabul edilip koleksiyon içerisinde aldı.


IndexNumber

Key ve Item'larda indeks numaraları belirtilerek istenilen Key ve Item değeri de alınabilir.
Key ve Item özelliğine alına verilerin indeks değeri 0'dan başlar.
Bununla ilgili bir örnek vereyim.
VBA:
Sub ExcelTurkey()
    With CreateObject("Scripting.Dictionary")
        For Each bak In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
            .Item(bak) = bak & "_Excel"
        Next bak
        MsgBox .Item(.Keys()(1)) ' 2. key değeri
        MsgBox .Item(.Keys()(2)) ' 3. key değeri
        MsgBox .Item(.Keys()(.Count - 1)) ' Son key değeri
    End With
End Sub
VBA:
Sub ExcelTurkey()
    With CreateObject("Scripting.Dictionary")
        For Each bak In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
            .Item(bak) = bak & "_Excel"
        Next bak
        MsgBox .Items()(0) ' 1. Item değeri
        MsgBox .Items()(2) ' 3. Item değeri
        MsgBox .Items()(.Count - 1) ' Son Item değeri
    End With
End Sub

Bir de şöyle bir örnek yapalım; yukarıda kullandığımız bir aylar/tutar tablomuz vardı, o verileri kullanarak tablodaki benzersiz verilerin son kayıtlarını alıp listeleyelim. Bu örneği nerede kullanabiliriz derseniz, örneğin; müşterilere kesilen son faturaları, son ürün gönderilerini vs. gibi müşteri, ürün, fatura, stok vs. işlerindeki son kayıtların bir listesini almak istediğinizde kullanabilirsiniz..

Örnek tablomuz bu, yanda da sonuç olarak elde edeceğimiz tablomuzu görüyorsunuz.

Ocak

331

………..

Ocak

284

Şubat

449

 

Şubat

342

Şubat

342

 

Nisan

301

Nisan

210

 

Haziran

449

Ocak

284

 

Temmuz

230

Haziran

449

 

Mart

449

Temmuz

230

 

Eylül

320

Mart

449

 

Kasım

114

Eylül

320

 

Aralık

164

Nisan

301

   

Kasım

114

   

Aralık

164

   


Bu kodlar da istediğimiz işi yapmamız için gereken kodlarımız..
VBA:
Sub Benzersiz_Son_Kayıtları_Listele()
    dizi = Cells(1).CurrentRegion.Resize(, 2).Value
    With CreateObject("Scripting.Dictionary")
        For sat = 1 To UBound(dizi)
            .Item(dizi(sat, 1)) = WorksheetFunction.Index(dizi, sat, 0)
        Next sat
        Range("F1").Resize(.Count, UBound(dizi, 2)) = WorksheetFunction.Index(.Items, 0, 0)
    End With
End Sub

devamı gelecek.. (y)
 
Son düzenleme:

Refaz

Yeni Üye
Katılım
19 Haz 2018
Mesajlar
10
En İyi Yanıtlar
0
Beğeniler
0
Puanları
1
Yaş
41
Konum
Türkiye
Ad Soyad
Zafer
#2
Murat hocam.
Benzersiz değilde sadece mükerrer olanları aldıramıyormuyuz item yada key içine.
Açıklamışssınız yinede bir sorayım istedim.
 
Katılım
23 Eki 2018
Mesajlar
2
En İyi Yanıtlar
0
Beğeniler
1
Puanları
1
Yaş
40
Konum
Kocaeli
Ad Soyad
Zülfü YORULMAZ
#4
Sayın Admin.
Çok güzel ve açıklayıcı bir yazı olmuş, devamını merakla bekliyorum.

Mali Müşavirlik hizmeti veriyorum. Çalıştığım veriler büyük ve " Scripting.Dictionary " gibi nesneler çok işime yarayacak. Bu nedenle iyi öğrenmem gerekir, yazınızın devamını bekliyorum.

Birde sorum olacak. Scripting.Dictionary gibi başka koleksiyon nesneleri de var mı? Bazen işlerimizde bir sayfada bulunan verileri diğer sayfada bulunan veriler ile karşılaştırmak ve aynı olanları belirlememiz gerekiyor. Örnek Sayfa1 de 20.000 satır 103 sütunluk bir verimiz var. Sayfa2 de de 200 satır 103 sütunluk bir verimiz var. Sayfa2 deki her bir satırdaki B,C,D,E,F,G sütunlarındaki verileri Sayfa1 deki aynı sütunlar ile karşılaştıracak eğer varsa Sayfa2 ye ilgili satırın karşısına Var yazacak.

VBA:
Sub Ayn_CB_CC_CT_CU()
'On Error Resume Next
Dim i As Long
Set S1 = Sheets("A1453")
Set S2 = Sheets("CB_CC_CT_CU")
SnStr1 = S1.Cells(1, 1).SpecialCells(xlCellTypeLastCell).Row
SnStr2 = S2.Cells(1, 1).SpecialCells(xlCellTypeLastCell).Row
For t = 4 To SnStr2
    For i = 4 To SnStr1
    If S2.Cells(t, 80) = S1.Cells(i, 80) _
        And S2.Cells(t, 81) = S1.Cells(i, 81) _
        And S2.Cells(t, 96) = S1.Cells(i, 96) _
        And S2.Cells(t, 97) = S1.Cells(i, 97) _
        And S2.Cells(t, 98) = S1.Cells(i, 98) _
        And S2.Cells(t, 99) = S1.Cells(i, 99) _
        Then
    S2.Cells(t, 107) = "Var"
    End If
    Next i
Next t
End Sub
kodlarıyla bu işlemi yapıyoruz ancak çok uzun sürüyor. Bu nedenle Scripting.Dictionary gibi koleksiyon nesnelerini öğrenmek ve uygulayabilmek işlerimizi çok kolaylaştıracak.

Yazınız ve diğer paylaşımlarınız için teşekkürler.
Esenlikler dilerim. İyi çalışmalar.
 
Moderatör tarafında düzenlendi:

Admin

Yönetici
Site Yöneticisi
Katılım
25 May 2018
Mesajlar
1,055
En İyi Yanıtlar
77
Beğeniler
858
Puanları
113
Konum
İstanbul
#5
Merhaba @KarıncaZ,
Dictionary gibi birkaç koleksiyon nesnesi mevcut. ( Stack, Queue, ArrayList, SortedList, Hashtable gibi. )
Ayrıca ADO nesnesi ile SQL'in gücünü kullanarak hızlı raporlar alabilirsiniz.

Saygılar
 
Katılım
7 Haz 2018
Mesajlar
41
En İyi Yanıtlar
9
Beğeniler
44
Puanları
18
Konum
Sakarya-Hendek
#6
@KarıncaZ , And operatorunu en az tekrar edebilecek karşılaştırmadan başlayarak iç içe geçmiş If olarak kullanırsanız karşılaştırma hızı oldukça artacaktır. Bkz : AndAlso
 
Üst Alt