Programlamanın temel taşlarından biri koşullu yapılarsa, koşullu yapıların
temeli de IF bloklarıdır. Birçok programlama dilinde de zaten bu yapı kullanılır,
sadece syntaxı farklı olabilmektedir.
Boolean değişkenler ve If blokları
"If X=4" mü diye bir sorgulama yaparken aslında X=4 sonucu True mu False mu(doğru
mu yanlış mı) şeklinde
bir sorgulama yapmış oluyoruz. Aksi belirtilmedikçe tüm
sorgulamalarda sonucun True mu olduğunu sorgulamış oluruz, ve True ise Then
ifadesinden sonraki kısım işletilir.
If bloklarında False sorgulaması da yapılabilir, bunun için açıkça If x=
False diye sormak gerekir, tabi x'in boolean tipinde olması kaydıyla. Böylece ifadenin
False olması durumunda da Then'den sonraki kısmın işletilmesi sağlanabilir.
Unutulmamalıdır ki yaratılmış ancak henüz değer atanmamış Boolean
değişkenlerin değeri False'tur. Bazen bu bilgi çok kullanışlı olmaktadır.
Bi örnek yapalım: Kullanıcıdan ismini girmesini isteriz ve
bu ismi, arasında ";" olacak şekilde 10 kere yazdırmak istiyoruz diyelim. Şimdi ilk başta
hatalı bir kod yazalım. Bu kodda en başta da istenmeyen bir ";" olacak.
Sub booleanif1()
isim = InputBox("İsminizi girin")
For i = 1 To 10
kelime = kelime + ";" + isim
Next i
MsgBox kelime
End Sub
Gördüğümüz gibi en baştaki ; fazladan oldu.
Ancak kodumuzda aşağıdaki gibi False sorgulamasını yaparsak istediğimizi
elde ederiz.
Sub booleanif1()
Dim ilkDegerAtandımı As Boolean
isim = InputBox("İsminizi girin")
For i = 1 To 10
If ilkDegerAtandımı = False Then 'İlk etapta Falsetur, ve false ise bu kısım işletilir
kelime = isim
Else
kelime = kelime + ";" + isim
End If
ilkDegerAtandımı = True 'False'tan True'ya ilk geçişi burada yapıyoruz, sonrasında zaten 9 kez zaten True olan değere True atamış olacak
Next i
MsgBox kelime
End Sub
Başka bir örnek daha yapalım, bunu Interaktivite bölümünde de görmüştük,
kullanıcı InputBoxa giriş yapmadan çıkarsa bunu yakalayalım. Detay için
buraya bakınız.
Sub booleanif2()
a = Application.InputBox("Yaşınızı girin", Type:=1)
If a = False Then 'Variant her değeri alabileceği için False ifadesi aynen yazılır
MsgBox "Bir giriş yapılmadan çıkmayı tercih ettiniz"
'Diğer kodlar buraya
Else
MsgBox "Giriş yapıldı"
End If
End Sub
NOT:Boolean ifadelerde True sorgulaması yaparken "=True" yazmaya gerek yoktur,
o yüzden içinde = operatörü olmayan bir sorgulama şekli gördüğünüzde
şaşırmayın. Aşağıda bir örnek var.
Sub yaskontrol()
Dim yas As Integer
Dim resitmi As Boolean
yas = Application.InputBox("yaşınızı girin", Type:=1)
If yas >= 18 Then resitmi = True 'else durumunda False atamaya gerek yok hiçbir atama olmaz, atanmamaış boolenalar da default değeri yani false değeirini alır
If resitmi Then '=True yazmadık, yazabilirdik de.
MsgBox "reşitsin"
Else
MsgBox "reşit değilsin"
End If
End Sub
Bu yöntemi sadece değişkenlerle değil Booelan tipli dönüşü olan fonksiyon veya propertylerle de kullanabiliriz.
If Application.DisplayAlerts Then '=True yazmamama gerek yok çünkü DisplayAlerts propertysi Booelan döndürür
'kodlar
End If
Mantıksal kontroller
If ile birlikte kullanılan bazı built-in kontrol yapıları vardır. Yani =,
<, > ve is operatörlerinden başka bir de bu ifadelerle kontrol
sağlanır, ki bunlar da aslında Boolean sorgulama şekilleridir.
- IsEmpty:(Variant
tipli) değişken boşmu, yani henüz bir değer atanmadı mı?
Veya bir hücrenin içi boş mu?
- IsDate:Değişken, tarihsel bir değişken mi?
Pratikte, Inputboxa girilen bir
tarihin doğru formatta girilip girilmediğini kontrol etmek için
kullanılır.
- IsNumeric:Değişken sayısal mı? Inputboxa sayısal girilmesi
gereken bir verinin doğru girilip girilmediğini kontrol amaçlı
kullanılabildiği gibi, bir hücredeki verinin sayısal veri içerip
içermediğini kontrol etmek için de kullanılır. Gerçi Inputboxı
Application.Inputbox şeklinde kullanıp bir de veritipi olarak 1 seçersek
zaten kullanıcıyı otomatikman sayısal girmeye zorlamış oluruz ama normal
Inputboxla sorulduğunda bunu kontrol amaçlı kullanabilirsiniz.
- IsNull:Değişken, bir veri içeriyor mu?
Bütün bunları Not operatör ile ters mantıkta
sorgulayabilirsiniz. Bu konuyu bir alt bölümde göreceğiz.
Çeşitli örnekler:
1.Örnek
'bulunduğunuz yerden ilk dolu hücreye kadar olan tüm boş hücreleri silmek için
'tabi bu örneği bir döngü içinde yapmak daha şık olurdu ancak burda örnek vermek
'adına If ve GoTo ile yapılmıştır
bas:
If IsEmpty(ActiveCell) Then
ActiveCell.EntireRow.Delete
ActiveCell.Offset(1,0).Select
GoTo bas
End If
2.Örnek
'Be'Belli bir anda aktif hücrenin değerinin sayısal olmaması durumunda programı durduruyoruz
If IsNumeric(ActiveCell.Value) Then Exit Subre>
If Not
Bazen bir kodu günlük konuşma dilinde olduğu gibi önce negatifini
sorgulayarak yazmak isteyebiliriz. X=y değilse şu kod çalışsın. Biraz kötü
bir örnek olacak ama mesela aşağıdaki kodda, sadece 18 yaşından küçükler
için çalışacak bir kod yazmış oluyoruz.
'Öncül kodlar
If Not Yaş>18 Then
'işletilecek kod
End If
'diğer kodlar
Kötü bir örnek dedik çünkü burda if Yaş<=18 diye yazsaydık daha
az kodla yazılmış olurdu. Evet olurdu, ancak bazen öyle durumlar olacak ki
günlük konuşma diline göre kod yazmak size daha rahat gelecek ve negatifi sorgulamak
da daha mantıklı
olacaktır.
Şimdi mybooelan adına bir Boolean tipli değişkeniniz olsun. Bu durumda
If
Not myboolean yazmak ile If mybooolean=False yazmak arasında bir fark yok
gibi görünebilir ancak hem konuşma diline yakınlığı dolayısıyla
anlaşılırlığı hem de performans açısından Not'lı versiyon biraz daha
öndedir. Çünkü önce mybooleanını ne olduğunu hesaplıyor, bu 1; sonra bunun
False mu olduğuna bakıyor, bu da 2. Halbuki Not diyince sadece
1 değerlendirme işlemi yapmış oluyorsunuz. Ancak bu performans farkı o kadar
da büyük bir fark değil. Bu konu, daha çok okunaklılık ve kişisel tercihle
alakalıdır.
Not yöntemi pratikte en çok Boolean karşılaştırmalarda kullanılır ve
özellikle de Booelan değer dönüren bir fonksiyonu sonucu ile. Mesela
DosyaMevcutmu diye bir fonksiyonunuz olsun, eğer mevcutsa True, değilse
False döndürüyor olsun. Hergün saat 12de bir dosyanın oluşup oluşmadığına
bakan scheduled bir kodunuz olsun. Eğer dosya henüz oluşmamışsa kullanıcılara mail atmadan çıksın,
oluştuysa mail atsın.
If Not DosyaMevcutmu(dosyadı) Then
Exit Sub
Else
'uzunca bir mail atma kodu
End If
Şimdi yine bir itiraz gelebilir, bu örnekte de aslında Not kullanmasak
olabilir, ilk başa DosyaMevcutmu diye yazar mail işlemini Else öncesine
koyabilir, Exit Sub'ı da Else sonrasına. Ancak gördüğünüz gibi mail işemi
oldukça
uzun olabilir, mesela 50 satır. Böyle bir durumda ilk bloğa daha kısa olan kodu koymak daha mantıklı ve okunaklıdır.
Böylece dosya oluşmadıysa ne yapılacağını çok net görebilyorum, ancak başa
dosya oluşma durumunu koyup Else'den sonra oluşmama durumuu koysaydık
Else'den sonra ne olduğunu görmek için scrollbarı aşağı indirmek
gerekecekti. Küçük bir detay ama bu tür pratiklikler size hep zaman kazandırır.
Zaten makroların amacı da bu değil mi, bize her anlamda zaman kazandırmak. O
yüzden kodlarımızı düzenlerken en okunaklı, bi zaman sonra tekrar içine
baktığınıza anlaması en kısa sürecek şekilde düzenlemekte fayda var. Bu
arada bu kod da pek tabiki Not DosyaMevcutmu yerine
DosyaMevcutmu =False şeklinde yapılabilirdi ama yine okunurluk açısından
Not'lı halini gündelik dile daha çok
benzetiyorum. Tercih sizin.
Mantıksal fonksiyonlarla Not kullanımı
Yine mantıksal fonksiyonların ters sorgulaması yapıldığında False
ile sorgulamak yerine gündelik dile daha yakın olması açsıından
Not ile sorgularız. Ör:Kullanıcının boş mu
dolu mu bir hücre seçtiğini kontrol edecek bir kod yazalım.
tekrar:
Set alan=Application.InputBox("Hücre seçin", Type:=8)
If Not IsEmpty(alan) Then 'boş değilse. If IsEmpty(alan)=False de olur ama biraz garip görünür
'işletilecek kodlar
Else
MsgBox "Boş bir hücre seçtiniz, lütfen dolu bir hücre seçin"
GoTo tekrar
End If
Nothing ve Not
Bir de Not'ın tamamen zorunlu olduğu bir durum var ki, o da Nothing ile
birlikte kullanım şeklidir. Genel Syntax şöyledir: If Not nesne Is
Nothing. Burada nesne Object tipindeki herşey olabilir. Range,
Worksheet, Outlook application v.s. Kelime kelime tercümesi "nesne hiçlik
değilse" şeklinde yapılabilecek olan bu cümlecik aslında "nesne birşeyse,
yani birşey atanmışsa veya henüz boşaltılmadıysa" anlamında daha Türkçe olarak
yorumlanabilir. Ancak VBA'da "Birşey" yani
Something diye bir ifade olmadığı için bunun zıddı olan "Not
Nothing" şeklinde yazılır.
Mesela Worksheet olayları bölümünde sıkça
kullanacağımız bir Intersect metodu var. Worksheet değiştiğinde eğer değişen
hücreler belli bir aralıkta mı diye kontrol ederiz, işte burda Not
ve Nothing kombinasyonu kullaırlır.
Ör: If Not Intersect(Target,
Range("C3:C4")) Is Nothing Then aslında şu demektir: If Intersect(Target,
Range("C3:C4")) Is Something Then, yani değişen hücre(Target) C3:C4 alanı
ile kesişim kümesindeyse, yani kesişim kümesi boşküme değilse, yani
"birşeyse". Worksheet olaylarında daha detaylı örnekler için
buraya tıklayınız.
Aşağıda da 3 değişkenden 2sine değer atanma durumu sözkonusu, idğer
açıklamalar commentlerde bulunuyor.
Sub ifnotnothing()
Dim hucre As Range
Dim ws As Worksheet
Dim wb As Workbook
Set hucre = ActiveCell
Set ws = ActiveSheet
If hucre Is Nothing Then 'if not nothing, hücrenin boş olup olmadığını sorgulamak değildir.
'hucre değişkenine bir değer atanıp atanmadığnı sorgulamaktır. boş olup olmadığı IsEmpty ile sorgulanır
Debug.Print "hucre değişkenine atama yapılmamış"
Else
Debug.Print "hucre değişkenine atama yapılmış"
End If
If Not ws Is Nothing Then 'if ws is something yani birşey ise
Debug.Print "ws değişkenine atama yapılmış"
Else
Debug.Print "ws değişkenine atama yapılmamış"
End If
'sadece sometinh olma durumunda çalışacak kod bloğu
If Not wb Is Nothing Then 'if wb is something yani birşey ise
Debug.Print "buraya girmeyecek"
End If
End Sub
Koşulu terse çevirme
Bu arada boolean tipli özellikleri tersine çevirmek için o özelliğin
mevcut durumunu öğrenmek amacıyla If yapısını
kullanmaya gerek yoktur; Not operatörü ile doğrudan
tersine çevirilebilir. Mesela sayfadaki gridler açıkken kapatan, kapalıyken
açan(bu işlemlere toggle işlemleri denir) bir buton yapıp quickaccessbara
ekleyebilrisiniz.
If'li kod şöyle olacaktır.
Sub grid_toggle()
If ActiveWindow.DisplayGridlines Then 'Dikkat ettiyeniz =True yazmadım, yazsam da bişey farketmeyecekti
ActiveWindow.DisplayGridlines=False
Else
ActiveWindow.DisplayGridlines=True
End If
End Sub
Onun yerine basitçe şöyle de yazabilirsiniz:
Sub grid_toggle()
ActiveWindow.DisplayGridlines = Not ActiveWindow.DisplayGridlines
End Sub
Tabiki, bunu yapabilmeniz için ilgli propertynin(özelliğin) hem
okunabilir hem yazılabilir(Returns and Sets) karakterde olması lazım.
İçiçe If ve Bağlaçlar(Birden fazla koşul sorgulama)
Birden fazla koşulu sorgulamak için içiçe birkaç IF bloğu yazılabilir.
Ör: Açılış Tarihi bu yıldan önce olan şubelerden sadece Bireysel Şube
sayısını öğreneceğimiz bir kod yazalım.
If Subeaçılıştarihi< Year(Now) Then
If tip="Bireysel" Then
'işletilecek kodlar
End If
End If
Bunu yapmanını bir diğer yolu da And bağlacını kullanmak olacaktır.
If Subeaçılıştarihi< Year(Now) And tip="Bireysel" Then
'işletilecek kodlar
End If
And kullanmak sanki daha mantıklı gibi ama ikinci koşuldan önce ara bir
işlem yapmak isterseniz içiçe IF kullanmanız gerekir.
If Subeaçılıştarihi<Year(Now) Then
'ara işlemler
If tip="Bireysel" Then
'işletilecek kodlar
End If
End If
Koşul yapısı Veya şeklinde olacaksa da Or
kullanılır. Ör: Şube tipi
bireysel veya Karma ise şunları yap gibi.
If tip="Bireysel" or tip="Karma" Then
'işletilecek kodlar
End If
Çoklu If bloğu vs Ayrı If blokları
Bazen öyle anlar gelir ki, konuşma dilinde söylediğimiz şey sanki çoklu if kullanmamız gerektiğini ima eder, ancak yapılması gereken işlem ayrı if
blokları kullanmak olabilir. Hemen bir örnek yapalım.
Diyelim ki, bir schedule prosedürünüz var ve Excel açılır açılmaz devreye
giriyor.(Scheduling işlemleri için
buraya bakınız). O an
saat 08:01den büyükse A makrosu, 08:11'den büyükse B makrosu v.s çalışsın
istiyorsunuz. Söylerken kulağa çoklu if kullanılacakmış gibi geliyor ancak
öyle yaptığımız durumda ilk koşul gerçekleşince kalanı işletilmez. Aslında
burda düşüncemizi dile getirme şeklimiz de hatalı olabilir. O yüzden
düşündüğümüz şeyi kelimelere daha doğru dökelim: A makrosu, o an saat 08:01'den
büyükse çalışsın, B makrosu saat 08:11'den büyükse çalışsın v.s. Küçük bir nüans var,
farkedebilidiniz mi? Evet, önce makronun adını sonra zamanı dile getirdik.
İlk versiyona göre kodumuzu şöyle hazırlardık ve hatalı bir işlem yapmış
olurduk:
If TimeValue(Now) > TimeValue("08:01:00") Then
Application.OnTime Now + TimeValue("00:02:00"), Procedure:="pyskontrol"
ElseIf TimeValue(Now) > TimeValue("08:11:00") Then
Application.OnTime Now + TimeValue("00:02:30"), Procedure:="nrkontrol"
ElseIf TimeValue(Now) > TimeValue("08:21:00") Then
Application.OnTime Now + TimeValue("00:03:00"), Procedure:="pdmkontrol"
ElseIf TimeValue(Now) > TimeValue("08:31:00") Then
Application.OnTime Now + TimeValue("00:04:00"), Procedure:="pargkontrol"
End If
Doğru kod aşağıdaki gibi olacaktır.
If TimeValue(Now) > TimeValue("08:01:00") Then
Application.OnTime Now + TimeValue("00:02:00"), Procedure:="pyskontrol"
End If
If TimeValue(Now) > TimeValue("08:11:00") Then
Application.OnTime Now + TimeValue("00:02:30"), Procedure:="nrkontrol"
End If
If TimeValue(Now) > TimeValue("08:21:00") Then
Application.OnTime Now + TimeValue("00:03:00"), Procedure:="pdmkontrol"
End If
If TimeValue(Now) > TimeValue("08:31:00") Then
Application.OnTime Now + TimeValue("00:04:00"), Procedure:="pargkontrol"
End If
IIf
Bir değişkene, bir koşul sonucuna bakarak bir değer atamak istiyorsanız
IIf yapısı çok kulanışlıdır ve kullanımı
oldukça basittir.
Aşağıdaki kodda, segment kodu 1 ise Bireysel değilse Tüzel şeklinde bir
atama yapılmaktadır.
Segment=IIf(segmentkodu=1,"Bireysel","Tüzel")