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 3

For...Next... Döngüleri

VBA dünyasının en temel döngü tipi For döngüleridir. Bir önceki koşullu yapılar konusunda söylediğimiz gibi döngüler de programlamanın olmazsa olmazlarıdır. Onlar olmasaydı belki 3 satırlık kodu onlarca hatta yüzlerce satır şeklinde yazmamız gerekirdi.

For döngülerinin 2 tipi vardır:

  • Basit For Next döngüsü
  • For Each döngüleri

İlk olarak basit For döngüsü ile başlayalım

For...Next...

Genel kullanım şekli şöyledir:

For i=başlangıçsayısı to bitişsayısı
    'i'ye bağlı veya i'den bağımsız olarak şunu yap
Next i

Gördüğünüz gibi, sayaç olarak kullandığımız i değişkenini döngü içinde de parametrik olarak kullanabiliriz veya kullanmayabiliriz. İkisine de örnek verelim. Önce i'yi döngü içinde parametrik olarak kullanacağımız örnek olsun. Bu örnekte, A1'den A10'a kadar olan hücrelere sırayla i'nin kendisini yazmış oluruz.

For i=1 to 10
    Cells(i,1)=i
Next i

Şimdi de parametrik olmayan örneğe bakalım, bunda ise Excele 10 kez bip sesi çıkarttırıyoruz.

For i=1 to 10
    Beep
Next i

i sayacı genelde 0 veya pozitif(ki bu da genelde 1dir) bir sayı olmakla birlikte negatif bir sayı da olabilir, ama bunun pratikte pek kullanıldığını görmedim.

Sayacımız normalde 1er 1er artar, ancak istersek Step ifadesi ise 2'şer, 3'er de arttırabiliriz. Hatta sayacı geriye doğru da saydırabiliriz, ki bunun için Step ifadesinden sonra negatif bir sayı gelir.

For i = 10 To 1 Step -2
   Cells(i / 2, 1) = i
Next i

Tüm sayfalarda gezindiğimiz bir kod:

For i = 1 To Sheets.Count
   Worksheets(i).Select
   'diğer kodlar
Next i

Şimdi bir başka örnekte de ilk hücreden en alt hücreye doğru ilerleyelim.

For i = 2 To Cells(1, 1).End(xlDown).Row
   Cells(i,1).Select
   'Diğer kodlar buraya
Next i

İçiçe For Döngüleri

For döngülerini de tıpkı koşullu yapılarda olduğu gibi iç içe geçmiş şekilde kullanabiliriz. Aşağıdaki örnekte boş olan hücreleri sarıya boyayalım ve sayısını bulalım:

Öncelikle şunu belirtmekte fayda var. Tek olsun içiçe olsun tüm döngülerde For satırını yazdıktan sonra hemen onunu bitişi olan Next satırını da yazın, aradaki kodları da girintili yazın. İçiçe For Next olacaksa bu ikinci For'u da yine girintli yazın. Şimdi kodumuza bakalım.

Sub bosluksay()
Dim adet As Integer
For i = 1 To Range("A1").End(xlToRight).Column
    For k = 1 To Range("A1").End(xlDown).Row
        If IsEmpty(Cells(k, i)) Then
            Cells(k, i).Interior.Color = vbYellow
            adet = adet + 1
        End If
    Next k
Next i

MsgBox "toplamda " & adet & " adet boş hücre var"
End Sub	

ve sonuç:

For Each...Next...

For Each yapısı bir obje grubu ve bir dizi(veya dizimsi) içindeki elemanlar içinde gezinmek için kullanılır.

For Each nesne in nesnegrubu
  'nesneyle ilgili bir işlem 
Next nesne 

For Each elaman in dizi
  'dizi elemanıyla ilgili işlem
Next eleman 

Diziler hakkında ön bilgi almak için buraya tıklayın.

Şimdi yukardaki boşluk saydırma örneğini For Each ile nasıl yapacağımıza bir bakalım.

Sub bosluksay2()
Dim adet As Integer
Dim hucre As Range, alan As Range

Set alan = Range("A1").CurrentRegion

For Each hucre In alan
    If IsEmpty(hucre) Then
        hucre.Interior.Color = vbYellow
        adet = adet + 1
    End If
Next hucre

MsgBox "toplamda " & adet & " adet boş hücre var"
End Sub

Bence For Each ile sanki daha kolay gibi görünüyor. O yüzden böyle bir görevde ben ForEach'i kullanırdım. Ancak eğer döngü içinde i veya k parametrelerinden birini kullanarak da bir işlem yapmam gerekseydi, o zaman basit For döngüsü kullanırdım, gerçi yine For Each kullandığımızda hücrenin row ve column özellikleri ile i ve k'yı dolaylı olarak elde edebilirim ama basit For'da bunlar zaten elimde olacaklardı. Kısacası duruma göre hangisini kullanacağınıza siz karar vereceksiniz. Basit For'un esnek başlangıç ve bitiş değerleri ile hareket yönündeki esnekliği avantaj sayılabilirlken, For Each için daha hızlı olmasını avantaj olarak vurgulayabiliriz.

For Each yapısını, Range'teki hücrelere ek olarak, Workbooktaki sayfalar ve tüm workbooklar arasında dolaşma şeklinde de bol miktarda kullanıyoruz.

'workbooklarda dolaşma
Dim wb As Workbook
For Each wb In Workbooks
    MsgBox wb.FullName
Next wb
 
'worksheetlerde dolaşma
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Sheets
    MsgBox ws.Name
Next ws

Yine dizi veya dizimsilerin elemanları içinde gezinirken de her iki yapı kullanılabilir. Basit For'da 1 to elemansayısı yapısı kullanılırken ForEach'te each eleman in dizi şeklinde kullanırız. Şimdi kısa bir örnek de dizilerle ilgili yapalım, daha detaylı örnekleri Diziler bölümüne bırakalım.

Mesela sabit bir bölge kodu listeniz olsun ve bunların her birini bir diziye atayalım, sonra da bu bölge kodunu kullanarak bir işlem yapalım.

Sub forarray()
Dim blg() As Variant

blg = Array(5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010)
For Each b In blg
   Workbooks.Open ("C:\bölge raporları\" & b & "-netice raporu.xlsx")
   'diğer işlemler
Next b
End Sub

Akılda bulundurulması gereken önemli bir husus, ForeEach kullanıldığında read-only bir özellik gösterir. Yani bu yöntemle dizi elemanlarını değiştiremezsiniz. Elamanları değiştirmek istiyorsanız basit For döngüsü kullanmanız lazım. Exlcemacromastery sitesinden aldığım bu iki örnekte fark çok açıkça anlatılmış.

Sub UseForEach()

    ' Diziyi yaratıp 3 değer ekliyoruz
    Dim arr() As Variant
    arr = Array("A", "B", "C")

    Dim s As Variant
    For Each s In arr
        ' s'nin atadığı değeri değiştirmeye çalışıyoruz
        s = "Z"
    Next

    ' Ama değişmemiş olduğuğnu  görüyoruz
    For Each s In arr
        Debug.Print s
    Next

End Sub	

Basit for ile değişimi görelim

Sub UsingForWithArray()

    Dim arr() As Variant
    arr = Array("A", "B", "C")

    Dim i As Long
    For i = LBound(arr) To UBound(arr)
        arr(i) = "Z"
    Next

    For i = LBound(arr) To UBound(arr)
        Debug.Print arr(i)
    Next

End Sub

Son bir örnek daha yapalım. Bu sefer, toplu bir goalseek(hedef ara) işlemi yapalım.

Sub toplugoalseek()
Dim h As Range
For Each h In Range("E8:E2294")
   h.Select
   h.goalseek Goal:=h.Offset(0, 4).Value2, ChangingCell:=h.Offset(0, 2)
Next h

End Sub	

Döngüden Çıkış

Yukarıdaki kod örneklerinden de gördüğünüz üzere, For döngüleri genellikle kaç kez çalıştırılacağını bildiğiniz durumlarda kullanılır. Ör: For i=1 to 10 dersek, 10 kez çalışacağını biliriz veya For Each item in dizi dersek dizideki tüm elemanlar için çalışacağını biliriz. Tabiki üst limitin değişken olduğu bazı durumlarda, o limite başka VBA kodları ile de ulaşabilir ve yine For döngülerini kullanabiliriz, mesela en alt satırın kaç olduğunu bilmiyoruzdur ama Range("A1").End(xlDown).Row ile bunu bilip döngüyü buraya kadar götürebiliriz, gerçi bu tür durumlarda diğer döngü türlerini kullanmak daha kullanışlıdır.

Ancak bazen, döngüyü erken terketmeniz gerekebilir. Yani döngüye girdiniz diye ille sonuna kadar gitmeniz gerekmiyor. Bunun için GoTo ifadesi kullanılabileceği gibi, Exit For yapısı da kullanılabilir. GoTo kullanımında doğrudan belli bir etikete yönledirilirken Exit For ile döngünün hemen arkasından devam edilir.

Mesela yukardaki örneğimizi, boşluğa ilk rastlanılan hücrenin adresini verecek şekilide değiştrelim.

Sub bosluksay3()
Dim a As String
Dim hucre As Range, alan As Range

Set alan = Range("A1").CurrentRegion

For Each hucre In alan
    If IsEmpty(hucre) Then
        a = hucre.Address
        Exit For
    End If
Next hucre

If a <> vbNullString Then
    MsgBox "ilk olarak " & a & " adresinde boşluğa rastlanmıştır"
Else
    MsgBox "herhangi bir boş hücre bulunmamaktadır"
End If
End Sub

 

YORUMLAR