Excel Vba Forum - Excelce.Net
SORU ve CEVAPLAR (Yazılabilir) => Microsoft Excel, Vba, Makro, Formül vb. Soruları => Çözülen Excel, Vba, Makro, Formül vb. Soruları => Konuyu başlatan: Evolver - 30 Temmuz 2010, 16:31:57
-
Selamlar.
Dizi hakkında biraz bilgi ve örnek verebilir misiniz lütfen.
Aklıma takılan başlıca sorular şunlar. Cevaplandırırsanız memnun olurum;
1. dim dizi(.........) as ..............
yukarıdaki ifadede noktalı yerlere ne yazmalıyım?
2. araştırma yaparken aşağıdaki gibi değişik şekillere rastladım.
Bunların neden farklı olduğunu ve aralarındaki farkların ne olduğunu anlatırmısınız?
a) dim dizi(10)
b) dim dizi(0 to 10)
3. bazen dizilerin ikili yazıldığını gördüm. Bunun nedenini ve ne anlama geldiğinide yazabilir misiniz?
örnek: dim dizi(5,14)
4. diyelimki ikili dizi tanımlaması yapıldı (tabi sebebini bilmiyorum). Bu durumda birinci ve ikinci değerlere nasıl atama yapılacak?
5. Dizinin ilk değeri daima sıfırmıdır? İstesem 1 den yada 5den başlatamazmıyım?
-
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=0
Hakan 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 (http://www.excelvba.net/viewtopic.php?f=24&t=162&p=409#p409) makalesini anlayarak ve deneyerek okuyunuz, hazmediniz. Hazır başlamışken ListBox (http://www.excelvba.net/viewtopic.php?f=24&t=156) 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.
Uygulamalar
Bu 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.
(http://www.excelvba.net/forum/Diziler.JPG)
-
Dilerseniz yorumlamaya çalışın, yine takıldığınız yerler hakkında sorularınızı yazabilirsiniz.
merhaba
Bülent bey alakanızdan dolayı teşekkür ederim. hakan behcan beyde çok detaylı anlatmış bu vesileyle onunda ellerine sağlık diyorum
yukarıdaki cümlenizden destek alarak şu yeni sorularımı soracağım:
1. diziler variant değişkenlerdir bunu anladım, ama string olarak tanımlansa sorun olurmu. mesela "dim abc(10) as string" desek sorun çıkar mı?
2. "dim dizi(10)" ifadesiyle "dim dizi(1 to 10)" ifadesi arasında ki farkı anladım. sonuçta ikisinede 10 adet değer atayabiliriz ama birisinin ilk değer numarası 0 ilen diğerinin ilk değer numarası 1 den başlıyor. (yanılıyormuyum)
3. tek boyutlu dizilerde sorun yok. asıl birden fazla boyutu olan dizileri anlamakda zorlanıyorum.
elimizde "dim dizi(1 to 10, 1 to 10)" şeklinde bir ifade olsun. bu dizi tek boyutlu olsaydı en fazla 10 tane değer arayabilirdim. buraya kadar tamamda bu diziye en fazla kaç değer atanabilir (bana sorarsanız 10 x 10 = 100 adet değer atanabilir) yanılıyormuyum ??
saygılarımla.
-
Merhaba Erol Bey.
1-String olarak tanımlayıp çalıştırdım, sorun çıkmadı. Siz de deneyin isterseniz...
2-Haklısınız.
3-Haklısınız.
İyi çalışmalar.
-
merhaba
Bülent bey, herşey için çok teşekkür ederim. sağlıcakla kalın.
saygılar