Merhaba Erol Bey.
Konuyu Hakan Behcan arkadaşımız epey ayrıntılı olarak açıklamış, asıl konu linki ve alıntı aşağıdadır.
Dilerseniz yorumlamaya çalışın, yine takıldığınız yerler hakkında sorularınızı yazabilirsiniz.
http://www.excelvba.net/viewtopic.php?f=63&t=236&start=0Hakan Behcan - ExcelVba.Net - ExcelVba' da Diziler (Array) makalesi aşağıdadır:Diziler önemlidir. Dizileri kontrol etmeyi bilmek bize kodlamada ayrıcalık kazandırır.
Diziler neden önemlidir biraz araştıralım.
Dizi bir variant değişkendir. Ancak içinde binlerce değişken taşıyabilirsiniz. Ado ile çalışırken, excel userformlarında listbox ve comboboxlarla çalışırken, excel range ile çalışırken diziler bize hız ve beceri kazandırır. Nasıl kazandırdığına yazının sonuna doğru bakacağız. Önce bilseniz de bilmesenizde aslında pek anlamı olmayan terimleri inceleyeceğiz. Başka önemli bir özelliği de fonksiyonlarda ortaya çıkar. Tabi ki kullanırsak. Fonksiyonlara bir çok değer gönderebilir ancak tek bir değer geri alabiliyorduk. Eğer bu değer bir dizi ise demekki dizi ile bir çok değeri de geriye alabiiliriz. Bu kısmı pek anlamadı iseniz
Fonksiyonlar makalesini anlayarak ve deneyerek okuyunuz, hazmediniz. Hazır başlamışken
ListBox makalesini de okumanızı öneririm ki konuyla ilgilidir.
Gelelim Teorik Bilgiye:Diziler temel olarak Statik veya Dinamik türde olurlar.
Statik olanlar adı üzerinde başlangıçta boyutu ve eleman sayısı belirlenen ve sonradan değiştirilmeyen dizilerdir. dinamik olanlar ise başlangıçta boyut ve eleman sayısı belirtilmeyen ancak sonradan değiştirilebilen dizilerdir.
Eğer belirtmessek dizilerin boyut indeksi 0 dan başlar ve belirlediğiniz eleman sayısına kadar gider. Yani
Dim Dizim(10)
şeklindeki bir dizi tanımlamasının aslında 11 elemanı vardır.
Dizileri 0 dan değil de 1 den başlatmak istiyorsak deklerasyon kısmına
Option Base 1 yazarız.
Option Base 1
Sub DiziTanimi()
Dim dizim(10)
'..kodlarınız
End Sub
Dizilerimizi tanımlarken sınırlandırmamız da mümkündür. Aşağıdaki kodları inceleyiniz.
Sub DiziTanimi()
Dim Dizim(10)
Dim Dizim(0 To 10)
Dim Dizim(-10 To 10)
Dim Dizim(50 To 60)
End Sub
Peki boyut dedik nedir bu boyut.
Bir sınıfta 30 öğrenci var.
Sadece öğrencilerin adından bir dizi oluşturacak isek bu tek boyutlu bir dizi olur.
Dim OgrenciAdi(30)
Soyadlarını, ders notlarını falan da alacak isek o zaman boyut 2 ye çıkar.
Tek boyutlu dizileri dinamik olarak şu şekilde de atayabiliriz.
Sub Diziler()
Dim dizi() As Variant
dizi = Array("Hallederiz", "ExceLord", "ExelDelisi", "ExcelAns", "Codex")
MsgBox UBound(dizi)
'4 görüntülenir
MsgBox dizi(0)
'Hallederiz Görüntülenir
End Sub
Genellikle tek ve çift boyutlu dizileri kullanırız. 2 boyuttan fazla boyutlu diziler nerede kullanılır fikrim olmamakla birlikte bir örnek vereceğim.
Bir excel dosyasını düşünün
Tablo (sayfa, sheet) ler, ve tablolarda satır ve sütun adları olan hücreler var.
İlk boyuta Tablo, ikinci boyuta satır ve 3. boyuta da sütun numarasını verirsek tüm excel dosyasındaki değerleri bir diziye yükleyebiliriz.
Biz ilk 3 tablunun, 30 satır,10 sütununu diziye yükleyelim. 2. sayfanın 2 satır, 2 sütununa "Hallederiz" yazalım, siz dilediğinizi yazabilirsiniz.
Option Base 1
Sub Dizim()
Dim Tablo, Satir, Sutun As Integer
Dim Dizi(3, 30, 10)
For Tablo = 1 To 3
For Satir = 1 To 30
For Sutun = 1 To 10
Dizi(Tablo, Satir, Sutun) = Worksheets(Tablo).Cells(Satir, Sutun).Value
Next Sutun
Next Satir
Next Tablo
MsgBox Dizi(2, 2, 2)
End Sub
Evet gördüğünüz gibi neredeyse dosyayı bir 3 boyutlu bir diziye yükledik.
daha fazla da boyut tanımlamanız mümkündür.
Dim Dizi(10, 10, 10, 10, 10)
Çok boyutlu dizileri de sınırlandırmak mümkündür.
Dim Dizi(0 To 10, 5 To 10, -3 To 10, 8 To 88)
Ancak dediğim gibi benim asıl amacım çift boyutlu diziler.
Biraz da dinamik dizilere dönelim.
Bir diziyi Dim veya Redim ile tanımladığınızda elemanların taşıdığı değerler kaybolur. Bunun için Redim Preserve kullanmalıyız.
Dinamik dizileri tanımlarken
Sub DinamikDizi()
Dim dizim() As Variant
ReDim Dizi(0 To 10, 0 To 10)
End Sub
şeklinde başlangıçta boyut ve eleman sayısı belirtmeyiz.
Dizideki mevcut değerleri silmek istemiyorsak, yukarıda da bahsettiğimiz gibi
Sub DinamikDizi()
Dim dizim() As Variant
ReDim Preserve Dizi(0 To 10, 0 To 10)
End Sub
ReDim Preserve şeklinde kullanırız.
Burada önemli bir noktadan bahsetmek istiyorum.Bir değişkendeki değere göre dizi boyutu belirlemek istiyorsanız bunu Statik dizilerde yapamassınız.
Sub DiziElemean()
Dim ElemanSayisi As Integer
ElemanSayisi = 12
Dim dizi(ElemanSayisi)
End Sub
kodları size hata üretir.
Bu durumda mecburen dinamik dizi kullanacaksınız.
Sub DiziElemean()
Dim ElemanSayisi As Integer
Dim Dizi() As Variant
ElemanSayisi = 12
ReDim Dizi(ElemanSayisi)
End Sub
bu kodlar ise çalışacaktır.
Dizinin sınırlarını belirledik, ya da elimizde bir dizi var bu dizinin boyutlarındaki elemanların ilk ve son indekslerini (sıra numaralarını) bilmiyoruz. Bu dizi nereden başlar, nereye kadar gider öğrenemeyecek miyiz. Amcalar bunu düşünerek
LBound ve
UBound komutlarını geliştirmişler.
O halde, bir dizinin alt sınırını LBound fonksiyonu, üst sınırını da UBound fonksiyonu ile tespit edebiliriz.
Tek boyutlu bir dizide alt ve üst sınırı
Sub DiziSinir()
Dim Dizi(30) As Variant
MsgBox "AltSınır:" & LBound(Dizi) & vbNewLine & "ÜstSınır:" & UBound(Dizi)
End Sub
'Altsınır:0 ÜstSınır:30 görüntülenir.
şeklinde kod yazarak bulabiliriz.
Çok boyutlu bir dizide ise
LBound(Dizi,BoyutIndeksi) veya LBound(Dizi,BoyutIndeksi) şeklinde yazarak bulabiliriz.
Sub DiziSinir()
Dim Dizi(30, -15 To 20) As Variant
MsgBox "AltSınır:" & LBound(Dizi, 2) & vbNewLine & "ÜstSınır:" & UBound(Dizi, 2)
'AltSınır:-15 ÜstSınır:20 görüntülenecektir.
End Sub
Böyle bir yapıyı nerede kullanabiliriz.
Bir dizinin tüm elemanlarına veya baştan 5 elemanına, sondan 2 elemanına vs işlem yapacağımız zaman döngülerde sıklıkla kullanırız. Hele fonksiyonlara bir dizi gönderiyorsak, ayrıca dizinin boyutlarını göndermeden işlemi
Hallederiz.
Aşağıdaki kodda dizinin tüm elemanlarına ExcelVba.Net ekleyen bir kod mevcut.
Sub Dizi()
Dim Dizi(10 To 30) As Variant
Dim Sira As Long
For Sira = LBound(Dizi) To UBound(Dizi)
Dizi(Sira) = Dizi(Sira) & "ExcelVba.Net"
Next Sira
End Sub
İşin hikaye kısmı bitti. Gelelim dizilerin bize excelde hız ve beceri kazandıracak uygulamalarına. Hep diziler anlatılır ama hikayesi anlatılır. Bu kısımda ise meyveleri anlatılacaktır.
Eğer yazının öncesini okumadı iseniz bu kısmını mutlaka okuyunuz.UygulamalarBu kısımda özellikle çift boyulu dizileri kullanacağız. Aslında excelde kullandığımız ama dizi olduğunun farkında olmadığımız yapılar mevcut.
Uygun türdeki değişkenleri birbirine doğrudan atama yapabiliriz. Zaten bu yazının da can alıcı noktası, size kazandıracağı bu noktadadır.
Benim bildiğim dizi yapıları;
- Bir alanın (rangenin) value özelliği iki boyutlu bir dizidir. İlk Boyut satırları, ikinci boyut ise sütunlarıdır.
- Bir ListBoxun veya ComboBoxun List özelliği iki boyutlu bir dizidir. İlk boyutu satırı, ikinci boyutu sütunu ifade eder.
- Bir ListBoxun veya ComboBoxun Column özelliği iki boyutlu bir dizidir. İlk boyutu sütunu, ikinci boyutu ise satırı ifade eder.
- Bir Ado Kayıtsetinin Getrows özelliği iki boyutlu dizidir. İlk Boyut kayıtları, ikinci boyutu alanları ifade eder.
Bunları kullanıp görelim. Hepsi aynı türde olduğuna göre birbirlerine atama yapalım.
Yazının sonunda örnek dosyamız olacak. Onu indirirseniz deneyerek çalışma imkanınız olur.
Bir alandaki deki verileri doğrudan bir listboxa, comboboxa ya da diziye yükleyebiliriz.
Örneklere geçelim.
Sayfa1 de
A:G sütunlarında 30 satır veri var.
ListBox1 ve ComboBox1 adında da iki nesnemiz var.
Diğerleri de butonlar.
Bir alandan (range) ListBoxa veya ComboBoxa
Private Sub CommandButtonRngToLb_Click()
Dim SonSatir As Long
Dim Rng As Range
SonSatir = Worksheets(1).Range("A65536").End(xlUp).Row
Set Rng = Worksheets(1).Range("A2:G" & SonSatir)
Me.ListBox1.ColumnCount = UBound(Rng.Value, 2) ' Sütun Sayısı
Me.ListBox1.List = Rng.Value
Set Rng = Nothing
End Sub
koldarı ile doğrudan veriyi yükleyebiliriz.
Alandaki sütun sayısını özellikle UBound ile buldum, hani diyorduk ya alanın value özelliği bir dizidir diye. Madem ki dizi UBound kullanabiliriz. +1 i de diziler 0 dan başlıyordu, onu telafi etmek için kullandık.
İki boyulu dizilerde satır sütun yer değiştirmek için
Application.Transpose(Dizi)
excel fonksiyonunu kullanırız.
o şekilde alandaki veriyi tersleyip listboxa yüklemek için
Private Sub CommandButtonRngToLBTr_Click()
Dim SonSatir As Long
Dim Rng As Range
SonSatir = Worksheets(1).Range("A65536").End(xlUp).Row
Set Rng = Worksheets(1).Range("A2:G" & SonSatir)
Me.ListBox1.ColumnCount = UBound(Rng.Value, 1) ' Sütun Sayısı
Me.ListBox1.List = Application.WorksheetFunction.Transpose(Rng.Value)
Set Rng = Nothing
End Sub
yazarız.
Dikkat ederseniz, kodlarda satır ve sütun sayılarını ayarlamak için kodlar var, asıl işi yapan sadece tek bir satırdır.
Column ve List özelliklerini kullanarak ListBoxun veya Comboxun Satır ve sütunlarını sadece iki satır kod ile yer değiştirebiliriz.
Private Sub CommandButtonLBTersle_Click()
Me.ListBox1.ColumnCount = UBound(Me.ListBox1.List, 1) + 1
Me.ListBox1.Column = Me.ListBox1.List
End Sub
Application.Transpose kullanarak da satır ve sütunları yer değiştirebiliriz.
Private Sub CommandButtonLbTersle2_Click()
Me.ListBox1.ColumnCount = UBound(Me.ListBox1.List, 1) + 1
Me.ListBox1.Column = Application.WorksheetFunction.Transpose(Me.ListBox1.Column)
End Sub
Bir listbox veya comboboxdaki veriyi bir diğerine aktarabiliriz.
Private Sub CommandButtonLBtoCbox_Click()
Me.ComboBox1.ColumnCount = UBound(Me.ListBox1.List, 1) + 1
Me.ComboBox1.List = Me.ListBox1.List
Me.ComboBox1.ListIndex = 1
End Sub
Bir listbox veya comboboxtaki veriyi bir alana (range) doğrudan aktarabiliriz.
Private Sub CommandButtonLBtoSyf_Click()
Dim SatirSayisi As Integer
Dim SutunSayisi As Integer
'önce temizlik
Worksheets(2).UsedRange.Clear
SatirSayisi = UBound(ListBox1.List, 1)
SutunSayisi = UBound(ListBox1.List, 2)
Worksheets(2).Range(Cells(4, 4), Cells(4 + SatirSayisi, 4 + SutunSayisi)).Value = ListBox1.List
Columns("A:IV").EntireColumn.AutoFit
End Sub
Bir comboboxtaki veriyi önce diziye oradan da listboxa atalım.
Private Sub CommandButtonCbToDiziToLb_Click()
Dim Dizi As Variant
Dizi = Me.ComboBox1.List
Me.ListBox1.List = Dizi
End Sub
Kombinasyonları çoğaltmak mümkün. Örnek dosyada da değişik kombinasyonlar mevcut. Satır ve sütun sayılarını ayarladığınız sürece sorun yok. Bir kayıtsetini, listboxu, comboboxu ya da alanı dinamik bir diziye atıyorsanız satır ve sütun ayarlamamıza da gerek yoktur.
Bir diğer dizi özelliği olan nesne ise ADO kayıtsetinin Getrows özelliğidir.
Kayıtsetini açtınız
ListBox1.List=KayitSeti.Getrows
derseniz kayıtseti olduğu gibi listboxa yüklenir.
Ne kadar hızlı olduğun tahmin edemessiniz. Ancak deneyerek görürsünüz.
Benim sık kullandığım bir fonksyion var.
Private Function Liste(Sorgu As String) As Variant
Set KS = New ADODB.Recordset: Set Bagm = New ADODB.Connection
Bagm.Open "DRIVER={Microsoft Access Driver (*.mdb)};" & "DBQ=" & LabelYol.Caption' dosya yolu
Set KS = Bagm.Execute(Sorgu)
On Error GoTo err
If Not KS.EOF Then
Liste = KS.GetRows
Else
Liste = "Kayit Yok"
End If
err:
If err Then MsgBox "Bir Problem Oluştu! " & vbNewLine & "Hata:" & err.Description & vbNewLine & "Sorgunuz:" & Sorgu
Bagm.Close
Set KS = Nothing: Set Bagm = Nothing
End Function
Sub LBDoldur
Sorgu="Select*From Personel"
ListBox1.List=Liste(Sorgu)
Sorgunuzu gönderirsiniz ve Personel listesi listboxa yüklenir.
Tabi belirtmekte fayda var, KayıtSetinin GetRows kolleksiyonu salt okunurdur. Yani ona bu şekilde veri atayamaz, yalnızca alırsınız ki o bile muhteşemdir.
Ne additemle uğraştık ne list(satır sütun) lar ile
ListBox ve ComboBoxta başka bir yöntemle 10 sütundan fazla sütun görüntüleyemezsiniz.Diziler hakkında yazacaklarım şimdilik bu kadar. Aklıma gelen önemli püf noktaları olursa bu mesaja eklerim.
Dizileri daha etkin kullanmanız dileği ile.
Kalın sağlıcakla.
Hallederiz.