If'li Koşul Yapıları
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.
Genel yapı şu şekildedir: If....Then .... Tabi bu yapı farklı görünümler kazanabilmektedir. Hepsine tek tek bakalım, sonra da örnekleri verelim.
Kullanım şekli
Kullanım şekli | Syntax |
---|---|
Tek satırda yazım(kısa bir işlem yaptıracaksak) | If isim="Volkan" Then Goto devam |
Tekli if bloğu. Birden fazla işlem yaptıracaksak If-End If bloğu arasında yazılır. |
If isim="Volkan" Then MsgBox "merhaba volkan" Goto devam End If |
Çoklu if bloğu: Eğer şöyleyse şunu yap yok değilse bunu yap, diğer durumlarda ise şunu yap. |
If isim="Volkan" Then MsgBox "Merhaba volkan" ElseIf isim="Serkan" Then MsgBox "Merhaba serkan" Else MsgBox "Merhaba değerli insan" End If |
İç içe If: Eğer şöyleyse, ve yine eğer böyleyse şunları yap |
If isim="Volkan" Then If şehir="İstanbul Then MsgBox "merhaba istanbullu volkan" Else MsgBox "merhaba anadolulu volkan" End If Else MsgBox "merhaba değerli insan" End If |
IIF(tek satırda pratik değer atama) | YasDurum=IIF(yas<18;"Çocuk";Yetişkin") |
Şimdi hemen küçük bir örnek yapalım:
Sub basitif()
Dim segment As integer
Dim segmentAd as String
segment=Application.Inputbox("Segment kodunu girin",Type:=1)
If segment= 1 Then
segmentAd = "Bireysel"
Else
segmentAd = "Tüzel"
End If
MsgBox "Müşteri " & segmentAd & " segmenttedir"
End Sub
Operatörler
Temel operatörler şunlardır: eşitlik(=), eşit olmama(<>), büyük ve büyükeşit(>,>=) ile küçük ve küçükeşit(<,<=)
Bunlardan başka ne tür operatörler olduğunu aşağıda göreceğiz.
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
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")