28.12.2017 tarihinde,VBA konularına Dosya Okuma/Yazma sayfası eklenmiştir.

20.12.2017 tarihinde,sitem mobil uyumlu hale gelmiştir.

02.12.2017 tarihinde,Excel Fonksiyon konularına "Dizi Formülleri ve SUMPRODUCT" sayfası eklenmiştir.

31.10.2017 tarihinde,VBA Dictionary sayfasına Dictionary, Collection ve Collection dizisinden oluşan ilginç bir örnek eklenmiştir.

26.10.2017 tarihinde,Excel Fonksiyon konularına "İsatistiki ve Matematiksel fonksiyonlar" sayfası eklenmiştir.

VBAMakro Koşul ifadeleri ve Döngüler 1

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.

Temeller

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.

İleri Seviye işlemler

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:

'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

'Belli bir anda aktif hücrenin değerinin sayısal olmaması durumunda proramı durduruyoruz
If IsNumeric(ActiveCell.Value) Then Exit Sub

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)

 

YORUMLAR