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
TEST SORULARI
Son Sorumuz şuymuş:Bir metindeki tüm noktaları yoketmek istiyorsunuz. Hangi fonksiyonu kullanırdınız?
Soru:
A şıkkı:
B şıkkı:
C şıkkı:
D şıkkı:
Doğru Cevap
Etiketler
İlişkili konuyu seç
133055
Label
* Sorulara verilen yanlış cevaplardaki esprili yorumlarım için hoşgörünüze sığınıyorum.
* Test ve Ödevlerdeki bazı detaylar burada anlatılmamış olabilir. Bunları kendiniz araştırıp bulmalısınız.
* Birden çok konuya ait içeriği olan ödevler var. Algoritmik açıdan bakıldığında o an en uygun konuya adreslenmiştir.
Dikkat! Bir soruya cevap verdikten sonra geri dönemezsiniz.
ÖDEVLER
3
0
Ödev No:12.
Mevcut workbookta herhangi bir tek sayfa kalana kadar tüm sayfaları silin.
Sayfalarla ilgili çeşitli bilgiler şöyle:
Sayfa sayısı elde etmek için şunu kullanın: Sheets.Count
Herhangi bir sayfaya erişmek için: Sheets(i). (i sayfanın indeksidir)
Sayfa silmek için: Delete metodu
NOT:Sayfa silerken sürekli size uyarı çıkmasın diye kodunuzun başına "Application.DisplayAlerts = False" kodunu ekleyin
Çözüme bakın(Başka türlü de çözülebilir tabi, bu benim çözümüm.)
Sub Odev_12()
Application.DisplayAlerts = False
Do While Sheets.Count > 1
Sheets(1).Delete
Loop
End Sub