Interaktivite

Makrolar kullanıcı ile belli başlı 4 şekilde iletişim kurar.

  • Mesaj kutuları(MsgBox)
  • Bilgi sorma kutuları (InputBox)
  • Formlar(Userforms)
  • File/Folder dialog kutuları

Son ikisini ayrı bölümlerde işleyeceğiz, biz şimdilik burada MsgBox ve InputBox ile haşır neşir olacağız.

Inputbox ile kullanıcıya çeşitli sorular sorar, ondan bir şeyler yazmasını veya sayfa üzerinde birşeyleri seçmesini bekleriz. Kullanıcının bu girdiği değeri de bir değişken içinde depolarız. O yüzden Inputboxları tek başına kullanmak yerine her zaman bir değişkene atama şeklinde kullanırız.

                            
                                Dim ad As String
                                ad = InputBox("Adınızı girin")      

                            
                        

Inputbox'a girilen her değer bir metindir, sayı olsa bile bu metin olarak depolanır. Girilen değeri sayı olarak kullanmak istiyorsanız bunu Valveya buna benzer bir dönüştürme metodu (Int, CInt, CLng, CDbl gibi) ile sayıya çevirmeniz gerekir. Aksi halde istenmeyen sonuçlar ortaya çıkabilir. Bir örnekle bakalım

                        
                                Sub input1()

                                a = InputBox("bir sayı girin")
                                b = InputBox("ikinci bir sayı girin")

                                Range("A1").Value = a + b

                                End Sub      

                            
                        

Kodu çalıştıralım, a için 5, b için 7 girelim. A1 hücresinde 12 rakamını görmeyi bekleriz ama 57 yazar. Çünkü VBA metinler için birleştirme operatörü olarak + işaretini de kullanılır(bir de & işareti var).
Şimdi aynı kodu aşağıda gibi çalıştıralım, aynı değerleri girelim, bu sefer 12 sonucunu görebiliriz.

                        
                                Sub input2()

                                a = InputBox("bir sayı girin")
                                b = InputBox("ikinci bir sayı girin")

                                Range("A1").Value = Val(a) + Val(b)

                                End Sub     

                            
                        

Bir diğer alternatif de, numerik olmasını istediğimiz değişkenleri baştan numerik olarak tanımlamaktır.

                        
                                Sub input3()
                                Dim a As Integer
                                Dim b As Integer
 
                                a = InputBox("bir sayı girin")
                                b = InputBox("ikinci bir sayı girin")
 
                                Range("A1").Value = a + b '12 yazar
 
                                End Sub    

                            
                        
Kullanım şekli ve diğer InputBox

Nesne Modelini anlatırken Classlardan ve Library'lerden bahsetmiştim. İşte bu yukarda gördüğümüz InputBox da VBA Library'si içinde Interaction class'ına ait bir fonksiyondur. Birçok fonksiyon gibi bu da parametre alır.
Syntax'ı şöyledir: InputBox(Prompt[,title][,default][,xpos][,ypos][,helpfile,context])
Bu parametrelerden sadece köşeli parantez içine alınmamış olan Prompt parametresi zorunlu olup diğerleri opsiyonedir. Önemlilerin açıklaması ise şöyledir:

  • Prompt:Kullanıcıya ne girişi yapmasını söyleyeceğimiz ifade. Ör:Adınızı giriniz.
  • Title:Inputbox kutusunun başlığını set edebilirsiniz
  • Default:Faydalı bir özelliktir, kullanıcıya bazı durumlarda kutu içinde hazır bir değer sunabilirsiniz. Genelde, en çok girilen değerleri tahmin ederek girebilirsiniz. Örneğin "Bir il kodu girin" diyip, default değer olarak da İstanbul'un kodu olan 34ü yazabilirsiniz.

Yukarda Inputbox'ın bize aktif sayfadan bir seçim de yaptırabileceğini söylemiştim. Ancak yukardaki kodları çalıştırdığınızda bunu yapamazsınız, isterseniz bi deneyin, sonra tekrar gelin. Peki neden böyle söyledim. Çünkü bir Inputbox'ımız daha var, bu işlemi o yapar ve kendisi Excel Library'sindeki Application nesnesinin bir metodudur. Terminoloji sayfasında belirttiğimiz gibi, bu Inputbox metodu diğer metodlar gibi bir nesneye ihtiyaç duyar, yani tek başına kullanılamaz, o nesne de Application nesnesidir. İlki function iken ikincisi metoddur.
Zaten aşağıdaki resimden de görüleceği üzere bağlı oldukları classların iconları bile farklı.

post-thumb

İkinci Inputbox'ımızın syntax'ı ise şöyledir:Application.InputBox(Prompt,Title,Default,Left,Top,HelpFile,HelpContextID,Type)
Bir önceki InputBox'tan farklı olarak en sonda bir Type parametresi görüyoruz. Bu parametrenin alabileceği değerleri ve anlamları aşağıda verilmiştir. En sık kullanacaklarımız koyu gösterilmiştir.

Değer Anlam
0 Formül
1 Sayı
2 Metin
4 True/False
8 Range(Bir hücre grubu)
16 Hata değeri
64 Dizi

Tablodan da görüleceği üzere kullanıcıya bir hücre grubu seçtirmek için Type parametresini 8 tipinde belirtmemiz gerekiyor. Eğer kullanıcı hem metin hem sayısal birşey girebilecekse Type değerine toplam değer olan 3(1+2) yazılır.
Hemen bir örnek yapalım.

                        
                                Dim sonHucre As Range
                                Set sonHucre = Application.InputBox(Prompt:="Son hücreyi seçin", Type:=8)       
            

                            
                        

Değişkenlerle ilgili sayfadan hatırlayacağınız üzere nesnelere değer atamak için Set ifadesini kullanıyorduk, burada da öyle yaptık.

Boş geçilen kutular(Cancel veya Esc ile iptal)

Bazen kullanıcılar hiçbir değer girmeden çıkmak ister, o zaman ne olur.

  • Klasik Inputbox'ın dönüş değeri olan Stringtir ve bu durumda ilgili değişkene String tipinin default değeri atanır, yani "". O yüzden değişkenin değerinin "" olup olmadığı kontrol edilir.
  • Application.Inputbox metodununu dönüş değeri Varianttır, o yüzden default değer olarak Empty bekleriz ancak MSDN bize bu Inputbox'ta boş geçilen değerler için atanan değerin False olduğunu söylüyor. O yüzden değişkenin değerini False olup olmadığı kontrol edilir, ama bu klasik Inputboxa göre biraz daha alengirlidir. Aşağıdaki örneklere bakalım.

Kodumuzda hatalı birşey olmaması için bazı kontroller yapmamız gerekiyor. Bundan sonrasına devam etmeden önce koşullu yapıları bildiğinizden emin olun, bilmiyorsanız buradan kısa bir bilgi edinip tekrar buraya gelin.

                        
                                'klasik Inputbox
                                    a=Inputbox("Bir değer girin")
                                    If a<>"" Then
                                       Msgbox "Giriş yapıldı"
                                       'Diğer kodlar buraya
                                    Else
                                       Msgbox "Bir giriş yapılmadan çıkmayı tercih ettiniz"        
                                    End If

                                    'Application'lı, String
                                    Dim a As String
                                    a=Application.Inputbox("Adınızı girin", Type:=2)
                                    If a<>"False" Then 'False'ın tırnak içinde yazıldığına dikkat edin
                                        Msgbox "Giriş yapıldı"
                                        'Diğer kodlar buraya
                                    Else
                                        Msgbox "Bir giriş yapılmadan çıkmayı tercih ettiniz"           
                                    End If     

                                    'Application'lı, Integer(değişken tanımlanmaz, yani Varianttır)
                                    a=Application.Inputbox("Yaşınızı girin", Type:=1)
                                    If a<>False Then 'Variant her değeri alabilecğei için False ifadesi aynen yazılır
                                        Msgbox "Giriş yapıldı"
                                        'Diğer kodlar buraya
                                    Else
                                        Msgbox "Bir giriş yapılmadan çıkmayı tercih ettiniz"           
                                    End If

                                    'Application'lı, Integer(değişken tanımlanır)
                                    Dim a As Integer
                                    a=Application.Inputbox("Yaşınızı girin", Type:=1)
                                    If a<>0 Then 'Sayısal ifadelerde False veya False'ın rakamsal karşılığı olan 0 kullanılabilir
                                        Msgbox "Giriş yapıldı"
                                        'Diğer kodlar buraya
                                    Else
                                        Msgbox "Bir giriş yapılmadan çıkmayı tercih ettiniz"           
                                    End If

                                    'Applicationlu, Range
                                    'Range seçiminde eğer kullanıcı seçim yapmazsa hata oluşur, bu yüzden bir hata kontrol mekanizması da ekleriz
                                    've ayrıca bir seçim yapıp yapmadığını da Nothing ile kontrol ederiz        
                                    On Error Resume Next 'burayı yazmassak hata alırız. Hata yönetim mekanizmaları için ilgili sayfaya gidip bilgi edinebilirsiniz
                                    Dim a As Range
                                    Set a = Application.InputBox("Bir hücre seçin", Type:=8)
                                    If Not a Is Nothing Then
                                        Msgbox "Seçim yapıldı"
                                        'Diğer kodlar buraya
                                    Else
                                        Msgbox "Bir seçim yapılmadan çıkmayı tercih ettiniz"               
                                    End If      


                            
                        

Şimdi son olarak tam bir örnek yapalım. Bu örnekte kullanıcıdan açık olan dosyaya kaç sayfa eklemek istediğini soracağız, detaylara takılmayın, sadece yukardaki anlatılanları pekiştirmeye çalışın.

                        
                                Sub Sayfaekle()
                                Dim i As Integer, syf As Integer

                                syf = Application.InputBox("Kaç sayfa ekleyelim", Default:=3, Type:=1)

                                If syf = False Then 'escape'e baıslıysa veya Cancel'a tıklandıysa. Bunu ayrıca if syf= 0 diye de yapabilrdik
                                    Exit Sub
                                Else
                                    For i = 1 To syf
                                        Worksheets.Add
                                    Next i
                                End If
                                End Sub    


                            
                        

MsgBox ile ya bilgilendirme yaparız, ya da cevabı Evet/Hayır gibi sorular sorup bilgi ediniriz. Bilgilendirme yaptığımızda bunu bir değişkene atamaya gerek yoktur, ancak bilgi topladığımızda Inputboxta olduğu gibi bir değişkene atamamız lazım.
MsgBox da InputBox gibi VBA Library'sindeki Interaction sınıfı içinde yer alır ve syntax'ı şöyledir: MsgBox(prompt[, buttons] [, title] [, helpfile, context])
Burda prompt ve title InputBoxtaki gibidir, son iki parametreden bahsetmeyeceğim, arzu eden araştırabilir. Burda önemli bir parametre var: buttons parametresi. Bu parametrenin alabileceği değerler şöyledir(Liste daha uzun ama çoğu gereksiz olduğu için buraya almadım, hatta bunlardan da en çok YesNo ve YesNoCancel düğmelerini kullanacağımızı söyleyebilirim)

post-thumb

Aşağıda bilgilendirmeye örnek bir kod var

                            
                                    Sub MessageBox()
                                        'Uzunca bir kod bloğu

                                        MsgBox "İşlem tamamdır"
                                    End sub 

                            
                        

Bilgi edinme örneği ise şöyle birşey olabilir.

                        
                                    Sub MessageBox()
                                        cvp = MsgBox("Ana diskinizde(Ör:'C:') 'böl' isminde bir klasörünüz var mı?", vbYesNo) ' bu bilgi toplama mesajı
                                        If cvp= 6 Then 'yes demek oluyor
                                            GoTo ilerle
                                        Else
                                            MsgBox "O ZAMAN O KLASÖRÜ YARATIP TEKRAR ÇALIŞTIR" 'bu bilgi mesajı
                                            Exit Sub
                                        End If
                                    ilerle:
                                    'diğer kodlar
                                    End sub 

                            
                        

Gördüğünüz üzere cvp değerinin değerini 6 gibi bir sayıyla ölçtük. İşte VBA'da bazı sabitlerin(constant) böyle sayısal değerleri vardır, ikisi de kullanılabilir. Tüm düğmeler ve değerleri şöyle.

Sabit Değer
vbOK 1
vbCancel 2
vbAbort 3
vbRetry 4
vbIgnore 5
vbYes 6
vbNo 7

InputBox'ta olduğu gibi MsgBox'ın da iptal edilmesi sözkonusu olabilmektedir. Tabi eğer buton türü olarak Cancel varsa. Aksi halde Esc tuşu da işe yaramamaktadır.
Bu örnekten çıkış mümkün değilken,

                            
                                    Sub msgbox1()

                                    On Error GoTo hata
                                    a = MsgBox("Cevap verirmisin", vbYesNo)
                                    'Diğer kodlar
                                    Exit Sub
                                    hata:
                                    Debug.Print Err.Description

                                    End Sub

                            
                        

Ama bunu iptal edebilirsiniz.

                        
                                    Sub msgbox1()

                                    On Error GoTo hata
                                    a = MsgBox("Cevap verirmisin", vbYesNoCancel)
                                    If a = vbYes Then
                                        MsgBox "Evet denildi"
                                    ElseIf a = vbNo Then
                                        MsgBox "Hayır denildi"
                                    Else
                                        MsgBox "Seçimi iptal ettiniz"
                                    End If
                                    Exit Sub

                                    hata:
                                    Debug.Print Err.Description

                                    End Sub

                            
                        

Önemli bir detay da, MsgBox'ın bilgi toplama formundayken mutlaka ()'ler içinde kullanılmasıdır. Mesaj verirken ise genelde () olmadan kullanılır, ama parantezli kullanımı da sorunsuz çalışır.

Şimdi kod yazmada biraz deneyim kazandığımıza göre uzun kodlar yazarken nelere dikkat etmemiz gerekir ona bir bakalım.

Kullanıcı dostu kodlama

Kullanıcılara bazen MsgBox ile bazen Inputbox ile çeşitli mesajlar yayınlamak gerekecek. Kullanıcı bu mesajları rahat okusun diye gerekli yerlerde satır geçişlerini yapmanız lazım. Bir örnekle ne demek istediğimiz daha iyi anlatabilirim.
Şimdi aşağıdaki kodu, bir modül içine yazıp F5 ile çalıştıralım. Görüntü aşağıdaki gibi olup, kullancının okuması açısından çok kolay değildir.

                            
                                Sub satırgeçiş()
                                    a = InputBox("Müşteri segmenti için bir değer giriniz. Bireysel müşteriler için 1, Ticari müşteriler için 2, Kurumsal müşteriler için 3")
                                End Sub


                            
                        
post-thumb

Şimdi bir de bu kod nasıl daha düzenli hale getirilir ona bakalım: Her cümle ve seçenek arasına bir ifade koyarak. Bu ifade vbCrLf ifadesidir ve cümleleri bir alt satıra taşır, bunun yerine vbCr veya vbLf veya vbNewLine veya Chr(10) ifadeleri de kullanılabilir. (Bunların dördü de Msgbox ve InputBox kullanımında aynı etkiye sahiptir, ancak hücre içine birşey yazdırırken farklı etkilere sahiptir, bunu deneyip görebilrisiniz.)

                        
                                Sub satırgeçiş2()
                                a = InputBox("Müşteri segmenti için bir değer giriniz. " & vbCrLf & "Bireysel müşteriler için 1," & vbCrLf & "Ticari müşteriler için 2," & vbCrLf & "Kurumsal müşteriler için 3")
                                End Sub


                            
                        
post-thumb
Kodlamacı dostu kodlama

Şimdi yeri gelmişken bir de kullancı dostu olmakla ilgili değil ama kodlamacı dostu olmakla ilgili bir notum olacak. Yine yukardaki kodu örnek alalım, bu kod biz kodlamacılar için de okuması zor, çünkü VBE içinde kod sağa doğru uzuyor, ama kodlamacı olarak benim bunu ekranda, scroolbarı sağa sürüklemeden görebilmem lazım. Hadi gelin bunu okunaklı hale getirelim.
Yapacağımız şey basit, cümleyi nerden kesmek istiyorsak oraya bir boşluk ve sonrasında bir alt çizgi(_) koymak. Buna Line Contination Character adı verilir.

                        
                                Sub satırgeçiş3()
                                a = InputBox("Müşteri segmenti için bir değer giriniz. " & vbCrLf &  _
                                "Bireysel müşteriler için 1," &  vbCrLf &  _
                                "Ticari müşteriler için 2," &  vbCrLf &  _
                                "Kurumsal müşteriler için 3")
                                End Sub


                            
                        

Görüldüğü gibi, kod şimdi bizim için de daha okunaklı hale geldi.
Bunu yapmanın bir yolu daha var, o da metni parçalara ayırmak.

                        
                                Sub satırgeçiş4()
                                mesaj = "Müşteri segmenti için bir değer giriniz. " & vbCrLf
                                mesaj = mesaj + "Bireysel müşteriler için 1," & vbCrLf
                                mesaj = mesaj + "Ticari müşteriler için 2," & vbCrLf
                                mesaj = mesaj + "Kurumsal müşteriler için 3"
 
                                a = InputBox(mesaj)
 
                                End Sub


                            
                        

NOT:mesaj = mesaj + ..... şeklinde sağduyuya aykırı gibi görünen kısım kafanızı karıştırdıysa buradan detaylı bilgi edinebilirsiniz.
Bu iki yöntemi sadece interaktivite sağlayan yerlerde değil başka yerlerde de kullanacağız.
Bu arada hemen iki yöntem arasındaki küçük farka da değinelim. İlk yöntem yani _ yöntemi ile sadece metin birleştirme değil, içinde metin bile olmayan tam bir VB kodunu da parçalara ayırabiliriz, amaç yine aynı: Sağa doğru uzayan kodu tek bir ekranda tutmak. Aşağıdaki gibi.

                        
                                Sub blabla()
                                Cells.Find(What:="Volkan", After:=ActiveCell, LookIn:=xlValues, _
                                LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                                MatchCase:=False).Activate
                                End Sub


                            
                        

İkinci yöntemin ise tek amacı uzun metinleri parçalara ayırmaktır.