SCRIPTING DICTIONARY
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.
Scripting 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;
Dim sozluk as Object
Set sozluk = CreateObject("Scripting.Dictionary")
Early Binding yöntemiyle bu şekilde sözlüğü tanımlayabiliriz;
Dim sozluk As Scripting.Dictionary
Set sozluk = New Scripting.Dictionary
Bu kodla Microsoft Scripting Runtime referansını seçtirebilir ve kullanabilirsiniz.
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;
With CreateObject("Scripting.Dictionary")
'kodlar'
End With
Scripting 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
.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
sozluk.Add "PEAKUP", "TEKNOLOJİ"
sozluk.Add "Murat", "OSMA"
sozluk.Remove "Murat"
RemoveAll Metodu
Tüm anahtarları sözlük koleksiyonundan kaldırır.
sozluk.RemoveAll
sozluk.Add "PEAKUP", "TEKNOLOJİ"
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
sozluk.Add "PEAKUP", "TEKNOLOJİ"
sozluk.Add "Murat", "OSMA"
MsgBox sozluk.Count
Key Özelliği
Sözlüğe eklenen anahtarı ifade eder.
sozluk.Add "PEAKUP", "TEKNOLOJİ"
buradaki PEAKUP kelimesi Key olarak alınır, TEKNOLOJİ 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("TEKNOLOJİ") = Date
sozluk.Add "PEAKUP", "TEKNOLOJİ"
sozluk.Item("TEKNOLOJİ") = Date
MsgBox sozluk.Item("TEKNOLOJİ")
Şimdiye kadar öğrendiklerimizle şöyle bir örnek yapalım; A1:B10 hücre aralığında birtakım verilerimiz olsun, A sütunundaki verileri Dictionarynesnesinin 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.
Sub PEAKUP()
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
Sub PEAKUP()
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.
Sub PEAKUP()
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.
Sub PEAKUP()
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.
Sub PEAKUP()
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.
Sub PEAKUP()
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
Sub PEAKUP()
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..
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
Sonuçları bu gif resim görebilirsiniz.
Makalemizi beğendiyseniz çevrenizle de paylaşmayı ihmâl etmeyiniz.