28.12.2017 tarihinde,VBA konularına Dosya Okuma/Yazma sayfası eklenmiştir.

20.12.2017 tarihinde,sitem mobil uyumlu hale gelmiştir.

02.12.2017 tarihinde,Excel Fonksiyon konularına "Dizi Formülleri ve SUMPRODUCT" sayfası eklenmiştir.

31.10.2017 tarihinde,VBA Dictionary sayfasına Dictionary, Collection ve Collection dizisinden oluşan ilginç bir örnek eklenmiştir.

26.10.2017 tarihinde,Excel Fonksiyon konularına "İsatistiki ve Matematiksel fonksiyonlar" sayfası eklenmiştir.

VBAMakroTemeller4

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

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 sunabilrsiniz. Genelde, en çok girilen değerleri tahmin ederek girebilirsiniz. Örneğin "Bir il kodu girin" diyip, default değer olarak da İstanbulun kodu olan 34ü yazabilirsiniz.

Yukarda Inputbox'ın bize aktif sayfadan bir seçim de yaptırabilieceğ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ı.

İ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şkenini 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. 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

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)

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
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 ok'dir.

Kullanıcı dostu mesajlar

Ş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
	

Ş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
	

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.

YORUMLAR