VBA-4: Karar Yapıları ve Nesneler(Sayfalar,Hücreler vs) ile Etkileşim

Excel’de önceki yazımızda sizlere fonksiyonlar ve operatörleri anlattım. Buraya kadar yaptığımız çoğu şeyi kod yazmadan da yapabilirdiniz. Bu bölümde ise sizlere, VBA’nın basit makro ve formüllerden güçlü olan yanlarından nesnelere erişimden ve karar yapılarından bahsedeceğim.

Yazılarımız devam serisi olduğu için önceki yazıları okumanızı şiddetle tavsiye ederim. Aksi halde kurduğunuz binanız temelsiz yükselir ve yıkılır.

Öncelikle Visual Basic Düzenleyicisine makro üzerinden giriş yapmak yerine, Alt+F11 ile geçelim. Görseldeki gibi Project – VBAProject yazan pencereden, bende syfGiris yazan, sizde Sayfa1 yazan yere çift tıklayın. Sağ taraftaki pencerenin sayfa1 içindeki kod bloklarını gösterecek(tabi kod yoksa boş görünecek) şekilde değiştiğini göreceksiniz.

Hemen alttaki Properties – Sayfa1 yazan pencerede (name) kısmının sağındaki metin kutusuna gelip syfGiris olarak değiştiriyoruz. Bu sayfaya bundan sonra syfGiris diyeceğim

SExcelde sayfaların 2 adı bulunur. İlki formüllerden aşina olduğunuz görünür adlarıdır. Diğeri ise benim örnekte syfGiris olarak adlandırdığım,  VBA kodlarından kolay erişim sağlamak için kullanılan addır. Bu VBA adları değişken ve fonksiyon isimleri gibi adlandırılmalıdır. Türkçe karakter kullanmaktan kaçınılması gerekmektedir.

 

              Görseldeki kodları VB Düzenleyicisinde sağda çıkan pencereye aynen yazdığınızda, kodları yazdığınız sayfa içerisinde, 2’inci satırdan sonraki 1 nolu sütuna(A2:A) birşeyler yazdığınızda, aynı satırdaki 2 nolu sütuna(B2:B) tarih-saat yazar. Sildiğinizde ise o satırdaki tarih saat yazdığı alanı boşaltır. Daha detaylı tarifi kodlarda saklıdır. 😉 Bu arada B:B sütununa biçimlendirme yapmazsanız, yazdığınız gün ve saate göre 40-50 bin ile başlayan bir sayı yazabilir. O yüzden B:B sütununu aşağıdaki gibi biçimlendirelim.

 

Kodları syfGiris içine aynen
yazdığınızı varsayıyorum.

Eğer sabırsızlık edip
makrolara baktıysanız bu subrutini göremeyeceksiniz. Çünkü makroların excel makro
penceresinden tetiklenebilmesi için değer alanının(parantez içinin) boş
olması(burda Target var) ve “Private” yazan yerin “Public
ya da boş olması gerekmektedir.

Kodları yazarken hatalarınız
olduysa, yazarken VB editörü uyaracaktır. Eğer çalışırken hatalı çalışıyorsa,
araç çubuğunda play ve pause benzeri tuşların sağındaki stop(kare olan) tuşuna
basıp, düzenleme yapabilir, tekrar deneyebilirsiniz.

Gelin şimdi bu kodu adım adım
inceleyelim. Öncelikle kodun ilk satırında hata ayıklama moduna girmesi için, “Private
Sub
” ile başlayan satırın solundaki gri alana tek tık yaparak “breakpoint
oluşturalım, görseldeki gibi bordo bir satır oluşacaktır. Kod çalıştığında bu
bordo alan sarı görünecek ve kodun işletilmesi duracaktır. Bundan sonra
aşağıdaki her satır için 1 defa F8 e basacağız ve satır satır kod ilerlerken, fare
ile etiketlerin üzerine giderek mevcut değerleri öğrenebilirsiniz. Mesela “Private Sub …” satırını geçtikten
sonra, Target yazısı üzerine fare imlecini götürdüğünüzde, excel hücresine
yazdığınız değer görünecektir.

 

Private Sub
Worksheet_Change(Byval Target As Range)

              Bu
satır bir subrutini  tanımlar, ancak önceki
gördüğümüz subrutinlerden farklı olarak bu bir olaydır, yani event. Bu
subrutini excel makro penceresinden çağıramazsınız. Sadece VBA kodlarıyla ve bulunduğu
kod sayfasının ait olduğu sayfadaki hücrelerde değişiklik olduğunda tetiklenebilir.

              Peki
burada parantez içi ne anlama geliyor? “ByVal” etiketini şimdilik görmezden
gelelim. Subrutinlerin değer döndürmesi ile ilgili olup, ileride değineceğiz. “Target
As Range
” kısmına gelirsek… Burada Target aslında bir değişkendir, aynı
zamanda bir nesnedir. Excel bize değiştirilen hücre bilgisini Target nesnesi üzerinden bildirmiştir. Ve
As Range” ile onun bir Range sınıfı
olduğu belirtilmiştir.

Kod sayfasında nesnenin tanımlandığı subrutin ya da
fonksiyon içerisinde bir satıra nesne adı yazıp, yanına nokta koyduğunuzda, o
nesnenin alt özellikleri listelenir. O özellikler üzerinden nesneye ait
bilgiler öğrenilebilir, değiştirilebilir, fonksiyonları çağrılabilir. Yani “Target.ClearContents” subrutini 
ile o hücrenin içeriği temizlenebilir, “Target.Value” ile hücrede yazan değer alınabilir ve değiştirilebilir. Ancak kodlarda değiştirilen hücrenin değerini almak için sadece “Target” kullandık. Sebebi bu nesnenin varsayılan özelliğinin “Value” olmasıdır.

 

 

If Target.CountLarge = 1 Then

…’Doğruysa

Else

…’Yanlışsa

End if

 

 

              Bu bir if bloğudur. If bloğu VBA’nın karar mekanizmalarından biridir. “Target.CountLarge=1” önermesi doğru ise “if … Then” ile “Else” arasındaki kodları, yanlışsa “Else” ile “End if” arasındaki kodları çalıştırır.

              Bu önerme değiştirilen hücre sayısını sorgular. Mesela birkaç satır seçip delete tuşuna basarsanız ya da bir alan seçip aktif olan hücreye yazı yazıp CTRL+ENTER ile sonlandırırsanız birden fazla hücre değiştirilmiş olur. Bu durumda kod görselinde if ile aynı hizadaki en alttaki else deyimine atlar ve “Application.Undo” fonksiyonunu çalıştırır. Bu da tahmin edeceğiniz gibi yapılan işlemi geri alacaktır. Yani bu kod bloğu çalıştığı sürece birden fazla hücreyi değiştiremezsiniz.

              Sadece tek hücre değiştirildiğinde ise alttaki kod bloğu çalıştırılmaktadır.

 

If Target.Column = 1 And Target.Row > 1 Then

            If Target = “” Then

                Cells(Target.Row, 2).ClearContents

            ElseIf Cells(Target.Row, 2).Value = “” Then

                Cells(Target.Row, 2).Value = Now

            End If

End If

 

              Buradaki ilk kodumuz yine if yapısı… Burada “Target.Column = 1” ile değiştirilen hücrenin A:A sütununda yer aldığı kontrol edilmektedir. “Target.Row > 1” ile değiştirilen hücrenin 2:2 ve sonraki satırları olduğu kontrol edilmektedir. “AND” komutu ise tahmin edebileceğiniz gibi bu iki önermeyi birbirine bağlar ve ikisinin de DOĞRU olması durumunda DOĞRU sonucu döndürür. Yani eğer değiştirilen hücre A2 ve altındakilerden biriyse “if …THEN” ile “End if” komutları arasındaki blok işlenir. Dikkatinizi çekeceği üzere bu if bloğunda “ELSE” komutu bulunmamakta, haliyle önerme yanlış olduğunda işletilecek bir kod bloğu bulunmamaktadır.

              Bu if bloğunun içindeki;

If Target = “” Then kodu değiştirilen hücrenin boş olup olmadığını denetler. Metin değerleri 2 adet çift tırnak içerisinde gösterilmektedir. Dolayısıyla iki çift tırnak arası boş olduğu için, değiştirilen hücrenin boş olup olmadığını sorgular. Eğer değiştirilen hücre boşsa;

Cells(Target.Row, 2).ClearContents komutunu işletir. Parantez içindeki “Target.Row”, yukarıda da farkettiğiniz üzere değiştirilen hücrenin satır numarasını verir. “Cells()” ise parantez içine isteğe bağlı olarak “Satır, Sütun” bilgisini girerek hücreye ait Range sınıfı bir nesne elde edersiniz. Yani burada değiştirilen hücrenin satırında, 2’inci sütununun(B:B) kesiştiği hücreyi temsil eder. Sonrasındaki “.ClearContents” ise bu hücrenin sadece içeriğini silen bir subrutin çalıştırır.

 

ElseIf Cells(Target.Row, 2).Value = “” Then komutu ise tahmin edeceğiniz üzere aynı hizadaki if bloğuna bağlı olup(ki hizaların bir önemi yoktur, sıralama önemlidir), önceki if komutu içindeki önerme doğruluğu sağlamadığı durumda çalıştırılır. Bu komutlarda da tarih yazan B:B sütunundaki aynı hizadaki verinin boş olması sorgulanıyor. Eğer tarih kısmı boş ise,

Cells(Target.Row, 2).Value = Now komutu işletilir. Önceki derste dikkat ettiyseniz atama yapılacak değişken solda, değer ise sağda bulunuyordu. Bu komuttan da anlayacağınız üzere tarih sütununa şimdiki zamanı atamaktadır. “Now” yerine “Date” ya da “Time” yazarak farkları da görebilirsiniz.

End If komutu ise anlayacağınız üzere aynı hizada gösterdiğim if bloğunun sonudur.

 

Bu komutları F8’e basarak işleyişini incelediyseniz, “Cells() = Now” komutundan sonra tekrar “Private Sub …” satırına döndüğünü farketmişsinizdir. Bunun sebebi o komutun hücreyi değiştirmesi, buna istinaden yeni bir olay(event) oluşturması ve yine Range sınıfı yeni bir hücre nesnesiyle aynı subrutini çağırmasıdır. “End Sub” komutuna geldiğinde ise ilk çağırılan subrutin kaldığı yerden devam etmektedir. Bu konu VBA’nın en çetrefilli ve can sıkıcı durumu olup, kod sırasına ve karar yapılarına dikkat edilmediği takdirde sürekli kendini çağıran ve sonunda yığın taşma hatası(stack overflow) veren bir kod parçasına dönüşebilir. Bu şekilde hata verme sebebi ise her subrutin veya fonksiyon çağrıldığında kaldığı yeri not etmesi ve ramde ayrılan bu alanın dolması nedeniyle yeni subrutin çağıramayacağı içindir.

              Aklınıza en üstte sayfa1 yazan yeri neden syfGiris olarak değiştirdiğimiz gelecektir. Aslında şu kod bloğunda bunun bir önemi yok. Ancak farkettiğiniz üzere sayfa ismi vermeden hücrelere eriştik. Peki hangi sayfanın hücresini kastettiğimi nerden biliyor bu uygulama? “Cells(1,1)” nesnesini kullandığımız sayfa syfGiris’in kod sayfasıydı. Bu nedenle VBA da bu nesneyi, kodun yazıldığı sayfanın elemanı olarak değerlendirmiştir. Haliyle “Cells” nesnesini başka bir sayfanın kodunda kullanırsanız o sayfadaki, bir makroda(module’de) kullanırsanız, excelde açık olan aktif sayfadaki(ActiveSheet nesnesindeki) ilgili hücreyi değiştirecektir. Bu karmaşadan kurtulmak için ise “syfGiris.Cells(…)” şeklinde Cells den önce sayfa adımızı yazıp nokta koyarak değiştirilecek alanı tanımlıyoruz.

 

If bloklarıyla ilgili son söze gelirsek… Else kullanmayacaksak eğer;

If Target = “” Then Cells(Target.Row, 2).ClearContents

şeklinde tek satırlık if komutları kullanılabilir. Hatta alttaki gibi birden fazla kodu da aralarına iki nokta koyarak tek satırda yazabilirsiniz.

If Target = “” Then Cells(Target.Row, 2).ClearContents: Exit Sub

Bir diğer if bloğu kullanımı ise; uzun satırları bölmeye yarayan boşluk ile alt çizgi( _) kullanımı iledir. Ancak hizalama kurallarına uymadığınız taktirde kodun okunabilirliği zorlaşmaktadır.

If Target = “” Then _

Cells(Target.Row, 2).ClearContents

VBA’da karar yapılarını, nesneleri ve bir olayı en basit haliyle sizlere anlatmaya çalıştım. Umarım faydalı olmuştur. Okuduğunuz için teşekkürler ederim.

 

Kodlarınız kararlı, işleriniz yararlı olsun. 🙂

 

             

 

Bu arada bir an evvel VBA öğrenmeliyim, blog yazılarını bekleyemem, uzun videoları severim, sıkılmam izlerim diyorsanız; alttaki linkten VBA’yı anlattığım videoyu da seyredebilirsiniz. 🙂

Paylaş:

Diğer Blog Yazıları

Skip to content