Genel Bakış
Class (Sınıf), özellikleri, yöntemleri ve olayları olan bir nesne türünün şablonudur; VBA'da bu şablon bir sınıf modülünde yazılır. Sınıf modülü sayesinde veriyi ve o veriyle çalışan kodu tek bir pakette toplar, New ile istediğiniz sayıda bağımsız nesne (örnek) üretirsiniz. Böylece kodunuz daha düzenli, yeniden kullanılabilir ve bakımı kolay olur.
Kendi sınıfınızı yazmak için Visual Basic Düzenleyicisi'nde Ekle > Sınıf Modülü (Insert > Class Module) komutunu kullanın. Modülün adı, sınıfın adı olur; adı Özellikler (Properties) penceresindeki Name kutusundan değiştirebilirsiniz (pencereyi F4 ile açarsınız). Ad vermede yaygın alışkanlık, clsUrun gibi cls önekini kullanmaktır.
Excel'deki ThisWorkbook modülü, sayfa modülleri ve UserForm modülleri de birer sınıf modülüdür; bu yüzden onlarda da Public değişken, yordam ve olay yazabilirsiniz. Sınıf modülleri yalnızca makro içerebilen dosya türlerinde (xlsm, xlsb, xlam) saklanır; xlsx dosyasına kaydederseniz kod silinir.
Bu yapıda dış dünya yalnızca Ad, Fiyat ve KdvliFiyat üyelerini görür; pAd ve pFiyat gizli kalır. Bu ilkeye kapsülleme denir ve geçersiz değerlerin (ör. negatif fiyat) nesneye girmesini engellemenizi sağlar.
Değişkeni As clsUrun diye tanımlamak erken bağlama (early binding) sağlar: yazarken üye listesi açılır, derleme sırasında yazım hataları yakalanır ve kod daha hızlı çalışır. As Object ile tanımlarsanız geç bağlama olur; bu durumda hatalar ancak çalışma anında ortaya çıkar.
Class_Initialize parametre alamadığı için başlangıç değerlerini bir fabrika işleviyle vermek yaygındır: aynı modülde Public Function UrunOlustur(ad, fiyat) As clsUrun yazar, içinde New ile nesneyi üretir, özelliklerini atar ve işlev adına Set ile geri döndürürsünüz.
İki değişken aynı nesneyi gösterebilir: Set b = a yeni bir nesne üretmez, yalnızca ikinci bir başvuru oluşturur. İki değişkenin aynı nesneye bağlı olup olmadığını Is işleciyle sınarsınız. Nesnenin türünü öğrenmek için TypeName işlevini, belirli bir sınıf olup olmadığını sınamak için TypeOf ... Is yapısını kullanın.
WithEvents ile Excel'in Application nesnesinin olaylarını da yakalayabilirsiniz. Sınıf modülü (örneğin clsUygulamaIzleyici):
Bu sınıfı etkinleştirmek için standart modülde modül düzeyinde bir değişken tanımlar ve bir yordamdan başlatırsınız:
Değişken modül düzeyinde olmalıdır; yordam içinde tanımlarsanız yordam bitince nesne yok olur ve olaylar artık yakalanmaz.
Implements deyimi ise bir sınıfın başka bir sınıfın (arayüzün) üyelerini uygulamasını sağlar. Arayüz sınıfında yalnızca üye başlıkları yazılır; uygulayan sınıfta her üye, arayüzAdı_üyeAdı biçiminde ve Private olarak yeniden yazılmak zorundadır. Böylece farklı sınıflara aynı değişkenle ortak biçimde ulaşırsınız.
Meyve koleksiyonuna eklenen ilk ürün Elma olduğu için C2 hücresine sıra numarası olarak 1 yazılır; Muz üçüncü meyve olduğundan C6 hücresinde 3 görünür. Temizlik koleksiyonu ayrı bir nesne olduğu için kendi sırasını tutar: Deterjan için 1, Çamaşır Suyu için 3. D sütunu her kategorinin toplam öğe sayısını gösterir: Meyve için 3, Temizlik için 3. İki koleksiyon aynı sınıftan üretilmiş olsa da birbirinin verisini etkilemez.
ThisWorkbook için sınıf adı Workbook, etkin sayfa için Worksheet, A1 hücresi için Range olarak bulunur. Application nesnesi Application, New ile üretilen nesne Collection, yazı tipi nesnesi ise Font sınıfındandır. C sütunu TypeOf ... Is sınamasının sonucunu gösterir: etkin sayfa için Evet, ThisWorkbook için Hayır. Böylece bir nesne değişkeninin gerçekte hangi sınıfı gösterdiğini çalışma anında öğrenebilirsiniz.
İlk satırda a nesnesinde 2 öğe vardır. b değişkeni aynı nesneye bağlandığı için b üzerinden eklenen öğe a'da da görünür; ikinci satırdaki sayı 3 olur. c ise New ile üretilmiş ayrı bir nesnedir ve öğe sayısı 0 değerindedir. Is sınamasında a ile b için Evet, a ile c için Hayır sonucu çıkar. a'ya Nothing atandıktan sonra bile nesne b tarafından tutulmaya devam eder; b.Count değeri 3 olarak kalır. Nesne, kendisine bağlı hiçbir değişken kalmayınca bellekten kalkar.
Sınıf ve sınıf modülü nedir
Sınıf, bir nesnenin nasıl görüneceğini ve neler yapabileceğini tanımlayan şablondur. Nesne (örnek, instance) ise bu şablondan New ile üretilen somut kopyadır. Excel'in kendi nesneleri de birer sınıftır: Range, Worksheet, Workbook, Collection gibi. Aynı sınıftan üretilen iki nesne kendi verisini ayrı tutar.Kendi sınıfınızı yazmak için Visual Basic Düzenleyicisi'nde Ekle > Sınıf Modülü (Insert > Class Module) komutunu kullanın. Modülün adı, sınıfın adı olur; adı Özellikler (Properties) penceresindeki Name kutusundan değiştirebilirsiniz (pencereyi F4 ile açarsınız). Ad vermede yaygın alışkanlık, clsUrun gibi cls önekini kullanmaktır.
Excel'deki ThisWorkbook modülü, sayfa modülleri ve UserForm modülleri de birer sınıf modülüdür; bu yüzden onlarda da Public değişken, yordam ve olay yazabilirsiniz. Sınıf modülleri yalnızca makro içerebilen dosya türlerinde (xlsm, xlsb, xlam) saklanır; xlsx dosyasına kaydederseniz kod silinir.
Sınıf modülünün yapısı
Bir sınıf modülü şu öğelerden oluşabilir:- Private değişkenler: nesnenin iç verisini tutar; dışarıdan doğrudan erişilmez.
- Property Get / Property Let / Property Set: özelliği okumak (Get), değer atamak (Let) ve nesne atamak (Set) için kullanılır. Özellik salt okunur olacaksa yalnız Property Get yazılır.
- Public Sub ve Function: nesnenin yöntemleridir; Sub değer döndürmez, Function döndürür.
- Class_Initialize: nesne New ile oluşturulurken otomatik çalışır; başlangıç değerlerini atamak için kullanılır. Parametre almaz.
- Class_Terminate: nesne bellekten kaldırılırken çalışır; kaynakları temizlemek için kullanılır.
- Instancing: sınıfın Özellikler penceresindeki ayarıdır. Varsayılan Private'tır; PublicNotCreatable seçeneği sınıfı başka projelerin görmesine izin verir ama onlar New ile örnek üretemez.
VBA
35 satır
Option Explicit
Private pAd As String
Private pFiyat As Double
Private Sub Class_Initialize()
pFiyat = 0
End Sub
Public Property Get Ad() As String
Ad = pAd
End Property
Public Property Let Ad(ByVal Deger As String)
pAd = Deger
End Property
Public Property Get Fiyat() As Double
Fiyat = pFiyat
End Property
Public Property Let Fiyat(ByVal Deger As Double)
If Deger < 0 Then
Err.Raise vbObjectError + 1000, "clsUrun", "Fiyat negatif olamaz."
End If
pFiyat = Deger
End Property
Public Function KdvliFiyat(ByVal Oran As Double) As Double
KdvliFiyat = pFiyat * (1 + Oran)
End Function
Private Sub Class_Terminate()
' Nesne bellekten kalkarken çalışır
End Sub
Sınıfı kullanma
Sınıfı kullanmak için önce nesne değişkenini tanımlar, sonra Set ve New ile örneği oluşturursunuz. İşiniz bitince Set ile Nothing atayarak başvuruyu bırakabilirsiniz. Nesne değişkenine atama her zaman Set ile yapılır; Set yazmazsanız Excel nesnenin varsayılan özelliğini atamaya çalışır ya da hata verir. Standart modülde şöyle kullanılır:
VBA
10 satır
Sub UrunDene()
Dim u As clsUrun
Set u = New clsUrun
u.Ad = "Kalem"
u.Fiyat = 12.5
Debug.Print u.Ad, u.KdvliFiyat(0.2)
Set u = Nothing
End Sub
Class_Initialize parametre alamadığı için başlangıç değerlerini bir fabrika işleviyle vermek yaygındır: aynı modülde Public Function UrunOlustur(ad, fiyat) As clsUrun yazar, içinde New ile nesneyi üretir, özelliklerini atar ve işlev adına Set ile geri döndürürsünüz.
İki değişken aynı nesneyi gösterebilir: Set b = a yeni bir nesne üretmez, yalnızca ikinci bir başvuru oluşturur. İki değişkenin aynı nesneye bağlı olup olmadığını Is işleciyle sınarsınız. Nesnenin türünü öğrenmek için TypeName işlevini, belirli bir sınıf olup olmadığını sınamak için TypeOf ... Is yapısını kullanın.
Olaylar, WithEvents ve Implements
Sınıflar kendi olaylarını tanımlayabilir. Sınıf içinde Public Event ile olayı bildirir, uygun yerde RaiseEvent ile tetiklersiniz. Olayı dinleyen kod ise nesne değişkenini WithEvents ile tanımlar; WithEvents yalnızca sınıf modüllerinde, UserForm'larda ve belge modüllerinde modül düzeyinde kullanılabilir.WithEvents ile Excel'in Application nesnesinin olaylarını da yakalayabilirsiniz. Sınıf modülü (örneğin clsUygulamaIzleyici):
VBA
5 satır
Public WithEvents App As Application
Private Sub App_NewWorkbook(ByVal Wb As Workbook)
Debug.Print "Yeni kitap açıldı: " & Wb.Name
End Sub
VBA
6 satır
Dim izleyici As clsUygulamaIzleyici
Sub IzlemeyiBaslat()
Set izleyici = New clsUygulamaIzleyici
Set izleyici.App = Application
End Sub
Implements deyimi ise bir sınıfın başka bir sınıfın (arayüzün) üyelerini uygulamasını sağlar. Arayüz sınıfında yalnızca üye başlıkları yazılır; uygulayan sınıfta her üye, arayüzAdı_üyeAdı biçiminde ve Private olarak yeniden yazılmak zorundadır. Böylece farklı sınıflara aynı değişkenle ortak biçimde ulaşırsınız.
1. Collection sınıfından bağımsız örnekler
Aynı sınıftan üretilen nesneler birbirinden bağımsızdır. Bu örnekte Collection sınıfından New ile iki ayrı nesne oluşturulur; ürünler kategorisine göre ilgili koleksiyona eklenir. Kodu Ekle > Modül ile açtığınız standart modüle yapıştırın.
VBA
33 satır
Option Explicit
' Collection sınıfından iki ayrı nesne (örnek) oluşturur
Sub KoleksiyonlariDoldur()
Dim ws As Worksheet
Dim meyve As Collection
Dim temizlik As Collection
Dim i As Long
Set ws = ActiveSheet
Set meyve = New Collection
Set temizlik = New Collection
' Her ürünü kategorisine uygun koleksiyona ekle
For i = 2 To 7
If ws.Cells(i, 2).Value = "Meyve" Then
meyve.Add ws.Cells(i, 1).Value
ws.Cells(i, 3).Value = meyve.Count
Else
temizlik.Add ws.Cells(i, 1).Value
ws.Cells(i, 3).Value = temizlik.Count
End If
Next i
' Her satıra kendi koleksiyonunun toplam öğe sayısını yaz
For i = 2 To 7
If ws.Cells(i, 2).Value = "Meyve" Then
ws.Cells(i, 4).Value = meyve.Count
Else
ws.Cells(i, 4).Value = temizlik.Count
End If
Next i
End Sub
Class
Formülünü incelemek için bir hücre seçin.| A | B | C | D | |
|---|---|---|---|---|
| 1 | Ürün | Kategori | Koleksiyondaki Sıra | Koleksiyon Toplamı |
| 2 | Elma | Meyve | 1 | 3 |
| 3 | Deterjan | Temizlik | 1 | 3 |
| 4 | Portakal | Meyve | 2 | 3 |
| 5 | Sabun | Temizlik | 2 | 3 |
| 6 | Muz | Meyve | 3 | 3 |
| 7 | Çamaşır Suyu | Temizlik | 3 | 3 |
Ürün ListesiExcelDepo v1.0.0
2. Nesnenin sınıfını öğrenme
Her nesne bir sınıfa aittir. TypeName işlevi nesnenin sınıf adını döndürür, TypeOf ... Is yapısı ise nesnenin belirli bir sınıftan olup olmadığını sınar. Kodu standart modüle yapıştırın; sınıf adları B sütununa, Worksheet sınaması C sütununa yazılır.
VBA
29 satır
Option Explicit
' Farklı nesnelerin sınıf adlarını sayfaya yazar
Sub SinifAdlariniYaz()
Dim ws As Worksheet
Dim nesneler(1 To 6) As Object
Dim i As Long
Set ws = ActiveSheet
Set nesneler(1) = ThisWorkbook
Set nesneler(2) = ActiveSheet
Set nesneler(3) = ws.Range("A1")
Set nesneler(4) = Application
Set nesneler(5) = New Collection
Set nesneler(6) = ws.Range("A1").Font
For i = 1 To 6
' Sınıf adı
ws.Cells(i + 1, 2).Value = TypeName(nesneler(i))
' Nesne Worksheet sınıfından mı?
If TypeOf nesneler(i) Is Worksheet Then
ws.Cells(i + 1, 3).Value = "Evet"
Else
ws.Cells(i + 1, 3).Value = "Hayır"
End If
Next i
End Sub
Class
Formülünü incelemek için bir hücre seçin.| A | B | C | |
|---|---|---|---|
| 1 | Nesne İfadesi | Sınıf Adı | Worksheet mi? |
| 2 | ThisWorkbook | Workbook | Hayır |
| 3 | ActiveSheet | Worksheet | Evet |
| 4 | Hücre A1 | Range | Hayır |
| 5 | Application | Application | Hayır |
| 6 | New Collection | Collection | Hayır |
| 7 | Hücre A1 yazı tipi | Font | Hayır |
Nesne TürleriExcelDepo v1.0.0
3. Nesne başvurusu ve Is işleci
Nesne değişkenleri nesnenin kendisini değil, ona giden bir başvuruyu tutar. Bu örnekte Set b = a ile aynı nesneye ikinci bir başvuru oluşturulur; New ile ise ayrı bir nesne üretilir. Kodu standart modüle yapıştırın.
VBA
43 satır
Option Explicit
' Başvuru atama ile yeni örnek oluşturma arasındaki farkı gösterir
Sub BasvuruTesti()
Dim ws As Worksheet
Dim a As Collection
Dim b As Collection
Dim c As Collection
Set ws = ActiveSheet
' a nesnesine iki öğe ekle
Set a = New Collection
a.Add "Ocak"
a.Add "Şubat"
ws.Cells(2, 2).Value = a.Count
' b aynı nesneyi gösterir; b üzerinden öğe ekle
Set b = a
b.Add "Mart"
ws.Cells(3, 2).Value = a.Count
' c yeni ve boş bir nesnedir
Set c = New Collection
ws.Cells(4, 2).Value = c.Count
' Is işleci ile nesne eşitliği sınaması
If a Is b Then
ws.Cells(5, 2).Value = "Evet"
Else
ws.Cells(5, 2).Value = "Hayır"
End If
If a Is c Then
ws.Cells(6, 2).Value = "Evet"
Else
ws.Cells(6, 2).Value = "Hayır"
End If
' a başvurusunu bırak; nesne b sayesinde yaşamaya devam eder
Set a = Nothing
ws.Cells(7, 2).Value = b.Count
End Sub
Class
Formülünü incelemek için bir hücre seçin.| A | B | |
|---|---|---|
| 1 | Deneme | Sonuç |
| 2 | a: iki öğe eklendi, a.Count | 2 |
| 3 | b = a atandı, b ile öğe eklendi, a.Count | 3 |
| 4 | c = New Collection, c.Count | 0 |
| 5 | a Is b | Evet |
| 6 | a Is c | Hayır |
| 7 | a = Nothing sonrası b.Count | 3 |
Başvuru TestiExcelDepo v1.0.0
Kullanırken dikkat edin
- Set unutmayın: Nesne değişkenine atama Set ile yapılır. Set kullanmadan atama yapmak ya da New ile örneği hiç oluşturmadan üyeye erişmek, 'Nesne değişkeni ya da With bloğu değişkeni ayarlanmamış' (Object variable or With block variable not set, hata 91) iletisine yol açar.
- Dim ... As New kullanımından kaçının: Tanımlama satırında As New yazarsanız nesne ilk kullanıldığı anda oluşur. Nothing atadıktan sonra değişkene tekrar dokunmanız nesneyi sessizce yeniden yaratır. Tanım ile örnek oluşturmayı ayrı yapmak (Dim, sonra Set ... New) davranışı daha öngörülebilir kılar.
- Class_Initialize parametre almaz: Sınıf oluşturulurken değer geçirmek istiyorsanız Class_Initialize kullanamazsınız. Bunun yerine nesneyi üretip özelliklerini atayan bir fabrika işlevi yazın ya da Init gibi bir yöntem tanımlayın.
- Sınıf modülü doğrudan çalıştırılmaz: Sınıf modülündeki bir Sub'ı F5 ile ya da Makrolar penceresinden çalıştıramazsınız; önce standart modülden sınıfın bir örneğini oluşturmanız gerekir. Sınıfı başka bir projeye taşımak için modülü sağ tıklayıp dosyaya aktarabilir (Export) ve diğer projeye içe aktarabilirsiniz.
- Döngüsel başvurular bellek sızdırır: İki nesne birbirini özellik olarak tutuyorsa, dışarıdaki tüm değişkenlere Nothing atasanız bile nesneler bellekten kalkmayabilir ve Class_Terminate çalışmaz. Karşılıklı başvuru gerekiyorsa işiniz bitince başvurulardan birini elle Nothing yapın.
- WithEvents değişkeni uygun yerde olmalı: Olay dinleyen nesne değişkeni modül düzeyinde tanımlanmalıdır. Yordam içinde tanımlanan değişken yordam bitince yok olur ve olaylar yakalanmaz. Ayrıca WithEvents standart modüllerde kullanılamaz.
- Sınıf içinde alan adlarını özellik adından ayırın: Private değişkene pAd, özelliğe Ad gibi farklı adlar verin. Aynı adı kullanamazsınız; ön ek alışkanlığı kodun okunmasını da kolaylaştırır.
- İlgili konular:
- Set, New ve Nothing: nesne oluşturma ve başvuru bırakma
- Property Get, Property Let, Property Set: sınıf özellikleri
- Implements: arayüz uygulama
- WithEvents, Event, RaiseEvent: sınıfta olay tanımlama ve dinleme
- TypeName ve TypeOf ... Is: nesne türünü sınama
- Is işleci: iki nesne başvurusunu karşılaştırma
- Collection nesnesi: hazır bir sınıf örneği
- CallByName: özelliğe ya da yönteme adıyla erişme
- UserForm modülü ve ThisWorkbook: sınıf modülü olarak çalışan belge modülleri
- Ekle > Modül (Insert > Module): standart modül oluşturma