30.09.2018 tarihinde Excel bölümüne Dış Verilerle çalışmak sayfası eklenmiştir

04.08.2018 tarihinde VBA bölümüne ObjelerDünyası sayfası eklenmiştir

25.07.2018 tarihinde VBA bölümüne Outlook programlama sayfası eklenmiştir

13.07.2018 tarihinde VBA bölümüne Formlar-Kontroller sayfası eklenmiştir

25.05.2018 Hosting şirketi dğeiştirmekten kaynaklı bir hata nedeniyle Excelent add-ini indirirken hata alınmaktaydı. Bu hata düzeltilmiştir. İki ayrı download alternatifi sunulmuştur. Kurumunuzun BT politikalarının veya şahsi PC’nizdeki güvenlik ayarlarının izin vermesi durumunda yöntemlerden biriyle kurulum yapabilmelisiniz. Bi sorun olursa bana iletebilirseniz sevinirim.

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

Do ve While Döngüleri

For döngülerini incelerken gördük ki, bu döngüler genellikle çevrelenen kod parçasının kaç kez çalıştırılacağının bilindiği durumlarda kullanılmaktaydı.

Üst limitin bilinmediği diğer durumlarda ise çoğunlukla Do ve While döngüleri kullanıır. While ifadesi ile genelde "Do While" kalıbı içinde geçer ve bu aslında While döngüsü değil bir Do döngüsüdür. While Wend döngüsü artık çok kullanılan bir döngü olmayıp bu bölümdeki  ve site genelindeki kodlarımızı Do döngüleriyle halletmeye çalışacağız. En son kısa bir While Wend döngü örneği de yapıp konuyu bitireceğiz.

Do döngüleri de For döngüleri gibi dizi ve dizimsilerde bol miktarda kullanılır, ayrınılı bilgi için For Döngüleri ve Diziler bölümlerine bakabilirsiniz.

Do Döngüleri

Do döngülerinin 2 ana, 4 alt tipi vardır.

  • Do While
    • Do While Şart şuysa.......Loop:Şart gerçekleşmezse çevrelenmiş kod hiç çalışmayabilir
    • Do ....... Loop While Şart şuysa:Şart gerçekleşse de gerçekleşmese de en az 1 kez çalışır
  • Do Until
    • Do Until Olay......Loop:Olay olana(şart gerçekleşene) kadar çalışır, döngüye girildiğinde olay zaten olmuşsa(şart gerçekleşmişse) çevrelenmiş kod hiç çalışmaz
    • Do ....... Loop Until Olay:Olay olana(şart gerçekleşene) kadar çalışır; Çevrelenmiş kod en az 1 kez çalışır

Gördüğünüz üzere, şart eğer Do satırındaysa, kod hiç çalışmayabiliyor, ama Loop satırındaysa en az 1 kez çalışır.

Hemen bir örnek yapalım. Kullanıcıdan karesi alınacak bir sayı girmesini isteyelim ve eğer kullanıcı geçerli bir sayı yerine başka birşey mesela bir harf girerse başa dönmesini sağlayalım. Bunu bir If ve GoTo ile de yapabilirdik ama bu sefer Do ile yapacağız.

Sub dowhile1()
'bu en az 1 kere çalışır, ve sayı girene kadar bize aynı soruyu sorar 
Do
  sayı = InputBox("Karesi alınacak bir sayı girin")
Loop While Not IsNumeric(sayı)
 
MsgBox sayı & " sayısının karesi şudur:" & sayı * sayı
 
End Sub

Sub dowhile2()
'Bu ise soruyu hiç sormaz. Çünkü önce şart kontrolünü yapar, 
'şart sağlanmadığı için döngüye girmeden çıkar 
'Şart sağlanmaz çünkü say değişkeni varianttır ve 
'Variantlara henüz değer atanmadıysa 0 değerini alır, yani IsNumeric sorugus True'dur
'başında da bir Not operatörü olduğu için şart sağlanmaz.

Do While Not IsNumeric(sayı)
  sayı = InputBox("Karesi alınacak bir sayı girin")
Loop
 
MsgBox sayı & " sayısının karesi şudur:" & sayı * sayı
 
End Sub

Aşağıda ise Do Until yapısına ait 2 örnek bulunuyor.

Sub dountil1()
'sayfa sayısı 5 olana kadar işlem yapar. 5ten çoksa siler azsa ekler.
Application.DisplayAlerts = False
If Sheets.Count < 5 Then
    Do Until Sheets.Count = 5
        Sheets.Add After:=Sheets(Sheets.Count)
    Loop
ElseIf Sheets.Count > 5 Then
    Do Until Sheets.Count = 5
        Sheets(Sheets.Count).Delete
    Loop
End If
End Sub

Sub dountil2()
'en az bir kere çalışır, taki sayfa sayısı 1 olana kadar
Do
  Sheets(2).Delete 'Her defasında hep 2.sayfa silinir, ta ki tek sayafana kalana kadar
Loop Until Sheets.Count = 1
End Sub

While mı Until mi?

Hangi durumda hangisini kullanmalıyız?

İkisini de her durumda kullanabilirsiniz. Tek farkı, birini diğerinin tersi mantıkla yazmak. Geliştiriciler neden böyle bir ayrıma girmişler emin değilim ama sanırım konuşma dilindeki kullanım terchilerimizi gözönüde bulundurmuş olabilirler. Mesela çocuğumuza "yemeğin bitene kadar masadan kalkmak yok" da diyebilriz, "yemeğin bitmediği sürece masadan ayrılmak yok" da, ikisi de aynı kapıya çıkar. VBA'de de durum pek farklı değil: En alt satıra inene kadar çalış da diyebiliriz, "aktif satır no<son satır no" olduğu sürece çalış da.

Döngüden Çıkış

For döngülerinde olduğu gibi Do Looplarından çıkış için de Exit ifadesini kullanırız. Mesela aşağıdaki döngüde, boş bir hücreye rastlanıldığında döngüden çıkılır.

i=1
Do While i < 1000
  If IsEmpty(Cells(i,1)) Then 
     Exit Do
  End If
  i = i + 1
Loop 

İçiçe Loop

Diyelim ki bir bölgenin şubelerini hacimlerine göre boy sırasına dizdiniz, buna göre her bölgenin en yüksek hacimli rakamını yazdırmak istiyorsunuz, yani bir nevi Excelde varolmayan(2016da MAXIFS geldi) bir MAXIF fonksiyonunu Sub prosedür olarak ele alacağız ve bunun tersi olan MINIF'i.

Tabiki bunları bir UDF ile yapmak daha şık olackatır ancak içiçe Loop örneği görmek adına bu örnek faydalı olacaktır.

Sub maxif()
'maxı yazacağın yere gel, ordayken çalıştır ve liste sıralı olsun
 
Set kriter = Application.InputBox("ana değişken kriterinin olduğu sütundan bir hücre seç", Type:=8)
Set rakam = Application.InputBox("maksimumun arandığı sütunu seç", Type:=8)
 
ks = ActiveCell.Column - kriter.Column
rs = ActiveCell.Column - rakam.Column
 
 
Do
  
    Maks = ActiveCell.Offset(0, -rs).Value
    Set ilkyer = ActiveCell
   
    Do While ActiveCell.Offset(0, -ks).Value = ActiveCell.Offset(1, -ks).Value
       
        If ActiveCell.Offset(1, -rs).Value > Maks Then Maks = ActiveCell.Offset(1, -rs)
        ActiveCell.Offset(1, 0).Select
               
    Loop
   
    Set sonyer = ActiveCell
    Range(ilkyer, sonyer).Value = Maks
    ActiveCell.Offset(1, 0).Select
       
Loop Until ActiveCell.Offset(0, -1).Value = ""
 
End Sub
 
Sub minif()
'mini yazacağın yere gel, ordayken çalışıtır ve liste sıralı olsun
 
Set kriter = Application.InputBox("ana değişken kriterinin olduğu sütundan bir hücre seç", Type:=8)
Set rakam = Application.InputBox("minimumun arandığı sütunu seç", Type:=8)
 
ks = ActiveCell.Column - kriter.Column
rs = ActiveCell.Column - rakam.Column
 
 
Do
  
    Mini = ActiveCell.Offset(0, -rs).Value
    Set ilkyer = ActiveCell
   
    Do While ActiveCell.Offset(0, -ks).Value = ActiveCell.Offset(1, -ks).Value
       
        If ActiveCell.Offset(1, -rs).Value <= Mini Then Mini = ActiveCell.Offset(1, -rs)
        ActiveCell.Offset(1, 0).Select
               
    Loop
   
    Set sonyer = ActiveCell
    Range(ilkyer, sonyer).Value = Mini
    ActiveCell.Offset(1, 0).Select
       
Loop Until ActiveCell.Offset(0, -1).Value = ""
 
End Sub	

While Wend döngüsü

Başta da söylediğimiz gibi bu döngü tipi artık pek kullanılmıyor, sadece eski yazılmış bir kod karşımıza geldiğinde bilelim diye hala var. Ama MSDN'nin bize söylediği gibi, Do Döngüsü daha fonksiyonel ve esnektir ve yeni kodlarda bu kullanılmaldır.

While döngülerinde sadece başta şart kontrolü yapılır, yani en az 1 kere çalışma olayı bunda seçime bağlı değildir. Bu da demektir ki döngü içindeki kodumuzun hiç çalışmaması mümküdür. Ayrıca Do ve For dönülerindeki gibi döngüden çıkış ifadesi(Exit) de yoktur.

Aşağıdaki örnekte 1'den 10 kadar olan sayıların toplamını alıyoruz.

Sub topla()
While sayı <= 10
   toplam = toplam + sayı
   sayı = sayı + 1
Wend

MsgBox toplam
End Sub
 

Çeşitli Örnekler

Bir hücre grubuna harfleri yazdırma

Sub harfyaz()
Dim i As Integer
i = 1
Do While i < 27
  Cells(i, 1) = Chr(i + 64) 'A harfinin Ascii kodu 65tir
  i = i + 1
Loop
End Sub

İlk sayfa hariç tüm sayfaları silme

Do
  Sheets(2).Delete 'Her defasında hep 2.sayfa silinir, ta ki tek sayafana kalana kadar
Loop Until Sheets.Count = 1

Database'den tek tek tarihler için data çekip başka sayfada altalta getirme

Diyelim ki, bir nedenle tarihsel datasını tek tek çekmeniz gereken bir sorgu var. Ör:1 Ocak için ayrı, 2 Ocak için ayrı,.... v.s Bunu bir SQL ortamında yapmanız ağır bir iş gelebilir. Neyse ki VBA ve döngüler sayesinde bu ağır iş bile kolaylaşabilir.

Sub dowhileornek()

Dim t As Date
t = "01.01.2016"

Do
'SQL stringini oluşturuyorum
s1 = "Select * from PARG.ARG_TNETICE_MUSTERI_GER" & Chr(13)
s2 = "where BAGLI_URUN_ID in (165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184)"
s3 = "and TARIH=" & t & " and KPI_ID=1001 and RAPOR_TURU=2"
s4 = "and musteri_id in (Select ESLESEN_TARAF_ID from PDWH.DWH_TSAKLAMA where YONLENDIREN_SUBE <> 1234 and TARIH=t)" & Chr(13)


With ActiveWorkbook.Connections("DWH").ODBCConnection
.BackgroundQuery = True
.CommandText = Join$(Array(s1 & s2 & s3 & s4))
'Diğer kodlar
End With

ActiveWorkbook.Connections("Query from PDWH_USR").Refresh
t = t + 1 'Tarihi 1 artırıyorum

ActiveCell.CurrentRegion.Select
Selection.Copy
Sheets(2).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste 'ilk çalışan sorgu sonucunu 2.sayfaya ekleyip bir alt satıra iniyorum

Loop Until t = "15.02.2016" '15 şubata kadar yani 45 kez sorgu çalışacak
'SQL ortamınıda bunu yapmak çok yorucu olabilirdi

End Sub

Belirli adette sayfası olan dosya yaratma

Diyelim ki, kodumuzun bir yerinde 5 sayfalı bir workbook yaratmamız gerekiyor. Normalde Excelin default ayarı yeni workbook açılıdığında 3 adet safyası olması yönündedir ama biz bu default ayarı değiştirmiş olabiliriz, mesela 1 veya 7 yapmış olabiliriz. O  yüzden ilk olarak bir If bloğu ile kontrol ederiz ve eğer 5 ten büyükse fazlalıkları sildirip, küçükse 5e tamamlayan bir kod yazarız. Sayfa sayımız zaten 5se kod hiçbirşey yapmaz.

Sub sayfaekleveyasil()
Application.DisplayAlerts = False 'sayfa silerken uyarmasın
If Sheets.Count < 5 Then
	Do Until Sheets.Count = 5
		Sheets.Add After:=Sheets(Sheets.Count)
	Loop
ElseIf Sheets.Count > 5 Then
	Do Until Sheets.Count = 5
		Sheets(Sheets.Count).Delete
	Loop
End If
End Sub

YORUMLAR