Genel Bakış
ReDim (Redimension), VBA'da dinamik bir dizinin eleman sayısını ve sınırlarını program çalışırken yeniden belirleyen deyimdir. Kaç veri geleceği önceden bilinmediğinde, örneğin bir sütundaki dolu hücreleri toplarken diziyi gerektiği kadar büyütmeye yarar. Preserve anahtar sözcüğüyle birlikte kullanılırsa dizideki mevcut değerler korunur.
Preserve kullanılmadan ReDim çalıştığında dizi sıfırlanır. Sayısal diziler 0, String dizileri boş metin, Variant dizileri Empty, Object dizileri Nothing değerini alır.
Dizinin sınırlarını öğrenmek için LBound ve UBound işlevleri kullanılır. Dizinin içeriğini silip belleği geri vermek için Erase deyimi uygundur.
Makro, adedi 50 ve üzeri olan ürünleri sırayla C sütununa yazar. İlk seçilen ürün Defter, ikincisi Silgi hücresindedir; listenin devamı Dosya, Kağıt ve Bant hücrelerinde yer alır. Dizi her uygun üründe bir eleman büyüdüğü için boyutu baştan bilmeniz gerekmez.
Üç aylık toplamlar E sütununa yazılır: Ankara için 405, İzmir için 590, Bursa için 295. Dizinin ikinci boyutu ReDim Preserve ile 2'den 3'e çıktığı için Ocak ve Şubat verileri kaybolmadan Mart sütunu eklenebilmiştir. İlk boyutu (şehir sayısını) Preserve ile değiştirmeye çalışsaydınız çalışma zamanı hatası alırdınız.
İlk adımda üst sınır 5, ilk eleman 10 olarak yazılır. Preserve ile büyütmeden sonra üst sınır 8 olur ve ilk eleman 10 değerini korur. Preserve olmadan yapılan son ReDim'de üst sınır 12 olur, fakat ilk eleman 0 değerine sıfırlanır; çünkü Preserve yazılmayan ReDim diziyi baştan oluşturur.
Söz dizimi
ReDim deyimi, daha önce parantezi boş bırakılarak bildirilmiş dinamik bir diziye (ya da Variant türündeki bir değişkene) boyut kazandırır. Aynı deyimde virgülle ayırarak birden çok dizi yeniden boyutlandırılabilir.
VBA
7 satır
ReDim [Preserve] degisken(altSinir To ustSinir, ...) [As tur]
' Ornek: tek boyutlu ve iki boyutlu dizi
Dim liste() As String
Dim tablo() As Double
ReDim liste(1 To 10)
ReDim tablo(1 To 5, 1 To 3)
- Preserve: İsteğe bağlıdır; varsayılan olarak yoktur ve yoksa dizideki tüm değerler silinir. Yazılırsa eski değerler korunur.
- degisken: Yeniden boyutlandırılacak dizinin adıdır. Dizi dinamik olmalıdır (Dim ad() biçiminde bildirilmiş) ya da Variant türünde bir değişken olmalıdır.
- altSinir: İsteğe bağlıdır; yazılmazsa varsayılan 0'dır (Option Base 1 kullanılıyorsa 1).
- ustSinir: Zorunludur; boyuttaki en büyük dizin numarasıdır. Değişken ya da hesaplanmış bir değer olabilir.
- As tur: İsteğe bağlıdır. Yazılırsa Dim deyimindeki veri türüyle aynı olmalıdır; türü ReDim ile değiştirmek yalnızca Variant değişkenlerde mümkündür.
Başlangıç değerleri ve dinamik dizi hazırlığı
ReDim, sabit boyutlu diziyi değiştiremez. Dim a(1 To 5) ile bildirilmiş bir diziye ReDim uygulanırsa Excel derleme hatası verir. Dinamik dizi için parantez boş bırakılır ve boyut sonradan ReDim ile verilir.Preserve kullanılmadan ReDim çalıştığında dizi sıfırlanır. Sayısal diziler 0, String dizileri boş metin, Variant dizileri Empty, Object dizileri Nothing değerini alır.
Dizinin sınırlarını öğrenmek için LBound ve UBound işlevleri kullanılır. Dizinin içeriğini silip belleği geri vermek için Erase deyimi uygundur.
Preserve kullanımı ve sınırları
ReDim Preserve ile dizi büyütülür ya da küçültülür, eski değerler korunur. Küçültülürse sığmayan elemanlar kaybolur. Preserve için şu kurallar geçerlidir:- Yalnız son boyut: Çok boyutlu dizilerde yalnızca son boyutun üst sınırı değiştirilebilir. Örneğin (1 To 3, 1 To 2) dizisinde yalnızca ikinci boyut büyütülebilir.
- Boyut sayısı: Boyut sayısı değiştirilemez; tek boyutlu dizi iki boyutlu yapılamaz.
- Alt sınır: Preserve ile alt sınır değiştirilemez.
- İlk kullanım: Henüz boyutlandırılmamış dinamik dizide de ReDim Preserve hata vermeden çalışır; bu sayede döngüde diziyi eleman eleman büyütmek kolaylaşır.
1. Koşula uyan ürünleri diziye toplama
A sütununda ürünler, B sütununda sipariş adetleri var. Kaç ürünün koşulu sağlayacağı bilinmediği için dizi her uygun üründe ReDim Preserve ile büyütülür; adedi 50 ve üzeri olan ürünler sonunda C sütununa yazılır. Kodu standart modüle yapıştırın.
VBA
26 satır
Option Explicit
Sub YuksekAdetListele()
Dim ws As Worksheet
Dim secilen() As String ' dinamik dizi
Dim sayac As Long, i As Long, sonSatir As Long
Set ws = ActiveSheet
sonSatir = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
For i = 2 To sonSatir
If ws.Cells(i, 2).Value >= 50 Then
sayac = sayac + 1
' Eski elemanlari koruyarak diziyi bir eleman buyut
ReDim Preserve secilen(1 To sayac)
secilen(sayac) = ws.Cells(i, 1).Value
End If
Next i
' Hic urun secilmediyse dizi boyutlanmamistir
If sayac = 0 Then Exit Sub
For i = 1 To sayac
ws.Cells(i + 1, 3).Value = secilen(i)
Next i
End Sub
Redim
Formülünü incelemek için bir hücre seçin.| A | B | C | |
|---|---|---|---|
| 1 | Ürün | Adet | Seçilen Ürün |
| 2 | Defter | 80 | Defter |
| 3 | Kalem | 35 | Silgi |
| 4 | Silgi | 120 | Dosya |
| 5 | Dosya | 60 | Kağıt |
| 6 | Zımba | 20 | Bant |
| 7 | Kağıt | 200 | |
| 8 | Makas | 45 | |
| 9 | Bant | 90 |
SiparişlerExcelDepo v1.0.0
2. İki boyutlu dizide son boyutu büyütme
Tabloda üç şehrin Ocak, Şubat ve Mart satışları var. Makro önce iki aylık veriyi (1 To 3, 1 To 2) boyutlu bir diziye alır, sonra ReDim Preserve ile ikinci boyutu 3'e çıkarıp Mart verisini ekler ve her şehrin toplamını E sütununa yazar. Kodu standart modüle yapıştırın.
VBA
33 satır
Option Explicit
Sub AyEkleVeTopla()
Dim ws As Worksheet
Dim veri() As Double
Dim i As Long, j As Long
Dim toplam As Double
Set ws = ActiveSheet
' Once Ocak ve Subat (2 sutun)
ReDim veri(1 To 3, 1 To 2)
For i = 1 To 3
For j = 1 To 2
veri(i, j) = ws.Cells(i + 1, j + 1).Value
Next j
Next i
' Yalnizca SON boyut buyutulur; eski veriler korunur
ReDim Preserve veri(1 To 3, 1 To 3)
For i = 1 To 3
veri(i, 3) = ws.Cells(i + 1, 4).Value
Next i
' Her sehrin toplamini yaz
For i = 1 To 3
toplam = 0
For j = 1 To 3
toplam = toplam + veri(i, j)
Next j
ws.Cells(i + 1, 5).Value = toplam
Next i
End Sub
Redim
Formülünü incelemek için bir hücre seçin.| A | B | C | D | E | |
|---|---|---|---|---|---|
| 1 | Şehir | Ocak | Şubat | Mart | Toplam |
| 2 | Ankara | 120 | 135 | 150 | 405 |
| 3 | İzmir | 200 | 180 | 210 | 590 |
| 4 | Bursa | 90 | 110 | 95 | 295 |
Şehir SatışExcelDepo v1.0.0
3. Preserve ile Preserve olmadan farkı
Makro 5 elemanlı bir Long dizisi oluşturup ilk elemana 10 değerini verir. Sonra diziyi önce ReDim Preserve ile, ardından Preserve olmadan büyütür ve her adımda üst sınırı ile ilk elemanı sayfaya yazar. Kodu standart modüle yapıştırın.
VBA
25 satır
Option Explicit
Sub PreserveFarki()
Dim a() As Long
Dim ws As Worksheet
Set ws = ActiveSheet
' 1. adim: ilk dizi
ReDim a(1 To 5)
a(1) = 10
a(2) = 20
ws.Cells(2, 2).Value = UBound(a)
ws.Cells(2, 3).Value = a(1)
' 2. adim: Preserve ile buyutme - degerler korunur
ReDim Preserve a(1 To 8)
ws.Cells(3, 2).Value = UBound(a)
ws.Cells(3, 3).Value = a(1)
' 3. adim: Preserve olmadan buyutme - degerler sifirlanir
ReDim a(1 To 12)
ws.Cells(4, 2).Value = UBound(a)
ws.Cells(4, 3).Value = a(1)
End Sub
Redim
Formülünü incelemek için bir hücre seçin.| A | B | C | |
|---|---|---|---|
| 1 | Adım | Üst Sınır | İlk Eleman |
| 2 | İlk dizi | 5 | 10 |
| 3 | Preserve ile büyütme | 8 | 10 |
| 4 | Preserve olmadan büyütme | 12 | 0 |
Dizi TestiExcelDepo v1.0.0
Kullanırken dikkat edin
- Preserve unutulursa veri kaybolur: Döngüde diziyi büyütürken Preserve sözcüğünü yazmayı unutmak en sık yapılan hatadır. Kod hata vermez, ama her seferinde dizi sıfırlanır ve yalnızca son eleman dolu kalır.
- Sabit boyutlu diziye ReDim uygulanmaz: Dim a(1 To 5) gibi boyutu bildirimde verilmiş bir dizi sabittir; ReDim uygulanırsa derleme hatası oluşur. Boyutu sonradan değiştirmek istiyorsanız diziyi Dim a() biçiminde bildirin.
- Çok boyutlu dizilerde yalnız son boyut: ReDim Preserve ile yalnızca son boyutun üst sınırı değişebilir. Satır sayısı sonradan artacaksa veriyi (sütun, satır) düzeninde tutup satırı son boyut yapmak ya da diziyi baştan boyutlandırıp kopyalamak gerekir.
- Veri türü ve performans: ReDim ile Dim'deki veri türü değiştirilemez; yalnız Variant değişkenlerde farklı tür atanabilir. Her ReDim Preserve dizinin kopyalanmasına yol açtığı için on binlerce elemanlık döngülerde diziyi önce büyük açıp sonunda küçültmek ya da bir seferde Range.Value ile dizi almak daha hızlıdır.
- Dizinin boyutlanıp boyutlanmadığını denetleme: Hiç ReDim uygulanmamış dinamik dizide UBound çağrılırsa 'Subscript out of range' hatası alırsınız. Bu yüzden eleman eklemeden önce bir sayaç tutmak ya da hata denetimi yapmak iyi bir uygulamadır.
- İlgili konular: Dim deyimi, Erase deyimi, Static deyimi, Option Base, UBound ve LBound işlevleri, Array ve Split işlevleri, Range.Value ile dizi okuma, For...Next döngüsü.