13.03.2018 tarihinde,VBA konularına Worksheet Olayları sayfası eklenmiştir.

16.02.2018 tarihinde,VBA konularına Workbook Olayları sayfası eklenmiştir.

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

20.12.2017 tarihinde,sitem mobil uyumlu hale gelmiştir.

VBAMakroTemeller2

Değişkenler ve Veri Tipleri

Değişkenler

Değişkenler, adı üstünde, tüm kod çalışırken zamanla içeriği değişebilecek alanlardır.(Tabiki tüm kod boyunca sabit de kalabilirler, adı değişken diye illa değişmek zorunda değildir).

Neden ve Nasıl?

Değişken tanımlamamızın iki temel nedeni var:

  1. Bilgisayarın belleğini daha verimli kullanmak için. Her değişken için uygun veri tipini tanımlarsanız bellekte o kadar az yer tutulmuş olur. Aksi halde değişkenler Variant tipte olurlar ve en yüksek hacim olan 16 Byte'lık bir hafıza işgal ederler.
  2. Hatalı işlem yapılmasını engellemiş olursunuz.

Birçoğunuzun bu aşamada ileri seviye programlamalar yapmayacağını varsayarak burada daha fazla bu konunun detaylarına şimdilik girmeyeceğim. Public/Private ayrımına da bu sayfada girmeyeceğim ancak isterseniz konularda biraz ilerleyince  buradan detaylı bilgiye ulaşabilrsiniz.

Değişkenleri tanımlamak için nerdeyse her zaman Dim ifadesini ve değişkenden hemen sonra As ifadesini ve hemen arkasından veri tipini yazarız.

Ör:

Dim İsim As String
Dim Yas As Integer
Dim Agirlik As Double
Dim Gerçekleştimi As Boolean	

Bunların hiçbirini tanımlamasanız da çok büyük ihtimalle programınız çalışacaktır. Bunları tanımlayarak hem daha derli toplu hem de daha hızlı çalışan bir makroya sahip olmuş olursunuz.

Değişken kullanmak efektiftir de, mesela i=Range("A1").Value demezseniz ve Range("A1")'deki değeri birkaç yerde kullanıyorsanız ve sonradan Range("A1") yerine Range("A2")'ye referans vermek isterseniz kod içinde Range("A1") geçen her yerde değişiklik yapmak zorunda kalırsınız, ama i=Range("A1").Value demişseniz sadece bunu değiştirmeniz ve diğer yerleri "i" olarak bırakmanız yeterlidir.

Değişikenin tanımlı olması ve olmaması durumunda bellek kullanımı nasıl oluyor bir ona bakalım. Bunun için basit bir örnek üzerinden gidelim.

Sub NoVariable()
	Range("A1").Value = Range("B2").Value
	Range("A2").Value = Range("B2").Value * 2
	Range("A3").Value = Range("B2").Value * 4
	Range("B2").Value = Range("B2").Value * 5
End Sub	

Yukardaki kodda, VBA B2 hücresine 5 kez başvurmaktadır. Yani işlemciyi 5 kez yormuş oluyoruz. Halbuki en baştan B2'nin değerini bir değişkene atamış olsak, işlemcimiz sadece bir kez yorulmuş olacaktır. Ayrıca Eğer B2 hücresindeki değeri silip B4'e taşımamız gerekseydi, kodumuzun 5 yerinde değişiklik yapmamız gerekecekti. Bir diğer detay da bu kodda kullanılan karakter sayısı fazla ve uzun gözüküyor.

Şimdi bi de değişken kullanarak yapalım:

Sub WithVariable()
  Dim i as Integer
  i = Range("B2").Value
  Range("A1").Value = i
  Range("A2").Value = i * 2
  Range("A3").Value = i * 4
  Range("B2").Value = i * 5
End Sub	

Şimdi ne olur? İşlemcimiz, B2 hücresine 5 kez değil 1 kez başvuracak, bu da daha az bellek kullanımı demektir. Ayrıca B2 yerine B4 kullanmak istersek sadece i değişkenini tanımladığımız satırda yani bir kez değiştirmemiz yeterli ve okunuşu daha kolay bir kod.

Bunun gibi 5-6 satırlık bir kodda çok büyük bir fark göremezsiniz, ama yüzlerce satırdan oluşan bir kodunuz olursa farkı o zaman hissedebilirsiniz.

Peki değişkenleri tanımlamadığımızda ne oluyor, program nasıl çalışıyor? VBA, bu tür değişkenleri Variant tipinde depolar ve her defasında bu değişkenin ne tür bir değişkenin ne tür bir değişken olması gerektiğine karar vermeye çalışır, bu da zaman kaybıdır, yani ağır çalışan bir kod demektir. Bu nedenle sitenin anasayfasında dediğim gibi işimizi doğru yapmakla kalmayalım, zerafet içinde doğru yapalım, hızlı yapalım, o yüzden değişkenlerimizi mutlaka tanımlayalım.

Aşağıda tipi belirtilerek değişken tanımladığımızda ve tanımlamadığımızda neler olduğunun süreyle ölçülmüş halini gösteren bir örneğimiz daha var. Fark oldukça açık ve net.

Bu kod, k değişkeni tanımlanmadan çalıştırıldığında 5,88 saniye sürmekteyken k'nın önündeki ' işareti kaldırılıp tanımlama yapıldığında ise 2,13 saniye sürmekte. İşte bellek yönetimi budur!

Sub timerkontrol()
Dim başlangıç As Single
Dim bitiş As Single
Dim i As Long 
'Dim k As Long

başlangıç = Timer 'bu fonksiyon, kodunuzun ne kadar sürede çalıştığını tesipt etmek için kullanılır

For i = 1 To 100000000 'Bu yapı For-Next döngüsüdür. Şimdilik bu döngünün nasıl kullanıldığını bilmiyor olabilirsiniz, buna takılmayın. Sonraki bölümlerde detaylıca incelenecek.
  k = k + 1
Next i

bitiş = Timer

MsgBox ("İşlem süresi:" & vbNewLine & Round(bitiş - başlangıç, 2) & " saniyedir.")
End Sub

Değişken tanımlama kuralları

Değişkenleri tanımlamanın bi faydası da şudur: Değişkenlerinizde mutlaka bir tane Büyük harf bulunursa ve bundan sonra değişkenleriniz hep küçük harfle yazıp space'e veya Enter'a bastığınızda, Excel ilgili harfi otomatikman büyük harfe çevirir, eğer büyük harf olmuyorsa anlarsınız ki değişkeninizi yanlış yazmışsınız. Bu nedenle, burda bu uyarıyı yapmakta da fayda görüyorum.

UYARI!:Değişken isimlerinizde iki kelime veya daha çok varsa mutlaka bir harf, mümkünse ortadan bir harf, büyük olsun. Kod içinde diğer heryerde küçük harfle yazıp, VBA'in büyütmesini bekleyin. Buna programcılık dilinde camelCase notasyonu denmektedir. Genel olarak tüm programlama dillerinde en çok önerilen değişken tanımlama geleneği camelCase olarak bilinen yöntemdir. Ör:

Dim okulNo
Dim ayAdı	
enAltSatırNo 

Böylece siz programınızın başka bir yerinde okulno yazdığınızda otomatikman okulNo olacaktır, aynı şekilde ayadı da otomatikman ayAdı olacaktır.

Bu arada bazı zamanlar olacaktır ki değişkenin içeriği sürekli değişebiliyordur, bazen sayısal bazen karekter bir içeriğe sahip olabiliyordur, hatta sadece sayısaldır ama bazen integer, bazen long integer veya bazen double olabiliyordur veya bir sebepten dolayı tipi bilinmiyordur, bu durumda değişkeni Variant olarak tanımlamaktan başka bir çare yoktur, sadece tipini Variant olarak belirtiyoruz, tip belirtmezsek de Excel onu Variant olarak algılar. Yani şu ikisi de aynı şekilde algılanır

Dim deger As Variant
Dim deger

Değişken tanımlamada dikkat edilecek diğer hususlar şöyledir:

  • İlk karakter bir harf olmalı
  • boşluk, nokta(.), ünlem(!), ve şu karakterler kullanılmaz (@, &, $, # )
  • Çok geçeğini sanmam ama karakter uzunluğu 255i geçmemeli
  • VB rezerv kelimeleri kullanılmamalı (for, next, String vs.)

Program boyunca sabit kalacak bir değişkeniniz varsa bunu Const ifadesi ile tanımlayabilirsiniz. Örneğin, mağaza sayısı 15 olan bir firma için bunu sabit olarak tanımlayabilir ve döngülerde bu sabiti kullanabilirsiniz.

Const magaza As Integer = 15 'aynı satırda tanımlanmak zorunda
For i = 1 to magaza
'Kodlar
Next i

Dikkat:Sık yapılan hatalardan biri de şudur. Şimdi iki String değişken tanımlamak istediğimizi düşünelim. Eğer kelimeden tasarruf edeyim deyip şu şekilde tanımlarsak hata yaparız:

Dim metin1, metin2 as String

Çünkü bu şekilde aslında ilk değişkenin tipi belirtilmemiş oldu ve bu yüzden Variant oldu, String değil. Bu nedenle şu şekilde tanımlama yapmalıyız.

Dim metin1 as String, metin2 as String
'veya daha güvenli olsun isterseniz
Dim metin1 as String
Dim metin2 as String

Option Explicit

Eğer buraya kadar okuduklarınızdan değişkenleri tanımlamanın gerçekten iyi bir fikir olduğunu düşünüyorsanız, bütün modüllerinizin başında Option Explicit ifadesi bulunsun, bu sizi değişkenleri tanımlamaya zorlayacaktır.

Option Explicit
Sub zorunlu()
  mesaj="Merhaba"
  MsgBox mesaj
End sub	

Yukardaki kodu çalıştırdığınızda hata verecektir, çünkü mesaj değişkeni tanımlanmamıştır.

Her modülün başına tek tek bu ifadeyi yazmak istemiyorsanız, şu ayarlamayı yapın. VBE içinde Tools>Options düğmesine basın ve aşağıdaki seçeneği işaretleyin.

Değer atama ve Default(Varsayılan) değerler

Değişkenleri tanımladıktan sonra onlara bir de değer atamak gerekir. Bunların değer atanmayana kadar aldıkları varsayılan değerleri vardır. Buna göre;

  • Sayısal tipte bir değişken için varsayılan değer 0'dır.
  • Karekter tipinde bir değişken için varsayılan değer "" yani sıfır uzunluklu stringtir.
  • Nesne tipinde bir değişken için varsayılan değer ise Hiçbirşeydir(Null veya Nothing)

Bu konuda daha detaylı ve karşılaştırmalı bilgiye buradan ulaşabilirsiniz.

Şimdiye kadarki örneklerde gördüğünüz üzere sayısal veya karakter tipte bir değişkene değer ataması için = işaretini kullanırız. Ör:

i=0
ay="Ocak"

Bir nesneye(Range, sheet, collection v.s) değer atamak içinse Set terimini kullanırız. Ör:

Dim hucre As Range
Dim ws As Worksheet

Set hucre=Range("A1")
Set ws=Activesheet

Nesne tanımlamalarında, kod bitiminde bu nesneleri tekrar Nothing olarak atamak bellek yönetimi açısından faydalıdır, böylece Excel bu nesneler için bellekte gereksiz yer ayırmayacaktır.

Sub Ornek()
	Dim hucre as Range
	Set hucre = Range("A1")
	'Diğer Kodlar
	Set hucre = Nothing
End Sub

Static deyimi ile değişken tanımı

NOT:Static kavramı biraz daha ileri seviye konularındandır, ancak tek başına ileri seviye konularının arasında sırıtacağı için anlam bütünlüğü açısından da buraya daha uyduğu için buraya almak durumunda kaldım.

Dim ifadesi ile tanımladığımız tüm değişkenler ilgili prosedür çalıştırıldıktan sonra bellekten silinir. Ancak bazı durumlarda, tanımladığımız değişkenin prosedür çalıştıktan sonra bile bir önceki değerini tutmasını bekleriz.

UYARI:Bundan sonrasına devam etmeden önce Application.OnTime metodunun öğrenilmesinde veya genel bir fikir edinilmesinde fayda var.

Mesela her 5 dakikada çalışacak şekilde bir ayarlanmış bir prosedür düşünün. Sabah işe geldiğinizde 9:00 gibi çalışmaya başlatıyorsunuz, akşam 18:00'e kadar da 5 dk aralıklarla kendisi Refresh olup çalışıyor. Saat 17:00 olduğunda belli alıcılara bir mail atsın istiyoruz diyelim. Sabah çalıştırma saatimiz her zaman tam net 9:00 olmayacağı için "saat=17:00 mı" diye kontrol edemeyiz. Bunun yerine saat 16'dan büyük mü diye kontrol etmeliyiz. Diyelim ki bir önceki çalıştırma işlemi 16:58:23'te oldu, bir sonraki 17:03:23te olacak, tam bu anda yakalarz, ama bi sonraki de 17:08:23te olacak, yine kontrole takılır ve bu şekilde 12 kez mail gitmiş olur, ki böyle birşey istemeyiz.

İşte böyle bir durumda statik bir değişken tanımlayabiliriz. Aşağıdaki örneğe bakalım. Saat 16'dan büyükse i'yi her defasıdna 1 artırıyoruz ancak sadece i=1 ise yani ilk kez gidecekse mail gönderimi yapıyoruz.

Sub statikornek()
Static i As Integer

If Hour(Now) > 16 Then 'Bu yapı koşullu karşılaştırma yapmamazı sağlayan IF yapısıdır. Şimdilik bu yapının nasıl kullanıldığını bilmiyor olabilirsiniz, buna takılmayın. Sonraki bölümlerde detaylıca incelenecek.
    i = i + 1
    If i = 1 Then Call mailproseduru
End If

Application.OnTime Now + TimeValue("00:05:00"), "statikornek" ' 5 dk sonra kendisini tekrar çalıştırıyor

End Sub

Sub mailproseduru()
  MsgBox "mail gönderimi"
  'diğer kodlar
End Sub

Bu işlemi pek tabiki saatin 17:05:00'ten küçük olup olmadığına bakarak da yapabilirdik ama Statik konusunu anlamak adına uygun bir önrek olacağını düşündüm.

Bu arada bir diğer alternatif de i'nin değerini sayfada boş ve görünmeyen bir hücreye yazıp bunun değerini kontrol etmek olabilirdi.

Veri Tipleri ve Boyutlar

Exceldeki temel veri tiplerini iki gruba ayırabiliriz, sayısal ve sayısal olmayan. Toplamda 14 çeşit temel veri tipi bulunur. Neden bu kadar veri grubu var dersek, birinci sebep kullandıkları hafıza miktarı, ikincisi ise belli işlemlerin sadece belli veri tipleriyle yapılmasını sağlayarak hatalı işlemlerin olmasını engellemek diyebiliriz. Şimdi bunlara yakından bakalım.

Sayısal veri tipleri

TipAlabileceği değerlerHafıza Kullanımı (Byte)
Byte 0 ile 255 1
Integer -32.768 ile 32.767 2
Long -2.147.483.648 ile 2.147.483.648 4
Single -3.4*10^38 ile 3.4*10^38 (Küsuratlar ihmal edilmiştir) 4
Double -1.7*10^308 ile 1.7*10^308 (Küsuratlar ihmal edilmiştir) 8

Currency diye bir tip daha var ama 20 yıldır hiç kullanmadım, o yüzden buraya koymuyorum.

Bunlardan en çok küsurata sahip olanı Double'dır. İhtiyacınıza göre birini kullanırsınız. Aşağıda küsuratları gösteren bir örnek var.

Sub tipler()

Dim d As Double, s As Single, c As Currency, l As Long, i As Integer, t As Byte

a = 9
b = 7
d = b / a
s = b / a
c = b / a
l = b / a
i = b / a
t = b / a

Debug.Print d, s, c, l, i, t 'sırasıyla 0,777777777777778 0,7777778 0,7778 1 1 1

End Sub

Bir de Decimal diye bir tip var, bu en yüksek küsurat duyarlığına sahip veri tipidir. Ancak bunun kullanımı biraz daha alengirli, o yüzden burada detaya girmiycem, zaten bunu da Currency tipi gibi 20 yıl boyunca kullanma ihtiyacım hiç olmadı.

Sayısal olmayan tipler

TipAlabileceği değerlerHafıza Kullanımı (Byte)
String(sabit boyutlu) Max 65400 karaktersabit boyut
String(değişken boyutlu) Max 2 milyar karakter10+karakter sayısı
Date Makul bir tarih girin yeter8
Boolean True ve False 2
Object Çok çeşitli(Ör:Range, Workbook, Collection)4
Variant(Varsayılan veri tipi)Herşey olabilir16

Burada biraz String enteresan görünüyor. Bununla ilgili bir örnek yapalım

Dim isim As String 'Boyut belirtmediğimiz için değişken boyutludur
isim="Volkan" 'şuan 6 karakter içerir+10=16 Byte
isim="Mustafa Kemal" 'şuan 13 karakter içerir+10=23 Byte

Şimdi diyebilirsiniz ki, Variant tipi 16 Byte tutuyor, değişken boyutlu String'i neden kullanalım ki, yukardaki örnekte 23 Byte oldu. Variant'ın 16 Byte tutma olayı, ilk tanımlama anındadır. Sonrasında, içersindeki değişkenini tipine göre boyutu artabilir.

Devam edelim, şimdi de sabit boyutlu String nasıl tanımlanır ona bakalım.

Dim isim as String*15
isim="Volkan" 'Hafızada şöyle tutulur "Volkan         " '15i tamamlayacak kadar boşluk eklenir

Temel olmayan veri tipleri

Bu yukarıdaki temel veri tipleri dışında Range, Collection, Worksheet gibi çeşitli class(sınıf)lardan üretilen nesneler var, o yüzden bunlar da veri tipi olarak düşünülebilir. Dim hucre As Range ifadesinde olduğu gibi. Bunun dışında ileri VBA sayfalarında göreceğimiz gibi kendi tanımladığımız sınıfları da veri tipi olarak düşünebiliriz. Mesela Student diye bir class tanımladysanız Dim st As Student şeklinde bir değişken tanımlayabilirsiniz.

Enumeration/Constant

Bazı sabitler vardır ki bunlar Excel açılır açılmaz yüklenirler ve kullanıma hazırdırlar. Bunların kimisinin kullanımı faydalı iken kimisi zorunludur. Mesela vbNullString boş string amaçlı olarak "" yerine kullanılabilir. Böylece boşuna bellekte yer ayrılmamış olur, zira bu vbNullString zaten o anda bellektedir, yani ilave bellek tüketmez. Ancak mesaj kutularına verilen cevabın evet mi olduğunu anlamak için vbYes sabitini kullanmak zorunludur.

Biz bu sabitlerden 3 çeşitini kullanıyor olacağız.

  • vb ile bşlayanlar: VBA library'sinin sabitleri
  • xl ile başlyanlar: Excel library'sinin saibtleri
  • mso ile başlayanlar:Office library'sini sabitleri

Bunların bir de numerik karşılıkları vardır, bunlara Enumeration değerleri denir. Örneğin vbYes'in değeri 6'dır. bunların ikisi de kullanılabilr.(NOT:İlerde kodlarınızı VSTO ortamına geçirmek istediğinzde numerik karşılıklarını kullanmanız gerekecektir)

Mesela aşağıdaki kodu yazıp çalışıtığrıdığınızda size bu sabitib sayısal karşılığı olan 65280i verir.

Ayrıca kendi Enumeration tiplerinizi de oluşturabilirsiniz.

Private Enum Bolgeler
  Akdeniz '0
  Karadeniz '1
  Marmara '2
  Ege '3
  Anadolu '4
End Enum

YORUMLAR