Anasayfa | Akademik Forum | Sizden Gelenler | Sipariş
Menü Açıklamaları
Sorular - Cevaplar
Makaleler
Makrolar
Yerleşik İşlevler
Animasyonlar
Yumurtalar
Fonksiyonlar
MTK Programlar
ExcelCE
Dosya İndir
Neler Yaptık?
İletişim
Makaleler
Programlamanın Bel Kemiği: DÖNGÜLER - 2
M. Temel Korkmaz - 01.11.2001
Geçen ay döngüler konusuna giriş yapmış ve ilk olarak For-Next döngüsünden bahsetmiş ve konuyla ilgili örnekler vererek, sizlerden de değişik örnekler çözmenizi istemiştim. Geçen ayki konunun anlaşıldığını düşünerek (çünkü bu konuda bir tepki olmadı) bu ay kaldığımız yerden döngülere devam ediyoruz.

Bu defa For-Next döngüsünün ikiz kardeşi olan For-Each-Next döngüsü ile bu ayki yazımıza başlayacağız.

For-Each-Next Döngüsü

Kullanım Şekli:

For Each Eleman In Grup
    ……………
    …………… (Komutlar)
    ……………
Next Eleman

Yazıya girişimizde For-Each-Next döngüsü için For-Next döngüsünün “ikiz kardeşi” ifadesini kullanmıştık. Gerçekten de böyledir. Yani mantık ve çalışma tarzı olarak aynı çalışır. Bu nedenle aynı olan kısımları burada anlatmayacağız. Sadece farklılıklarını anlatıp örnekler vereceğiz.

“Eleman” olarak tanımladığımız birim Grup olarak tanımlayacağımız kümenin bir elemanıdır. Şöyle düşünün. Manavdasınız ve önünüzde meyvelerin bulunduğu sepetler bulunuyor. Elma sepeti, ayva sepeti, portakal sepeti, mandalina sepeti gibi. (Şimdi bu yazımızı okuyan bir manav arkadaşımız içinden hafifçe gülüyor ve “Meyvelere bak aynı mevsimde mi oluyormuş bunlar?” diyerek cahillimizi ortaya koyuyordur. Neyse bu arkadaşımıza rağmen Teşbih’te bu tür zararsız hatalar mazur görülebilir diyerek konumuza dönelim) Evet önümüzde ki bu sepetlerin her biri bizim Grup olarak tanımladığımız kümedir. Elma sepetin içersindeki her bir Elma’da yukarıda tanımladığımız Eleman’dır. Ben pek bilmiyorum ama biraz İngilizce bilenlerimiz In ifadesinin “içinde, -de, -da” , Each ifadesin de “her biri, beher” manasını taşıdığını bilir.

Eğer siz, “Portakal” ı “Elma Sepeti”ne koyup satmak isterseniz ve müşterinizde sinirli ve asla hata kabul etmeyen bir müşteriyse size çıkışacaktır. “Manav Efendi!! ben sizden “Elma” istedim, siz ise bana “Portakal” da vermeye kalkışıyorsunuz.” Diye bir uyarı mesajı sizin ile müşteri arasında belirecektir.

Neden  bu kadar teferruat yaptık?

Çünkü, tanımlamalarınızı doğru yapmazsanız, Excel ile sizin aranızda bir hata uyarısı oluşacaktır. Siz de bu hatanın nereden geldiğini bir türlü anlamayacaksınız. Şimdi örnekleri bırakalım ve örneklerden edindiğimiz bilgi ile konumuza dönelim.

Excel’de de manav sepetleri gibi bir çok nesne grupları bulunmaktadır.Wokseheets, Range, Workbooks gibi. Eğer sizin değişkeniniz bu nesnelerden bir tanesi ile yanlış eşleşme yaparsa hata ile karşılaşırsınız.

Sayfa1 bir Worksheet nesnesidir.

A1 hücresi bir Range nesnesidir.

Yukarıda anlattığımız örnek ve teorileri basit bir örnek içerisinde açıklayalım.

Örnek: Amacımız A1 hücresinden A5 hücresine kadar “ExcelTim” yazdırmak olsun. Bunun için aşağıdaki kodu yazın ve çalıştırın.

Sub Doldur()
    For Each hucre In Range("A1:A5")
        hucre.Value = "ExcelTim"
    Next hucre
End Sub

Kodu çalıştırdığımızda Şekil-1’deki gibi bir görüntü elde edeceksiniz.


Şekil-1: Basit bir ForEach Next döngüsü

Koda dikkat edelim. “hucre” değişkeni (elemanı) Range(“A1:A5”) grubuna ait bir elemandır.

Döngüde hucre=A1
Döngüde hucre=A2
Döngüde hucre=A3
Döngüde hucre=A4
Döngüde hucre=A5

Yani daha açık ifade etmek istiyorum ki kafalarda en ufak bir soruna yer kalmasın. Şimdi ilk döngü yani birinci döngüde ne olacak?

Excel, hucre değişkenini görecek ve diyecek ki, bu hücre değişkeni Range sınıfının bir elemanıdır. Range sınıfı ise bu örnekte A1, A2, A3, A4 ve A5 hücrelerinden oluşuyor. O halde ilk döngüde “hucre” gördüğümüz yere Range(“A1”) ifadesini koyacağız.

For Each hucre In Range("A1:A5")
     Range(“A1”).Value = "ExcelTim"

İkinci döngüde ise hucre görünen yere Range(“A1”) ifadesi koyulacaktır. O zaman da kod aşağıdaki gibi olacaktır.

For Each hucre In Range("A1:A5")
    
Range(“A2”).Value = "ExcelTim"

Bu işlem hucre değeri Range(“A5”) oluncaya kadar devam edecektir. Sanıyorum anlaşılmayan bir yer kalmadı. Ama ben hemen sizi uyarmalıyım. Eğer “hucre” bir değişken ise ve biz de bilgisayarımızın “Bellek yetersiz” hatasını vermesini istemiyorsak bu “hucre” değişkenini tanımlamalıyız. Bunun içinde küçük bir açıklama yapalım.

Aynı kodu, For-Each-Next ile değil de For-Next döngüsü ile yapsaydık. Aşağıdaki  gibi bir kod yazacak ve aynı sonucu alacaktık.

Sub Doldur1()
    Dim hucre As Integer
    For hucre = 1 To 5
        Cells(hucre, 1).Value = "ExcelTim"
    Next hucre
End Sub

Dikkat ederseniz “hucre” değişkenini Dim ile tanımlarken “Integer” ifadesini kullandık. Çünkü “hucre” değişkeni 1, 2, 3, 4 ve 5 değerlerini alıyordu. O halde bunun için en uygun değişken tanımlaması “Integer”dir. Şimdi aynısını For-Each-Next’te uygulayalım. (Şekil-2)

Sub Doldur()
    Dim hucre As Integer
    For Each hucre In Range("A1:A5")
        hucre.Value = "ExcelTim"
    Next hucre
End Sub


Şekil-2: Yanlış değişken tanımlamalarında alınacak hata mesajlarından bir tanesi

Siz ne kadar vermek isteseniz de, Müşteriniz olaya hakim ve Portakal’ı asla Elma olarak sizden almak istemiyor ve sizi uyarıyor, bir daha böyle hatalar yapmayın diyor. Şekil-3’e dikkat ederseniz, hata mesajını “hucre” elemanının olduğu erde verecektir.


Şekil-3:  Yanlış tanımlamada hata mesajı değişkeni gösterecektir

Şimdi kodu aşağıdaki gibi değiştirelim ve tekrar çalıştıralım.

Sub Doldur()
    Dim hucre As Range
    For Each hucre In Range("A1:A5")
        hucre.Value = "ExcelTim"
    Next hucre
End Sub

“hucre” değişkenini Range olarak tanımladığımızda kodun doğru olarak çalıştığını göreceksiniz.

Bazı okurlarımızın aklına hemen, “Ama biz For Next döngüsü ile bunun arasında bir fark görmedik. Hem For-Next döngüsüne de alıştık. Bunu kullanmaya ne gerek var?” gibi sorular gelebilir. Hemen cevaplayayım ki, YANLIŞ (FALSE) düşünüyorsunuz. Bunun içinde çok basit bir örnek vereyim.

Örnek: Amacımız A1 hücresinden E5 hücresine kadar olan bölüme “ExcelTim” yazdırmak olsun. Hadi bakalım bunu önce For-Next döngüsü ile siz yapın, sonra da ben size bunu For-Each-Next döngüsü ile yapayım. Hadi benim verdiğim örneğe bakmadan önce siz yapın.

Uğraştınız ve yaptınız öyle mi? Öyle ise “Bravo” size. Yoksa yapamadınız mı? İç içe For-next döngüsü kullanmayı denemediyseniz biraz zor yaparsınız yada uzun bir kod yazarsınız. Neyse ben sizin yerinize çözümlerden bir tanesini sunayım. Yukarıdaki For-Next döngüsüne uyfun olarak eklemeler yaptım.

Sub Doldur1()
    Dim hucre As Integer
    Dim sutun As Integer
    For sutun = 1 To 5
        For hucre = 1 To 5
            Cells(hucre, sutun).Value = "ExcelTim"
        Next hucre
    Next sutun
End Sub

Şimdi gelelim For-Each-Next ile sorunu çözmeye. Yapacağımız tek bir işlem var. Yukarıdaki For-Each-Next örneğindeki A5’de A harfini E olarak değiştirmek.

Sub Doldur()
    Dim hucre As Range
    For Each hucre In Range("A1:E5")
        hucre.Value = "ExcelTim"
    Next hucre
End Sub

Her iki çözümde de Şekil-4’deki sonucu elde edeceksiniz.


Şekil-4:  Her iki döngüde aynı işi yapıyorsa en kısa kodlamayı kullanmak daha akıllıcadır.

Artık sıra For-Each-Next döngüsü ile verilecek örneklere geldi. Ne kadar çok örnek yaparsak o kadar çok olaya hakim oluruz.

Örnek 1: A1 ile D10 hücrelerine sıra ile rakamları yazdırmak.

Sub DonguForEachNext()
    Dim i As Range
    Dim k As Integer
    k = 1
    For Each i In Range("A1:D10")
        i.Value = k
        k = k + 1
    Next i
End Sub

Kodu çalıştırdığımızda Şekil-5’deki gibi bir görüntü elde edeceğiz.


Şekil-5:  For-Each-Next döngüsünde yazdırma sırası

Şekil-5’e dikkatle bakan okuyucularımız şunu hemen fark edeceklerdir. 1, 2, 3, 4 gibi rakamları alt alta değil de yan yana yazılmıştır. Bunun nedeni çok basit. Bu döngü sisteminde Veriler çoklu satır ve sütunlarda yazdırılırken A1, A2, A3 gibi değil, A1,B1 ve C1 olarak yazdırılır.

Örnek 2: Belirlenen hücreler için rasgele sayı üretip bu hücreleri içerisindeki sayılara göre biçimlendirmek.

Sub DonguForEachNext()
    Dim k As Range
    Range("A1:D10").Formula = "=rand()*100"
    For Each k In Range("A1:D10")
        If k > 0 And k < 10 Then
            k.Interior.ColorIndex = 45
            k.Font.ColorIndex = 1
        ElseIf k > 10 And k < 50 Then
            k.Interior.ColorIndex = 6
            k.Font.ColorIndex = 3
        ElseIf k > 50 And k < 100 Then
            k.Interior.ColorIndex = 37
            k.Font.ColorIndex = 9
       
End If
    Next k
End Sub

Kodu çalıştırdığınızda Şekil-6’daki gibi bir görüntü ile karşılaşacaksınız.


Şekil-6:  Her hücrede S_Sayı_Üret formülü bulunmaktadır.

Kod çalışmadan evvel, veri yazdırılan hücrelerin sayı formatını virgülden sonraki ondalık kısmını kaldırdım. Siz kaldırmadıysanız verileriniz mutlaka küsuratlı çıkacaktır. Biçimlendirme Araç çubuğundaki Ondalık Azalt düğmesine iki defa tıklamanız yeterli olacaktır.

Örnek 3: Belirlediğimiz aralıktaki yazı fontunu değiştirmek. Bu örneği çalıştırmadan önce Şekil-7’deki gibi bir tablo oluşturalım.


Şekil-7:  Excel’de varsayılan Font Arial’dir

Aşağıdaki kodu yazıp çalıştırdığınızda, Şekil-8’deki gibi bir görüntü elde edeceksiniz.

Sub ForNextEach()
    Dim k As Range
    For Each k In Range("A1:B5")
        If k.Font.Name Like "Arial*" Then
            k.Font.Name = "Arial Black"
        End If
    Next k
End Sub


Şekil-8:
Belirlediğimiz aralıktaki fontları değiştirdik.

Örnek 4: Eklentileri yüklü olup olmadığını araştırmak. Şimdi bazı okuyucularımız kalkıp da “Eklenti de neymiş?” derse gerçekten bozulurum. Ama yine de Eklentinin ne olduğundan kısaca bahsedelim ki yazdığımız kod net olarak anlaşılsın. Daha sonraki derslerimizde bu konudan bahsedeceğiz. Fakat siz illa da hemen öğrenmek istiyorsanız ve Eklenti hakkında bütün her şeyi bilmek istiyorsanız MAKROLAR kitabımızın 16. Bölümünde  40 sayfalık örnekli açıklamalar bulabilirsiniz.

Excel programını güçlendirmek ve programa yenilikler katmak, ya da size göre eksik olarak düşündüğünüz herhangi bir özellik varsa, hazırladığınız veya başkaları tarafından hazırlanmış olan bu programa kısaca “Eklenti” diyebilirsiniz. Bu programı Excel’in içerisinde kullandığınızda buna “Excel Eklentisi” dersiniz. Excel’in Kurulumuyla birlikte direk gelmeyen ya da gelse bile hemen aktif olmayan bu dosyalar .XLA uzantılı dosyalardır. Bu dosyalar önce .XLS dosyaları olarak hazırlanırlar, Daha sonra kaydedilirken “Farklı Kaydet” penceresinden .XLA seçeneği seçilerek kaydedilir ve dosyanız artık .XLA uzantılı bir eklenti haline dönüşmüş olur.

Excel’in kurulumu ile bilgisayarınıza bir çok eklenti programı da kayıtlı haldedir. Excel’in firma tarafından hazırlanmış veya satın alınarak programa katılmış eklenti programları “C:\Program Files\Microsoft Office\Office\Library” klasörünün altındadır. (Şekil-9)


Şekil-9:
  Library klasöründe Office ile birlikte gelen EKLENTİ’ler bulunur.

“Araçlar” menüsünden “Eklentiler” komutunu tıkladığınızda ekrana “Eklentiler” penceresi gelecektir.


Şekil-10: Excel 2002’de Library Eklentiler Penceresi

Bu pencerede bir çok seçenek göreceksiniz. Bu seçenekleri aslında biraz önce gördünüz. Şöyle bir benzetme yaparsak yerinde olur inancındayız, “Bu pencerede gördüğünüz seçenekler bir Vücudun dış görüntüsü, Library klasöründe gördüğünüz .XLA uzantılı dosyalar ise vücudun iskelet ve iç organlarıdır.”

Sürekli bilgisayarınızda bulunmasını istediğiniz bir eklentiyi çalıştırmak için seçeneklerin sol taraflarında bulunan Onay kutularını onaylayın ve “Tamam”  düğmesini tıklayın.

Bu açıklamayı daha fazla uzatmıyorum çünkü daha öncede belirttiğim gibi bu konu hakkında detaylı bilgiyi daha sonraki derslerimizde vereceğim.

Şimdi bilgisayarımızda hangi eklentiler var ve bunlardan hangileri bilgisayarımızda yüklü bunu gösteren küçük bir For-Each-Next örneği yapalım. Bunun için önce aşağıdaki kodu yazalım.

Sub ForNextEach()
    Dim satir As Integer
    Dim k As AddIn
    satir = 1
    For Each k In Application.AddIns
        Cells(satir, 1) = k.Name
        Cells(satir, 2) = k.Installed
        satir = satir + 1
    Next k
End Sub

Kodu çalıştırdığımızda ekran Şekil-11’deki gibi olacaktır.


Şekil-11: Sadece Koşullu Toplam sihirbazı (SUMIF.XLA) aktif

Değişik ve kullanabileceğiniz örneklerle konumuza devam edelim.

Örnek 5: Excel Çalışma kitabında bulunan, Çalışma sayfalarını gizlemek ve göstermek.

Sayfaları gizlemek için kullanılacak kod. Tabi unutmayın en son sayfa görünür olacaktır. Çünkü bütün sayfaları gizleyemezsiniz.

Sub SayfalariGizle()
    On Error Resume Next
    Dim sayfa As Worksheet
    For Each sayfa In Worksheets
        sayfa.Visible = xlVeryHidden
    Next
End Sub

Sanırım kodun ilk satırında bulunan On Error Resume Next deyimini neden kullandığımızı anladınız. Anlamayan arkadaşlarımız bu satırı kaldırarak kodu bir kez daha çalıştırsınlar. Kodu çalıştırdıklarında Şekil-12’deki mesaj ile karşılaşacaklardır. Çünkü bütün sayfalar gizlendikten sonra sıra Çalışma kitabında kalan en son sayfaya gelmiştir. Bunu da kaldırmak istediğinizde Excel’in kurallarına aykırı davranmış olursunuz. Kural: Bir çalışma kitabında en az bir sayfa bulunmalı ve görünür olmalıdır.

İşte bu hata denetimi kodunu yazarak, hatayı gözardı etmiş oluyoruz ve kodumuzun çalışmasına devam ediyoruz. Hata Konuları hakkında detaylı bilgiyi ilerideki sayılarda bulabileceksiniz. Hemen öğrenmek istediğinizde nerede bulabileceğinizi biliyorsunuz.


Şekil-12:  Son sayfayıda gizlemek yada kaldırmak istediğiniz bu mesajı alırsınız.

Sıra gizlenmiş sayfaları göstermeye geldi. Bunun için de aşağıdaki kodu yazıp çalıştırmanız yeterli olacaktır.

Sub GizliSayfalariGoster()
    Dim sayfa As Worksheet
    For Each sayfa In Worksheets
        sayfa.Visible = True
    Next
End Sub

Örnek 6: Excel’de Bul-Değiştir olayını hemen hemen herkes bilir. Ama bunu kod haline getirerek yaptınız mı hiç? Hem de bu işlemi Çalışma Kitabınızın bütün sayfalarında ve her sayfanın da bütün hücrelerinde gerçekleştirebilirsiniz. Eğer For Each Next döngüsünü bilmeseydiniz bunu nasıl yapardınız acaba?

Bu işlemi gerçekleştirmek için, önce değiştirmek istediğiniz Kelimeyi, sonra hangi kelime ile değiştirmek istediğinizi aşağıdaki makroda gerekli yerlere yazın. Ben “ExcelTim” kelimesini “M. Temel” ile değiştirmek için aşağıdaki kodu yazdım.

Sub BulDegistir()
    Dim sayfa As Worksheet
    For Each sayfa In Worksheets
        sayfa.Cells.Replace "ExcelTim", "M. Temel"
    Next
End Sub

Örnek 7: Yabancı sitelerden sizler için aldığım örneklerden bir tanesi. Yapmanız gereken birkaç hücreye rakam girmek ve bunların bulunduğu alanı seçmek ve aşağıdaki kodu çalıştırmak.

Sub MoveMinus()
    On Error Resume Next
    Dim cel As Range
    Dim myVar As Range

   
Set myVar = Selection

   
For Each cel In myVar
        If Right((Trim(cel)), 1) = "-" Then
            cel.Value = cel.Value * 1
        End If
    Next

   
With myVar
        .NumberFormat = "#,##0.00_);[Red](#,##0.00)"
        .Columns.AutoFit
    End With
End Sub

Örnek 8: Başka bir örnek. Bazı hücrelere veriler girin. Kodu çalıştırın ve boş olan hücrelerin kilitlendiğini görün

Sub Set_Protection()
    On Error GoTo errorHandler
    Dim myDoc As Worksheet
    Dim cel As Range

   
Set myDoc = ActiveSheet
    myDoc.Unprotect

   
For Each cel In myDoc.UsedRange
       If Not cel.HasFormula And Not TypeName(cel.Value) = "Date" And _           
           
Application.IsNumber(cel) Then
            cel.Locked = False
            cel.Font.ColorIndex = 5
        Else
            cel.Locked = True
            cel.Font.ColorIndex = xlColorIndexAutomatic
        End If
    Next
    myDoc.Protect
    Exit Sub
errorHandler:
    MsgBox Error
End Sub

Destek
M.ÖZTÜRK - Y.KARAMAN
Bu siteyi, "Hayatını çocuklarının Ahlâklı ve Dürüst yetişmesi için harcamış olan Cefakar ve Fedakar, Canım ANNEM'e adadım."
Copyright © 1998-2011 M. Temel Korkmaz - Tüm hakları saklıdır.