Worksheet
Excel Nesne Modelinde Workbooktan sonraki seviyede sayfalar gelir. Excelde 4 tip sayfa vardır. Bunlar;
- Çalışma sayfası(Worksheet:En çok bunları kullanacağız)
 - Chart Sheet(Başlı başına bir sayfa olan grafik sayfaları)
 - Macro Sheet(Bildiğimiz makro değil, eskiyle uyumluluk adına duruyor, biz bunlara hiç girmeyeceğiz)
 - Dialog Sheet(Eskiyle uyum adına duruyor, bunlara da girmeyeceğiz)
 
                        Biz en çok Sheet ve Worksheet nesnelerini kullanacağız. Yukardaki 4 maddeden anlaşıldığı üzere Worksheet nesnesi, Sheet nesnesinin bir alt türü oluyor. Sheet nesnesi, Sheets koleksiyonunun, Worksheet nesnesi de hem Worksheets koleksiyonunun hem de Sheets koleksiyonunun bir üyesidir. Bu koleksiyonlar bir dosyadaki tüm sayfaları ifade eder ve genelde döngülerde (Döngü konusunu hiç bilmiyorsanız en azından bir For Next için buraya bakıp tekrar gelin), veya toplam sayfa adedini saydırma gibi özelliklerle birlikte kullanılır. Diyelim ki dosyamızda 3 çalışma sayfası bir de grafik sayfası varsa Sheets.Count 4 sonucunu döndürürken Worksheets.Count 3 sonucunu döndürür.
                       
 Bunu kendiniz de deneyebilrisinz. Yukardaki özelliklerde bir dosya hazırlayın ve VBE'de şu kodları çalışıtırın
                    
                            
                                        Debug.Print ActiveWorkbook.Sheets.Count
                                        Debug.Print ActiveWorkbook.Worksheets.Count
                            
                        
                    Not:Biz birçok yerde Sheets ve Worksheets'i birbiri yerine kullanacağız.
Sayfalara erişim ve referans
                        Sayfalar bir koleksiyon üyesi oldukları için onlara koleksiyonun item özelliği ve bu özelliğin index numarası ile ulaşabiliriz. Item özelliği koleksiyonların default özelliği olduğu için tüm diğer koleksiyonlarda olduğu gibi bunda da yazılmadan es geçilebilir.
                        
Yani Worksheets.Item(1) ile Worksheets(1) tamamen özdeştir. Keza Workbooks.Item(1).Sheets.Item(2) ile Workbooks(1).Sheets(2) de özdeştir. Gördüğünüz üzere başka bir Workbooktaki bir sayfaya da Workbook ile sayfa arasına nokta koyarak ulaşıyoruz. Koleksiyonlarda indexler 1'den başlar(En soldaki sayfanın index değeri 1'dir.)
                        
Sayfalara index numarasıyla olduğu gibi sayfa adı ile de, Worksheets("ilksayfa") gibi, ulaşabiliriz.
                        
Mevcutta aktif olan sayfaya da ActiveSheet ifadesi ile ulaşırız. Activesheetle ilgili detaylara aşağıda değineceğiz.
                    
Seçme ve Aktive etme
                        Range nesnesinde nasıl bir veya birden çok hücreyi seçmek için Select metodu kullanılıyorsa sayfalar için de aynı metod kullanılır. Yine Range'te olduğu gibi tek bir hücreyi aktive etmek için Activate metodu kullanılıyordu, burda da yine aynı metod tek bir sayfayı aktive etmek için kullanılır.
                        
Aşağıdaki kod ile tüm sayfalarda dolaşıyor ve her sayfanın ilk hücresine artan bir şekilde sıra numarası yazıyorum.
                    
                            
                                For Each ws In ActiveWorkbook.Worksheets
                                    ws.Select
                                    Range("A1").Value=i
                                    i=i+1
                                Next
                            
                        
                     Activate gizli olan sayfaların seçimi için de kullanılabilirken, Select ile gizli sayfalar seçilemez. Mesela şimdi bi dosya açın, 5 sayfası olsun, 2.sini gizleyin. Sonra aşağıdaki kodu çalıştırın.
                        
                                Sub gizlisec_activateli()
                                Dim ws As Worksheet ' bu sefer ws'yi Worksheet olarak tanımladım
                                For Each ws In ActiveWorkbook.Sheets
                                    ws.Activate
                                    Range("a1") = ws.Index
                                Next
                                End Sub
                            
                        
                    Bu kod ile tüm sayfalarda A1 hücresinin dolu olduğunu görürsünüz, 2.sayfayı unhide edip kontrol edebilirsiniz.
                        
                                Sub gizliyisec1()
                                Dim ws As Worksheet
                                For Each ws In ActiveWorkbook.Sheets
                                    ws.Select 'gizli olduğu için hata verir
                                    Range("a1") = ws.Index
                                Next
                                End Sub
                            
                        
                    Bu yukardakini "sayfa visible mı?" diye kontrol ederek de yapalım, bu sefer hata almayız.
                        
                                Sub gizliyisec2()
                                Dim ws As Worksheet
                                For Each ws In ActiveWorkbook.Sheets
                                    If ws.Visible then 
                                      Range("a1") = ws.Index
                                       ws.Select
                                    End If
                                Next
                                End Sub
                            
                        
                    İsimlendirme
Name özelliği ile sayfanın ismini elde eder veya onu değiştiririz. Yani hem okunan hem yazılan(sets and returns) bir özelliktir. Index ise değiştirilemez bir özellik olup sadece okunurdur.
                        
                               ws.Name="Yeni sayfa"
                            
                        
                    Yeni sayfa açma(ekleme) ve silme
                        Yeni sayfa açmak/eklemek için Add metodu kullanılır.
                        
Syntax:Worksheets.Add(Konum) Konum belirtmezsek aktif sayfanın soluna ekler. Konum belirtmek için parametreleriyle birlikte kullanırız. Worksheets.Add Before:=Worksheets("Sheet3")
                        
 Sayfayı yaratırken aynı anda ismini de verebiliriz.
                    
                        
                               Worksheets.Add(Before:=Worksheets("Sheet2")).Name = "Yeni Sayfa"
                            
                        
                    Sayfaları silmek için Delete metodunu kullanırız.
                        
                               Worksheets(1).Delete
                            
                        
                    Silme işlemlerinde Excel bize uyarı çıkarır, silmek istediğimizden emin miyiz diye. Bu tür uyarılar bazen uzun makrolarda sorun çıkarabilir, hele bir de bilgisayarımızın başında değilkenki bir saate ayarlanmış bir kod ise biz gelip müdahale edene kadar ekranın takılı kalmasına neden olur, ve varsa sonrasında ayarlanmış kodların da çalışmasını engellemiş our. Bu tür durumlarla karşılaşmamak için kodların başına Application.DisplayAlerts=False cümleciği yazılır, ilgili kodlar bittikten sonra da True'ya çevrilir. Bunun detaylarına Application konusunda tekrar geleceğiz.
Sayfaları Gizleme ve Gizleneni tekrar gösterme
Sayfaları gizlemek veya tekrar göstermek için beklenenin aksine bir eylem değil Visible adında bir özellik kullanıyoruz. Bu özellik booelan tipinde değer döndürür.
                        
                               Worksheets("Sheet2").Visible = False/True
                            
                        
                    Bir diğer yöntem de bu özelliğe True/False atamak yerine XlSheetVisibility enumerationlarını kullanmak olabilir. Alacağı değerle şöyledir.
- xlSheetVisible:Sayfayı gösterir
 - xlSheetHidden:Sayfayı gizler
 - xlSheetVeryHidden:Sayfayı öyle bir gizler ki, kullanıcılar sayfalara sağ tıklayıp Unhide tuşuna bastıklarında bile gizli sayfa listesinde görünmez. Bunu nerede kullanmak isteyebilirsiniz? Mesela workbook/worksheet koruma şifrenizi veya bir veritabanı bağlantısı için yazdığnız Connection String içindeki bağlantı parolasını VBA kodu içine doğrudan yazmak istemiyorsunuzdur. Bunu bir xlVeryHidden nitelikli sayafanın bir hücresine yazıp buradan okutturabilirsiniz.
 
Bu konuyla ilgili örnekler için tıklayınız.
Taşıma ve Kopyalama
Move ve Copy metodularını kullanırız. İkisi de Before(Önce) ve After(Sonra) olmak üzere iki parametre alır.
                            code class="CodeMirror-activeline-background" data-lang="javascript">
                                    Worksheets("Sheet3").Move After:=Worksheets("Sheet1")
                                    Worksheets("Sheet3").Copy Before:=Worksheets("Sheet1")
                                    Worksheets("Sheet1").Copy Before:=Workbooks("ExcelVBA.xlsm").Sheets("Sheet3")
                                    Worksheets("Sheet1").Copy 'yeni bir dosya açıp ve direkt bu dosyaya kopayalar
                            
                        
                    
                        Bu metodları tek başına kullandığınızda yeni bir dosya açar ve oraya taşır/kopyalar. Aşağıdaki şu örnekte bu özelliği kullanıyoruz.
                        
Birkaç kopyalama ve taşıma örneğini macro recorder ile kendiniz de yapabilirsiniz. Basit bir konu olduğu için daha fazla detaya gerek görmedim.
                    
Sayfalarda koruma (Protection & Unprotection)
                        Yazdığımız kodlar, Sayfa korumalı bir dosyada işlem yapmaya kalkarsa şöyle bir hata alırız: "Run-time error '1004': Application-defined or object-defined error".
                        
Bu sorunun üstesinden gelmek için, öncesinde sayfanın korumalı olup olmadığını kontrol edebilir, varsa korumayı kaldırabiliriz. Ama bunun da bir sakıncası olabilir, o da şu ki, kodlarda ilerlerken başka bir hata çıkarsa program durur ve sayfamız korumasız kalır. Bunun için bir de Hata Yakalama kodu yazmamız ve ilgili yerde tekrar koruma koymamız gerekir.
                        
Korumaya almak Protect, korumayı kaldırmak Unprotect metodu ile sağlanır.
                        
Şimdi bir örnek yapalım. Yeni bi dosya açın ve ilk sayfasına koruma uygulayın, şifresi de 1234 olsun. Sonra da şu kodu ekleyip çalıştırın.
                    
                            
                                    Sub sayfakoruma1()
                                    Dim ws As Worksheet
                                    Set ws = ActiveSheet
                                    If ws.ProtectContents = True Then 'koruma var mı diye sorguluyoruz
                                       ws.Unprotect Password:="1234"
                                    End If
                                    'On Error GoTo hatayakala 'herhangi bir hatada sayfayı tekrar korumaya almak için ilgili yönlendirmeyi yapıyoruz
                                    Range("A1") = Environ("USERNAME")
                                    'çeşitli işlemler
                                    '0'a bölme olacak ve hata alacak
                                    a = InputBox("Bir sayı girin")
                                    b = InputBox("Bu sayıyı kaça bölelim")
                                    MsgBox "Sonuç: " & a / b
                                    ws.Protect Password:="1234"
                                    Exit Sub
                                    'hatayakala:
                                    'ws.Protect Password:="1234"
                                    End Sub
                            
                        
                    
                        İlk olarak, a için abc değerini girin, b için bir sayı girin. İkinci denemede de b için 0 değerini girin. İlki sayısal bir değer girmediğmiz için, ikincisi de 0'a bölmeye çalıştığı için hataya neden olacaktır. Hata yakalama kodları commentli olduğu için de dosyamız protectionsız kalacaktır.
                        
Şimdi yukardaki commentli kısımları commentsiz hale getirip tekrar çalıştıralım. Bu sefer hata yakalanacak ve çıkmadan önce tekrar şifreleme yapılacaktır.
                        
NOT:Filtrelemeye izin verme gibi seçeneklerden faydalanmak icin makro kaydetme aracından faydalanabilirsiniz. Ancak bu şekilde protection koymaya çalıştığınızda recorder şifreyi kaydetmez, bunu manuel eklemeniz gerekir.
                    
Protectionlı sayfalara devam
                        Yukarda korumalı sayfalarda çalışma şeklini görmüştük. Korumalı sayfalarla çalışmanın daha şık bir yolu var aslında. UserInterFaceOnly parametresi.
                       
 Bu parametreye True değeri atanırsa, sayfa sadece kullanıcı işlemlerine karşı korumalı olur, VBA kodları için koruma geçersiz olur. Gördüğünüz gibi Microsoft'taki abiler bunu da düşünmüşler. Bu parametrenin default değeri False olup değer atanmaması durumunda tahmin edeceğiniz üzere full koruma sağlanır.
                       
 Yanlız unutulmamalıdır ki, bu argüman sadece bir kereliğine koruma sağlar. Dosyayı kapatıp tekrar girdiğinizde, full korumalı açılır. Bu özelliğin daimi olması için Workbook_Open eventi içine uygun kod yazılabilir.
                    
                                
                                    ActiveWorkbook.Worksheets("calculatedlar").Sort.SortFields.Clear
                                    ActiveWorkbook.Worksheets("calculatedlar").Sort.SortFields.Add Key:=Range( _
                                            "F2"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
                                            xlSortNormal
                                    With ActiveWorkbook.Worksheets("calculatedlar").Sort
                                            .SetRange Range("A2:F175")
                                            .Header = xlNo
                                            .MatchCase = False
                                            .Orientation = xlTopToBottom
                                            .SortMethod = xlPinYin
                                            .Apply
                                    End With
                                
                            
                    Recorder'ın ürettiği kodda bir iki yeri değiştirmek gerekir, böylece makromuz daha dinamik hale gelir.
- Worksheets("calculatedlar")>ActiveSheet yapalım
 - Key:=Range("F2")>Key:=ActiveCell(veya duruma göre kalabilir)
 - Range("A2:F175")>Bunu nasıl değiştireceğimizi Range konusunda görmüştük
 
Keza filtreleme işleminin kodu da basit olup, dinamik hale getirilecek kısımları değiştirmek yeterlidir.
                        
                                    Range("B1").Select
                                    ActiveSheet.Range("$A$1:$F$175").AutoFilter Field:=2, Criteria1:="Şube"
                                
                            
                    Bu örnekte Range("$A$1:$F$175") yerine Range("A1").CurrentRegion denilebilir. Görüğünüz gibi Sort işleminde başlık hariç tutulurken burada başlık satırı dahildir. O yüzden Resize ve Offset kullanmadan işimizi halledebiliriz.
Filtre modları ve filtreyi kaldırma
                        Filtrelerle ilgili olarak kafa karışıklığına neden olabilecek iki konur var. Filtrenin açık/kapalı olması ile kriterin uygulanıp/uygulanmamış olması. Bunlardan ilki AutoFilterMode özelliği ile elde edilirken ikincisi FilterMode  özelliği ile elde edilir.
                        
Filtreyi uygulamak/kaldırmak Range nesnesinin AutoFilter metodu ile olur.
                    
- Filtre henüz yokken kullanılırsa filre uygulanır
 - Yanında parametre yoksa sadece filtre okları görünür
 - Parametreyle uygulanırsa direkt ilgili filtreleme yapılmış olur
 - Filtre varken kullanılırsa kriterler silinir ve filtre okları kalkar
 
                        Kriter uygulanmış bir data kümesinde kriterleri silmek ama filtre oklarını açık bırakmak için Worksheet nesnesinin ShowAllData metodu kullanılır.
                        
Aşağıda bütün bu durumları anlatan güzel bir örnek var. Bu örnekte sayfadaki data kümesinin rasgele olarak 4 durumundan birine girmesini sağlıyoruz, sonra hangi durumdaysa onunla ilgili bir mesaj veriyorum.
                    
                        
                                    Sub filtresub()
                                    a = WorksheetFunction.RandBetween(1, 4)
                                    MsgBox "Case " & a & " gerçekleşecek"
                                    Select Case a
                                        Case 1 'o an kapalıysa kapalı kalmaya devam, açıksa kapanır
                                            ActiveSheet.AutoFilterMode = False 'buna sadece false atanıyor, true atanamaz
                                        Case 2 'açıkken filtre konursa kapanır
                                            If ActiveSheet.AutoFilterMode = True Then Selection.AutoFilter
                                        Case 3 'kapalıyken filtre konursa açılır
                                            If ActiveSheet.AutoFilterMode = False Then Selection.AutoFilter
                                        Case 4 'filtre okları aktif olsa da olmasa da burası çalışır
                                            ActiveSheet.Range("$A$1").CurrentRegion.AutoFilter Field:=2, Criteria1:=Range("b2")
                                    End Select
                                    If ActiveSheet.AutoFilterMode = True Then 'filtre okları açıksa. Case 3 veya 4
                                        If ActiveSheet.FilterMode = False Then
                                            MsgBox "Case 3:Filtre açık ama kriter yok"
                                        Else
                                            MsgBox "Case 4:filtre açık ve kriter var, şimdi kriter kaldırılacak, ama filtre açık kalacak"
                                            ActiveSheet.ShowAllData
                                        End If
                                    Else 'filtre okları yoksa, yani henüz bir autofilter düğmesine basılmamışsa
                                        MsgBox "Case 1 veya 2:filtre yok"
                                    End If     
                                    End Sub
                                
                            
                    Sayfa ayarları
Page Setup, Print v.b işlemleri için macro recorderdan faydalanmanızı öneriyorum.
Calculation
Calculation konusuna Application nesnesine detaylıca değiniyoruz. Önemli bir metod olup Application konusunda mutlaka incelemenizi tavsiye ediyorum.
Sayfalarda gezinme
Sayfalarda dolaşma işini yukarıdaki birçok örnekte gördüğümüz gibi bir döngü aracılığı ile yapabilmekle birlikte, sadece bir sayfa geri veya ileri gitme işini, sayfa adı v.s yazmadan kolayca yapmamızı sağlayan iki özellik var.
                            
                                Activesheet.Next.Select ' sonraki sayfa
                                ActiveSheet.Previous.Select ' önceki sayfa
                            
                        
                    Hafızadan birşey yapıştırma
Hafızadaki(Clipboard) bilgiyi aktif sayfadaki aktif hücreye yapıştırmak için iki metod var. Birincisi Worksheet sınıfının normal Paste metdou, ikincisi Range nesnesinin PasteSpecial metodu. Worksheet.Paste metodu ile Excel arayüzünde yaptığımız gibi içerikte ne varsa yapıştırılır:Veri, formül, format v.s. Range.PasteSpecial ile ise yine Excel arayüzde yaptığımız özel yapıştırma türlerini yapabiliyoruz. Sadece değerleri, sadece formatı v.s.
                        
Aşağıdaki kod ile 1.sayfada aktif hücrenin CurrentRegion'ındaki hücreleri 2.sayfadaki aktif hücreye yapıştırıyoruz.
                    
                        
                                Sheets(1).Select
                                ActiveCell.CurrentRegion.Select
                                Selection.Copy
                                Sheets(2).Select
                                ActiveSheet.Paste
                            
                        
                    Bu arada Worksheet sınıfının da PasteSpecial metodu var ama biz onu çok kullanmayacağız, zira bununla Grafik gibi nesneleri veya Access gibi diğer uygulamalardan birşeyler yapıştırabiliyorsunuz.
                        
                                ActiveChart.ChartArea.Copy
                                Range("M2").Select
                                ActiveSheet.PasteSpecial Format:="Picture (PNG)", Link:=False, _
                                DisplayAsIcon:=False
                            
                        
                    Aşağıdaki örneği de MSDN'den aldım, burada diğer format seçeneklerine de bakabilirsiniz. Başka programlarla çalışmayacaksanız çok sık ihtiyacınız olacağını sanmam.
                        
                                Worksheets("Sheet1").Range("F5").PasteSpecial _ 
                                 Format:="Picture (Enhanced Metafile)", Link:=False,
                                 DisplayAsIcon:=False
                            
                        
                    Parent özelliği
Bazen bir sayfanın hangi workbookta olduğunu elde etmek isteriz. Bunun için hiyerarşide bir üst basamağa çıkmamızı sağlayan Parent özelliğini kullanırız.>
                            
                                Debug.Print TypeName(Activesheet.Parent) 'Workbook
                                Debug.Print Activesheet.Parent.Name 'ilg
                            
                        
                    Tüm sayfaları ayrı workbooklar olarak kaydetme
Bu örnekte açık olan bir dosyadaki tüm sayfaları ayrı ayrı dosyalar olarak seçilen bir klasöre kaydediyoruz.
                            
                                Sub sayfaları_wb_olarak_kaydet()
                                    Dim ws As Worksheet
                                    Dim wb As Workbook
                                    Dim fd As FileDialog
                                    Dim klasör As String
                                    Dim dosya As String
                                    On Error GoTo hata
                                    Application.ScreenUpdating = False
                                    Set wb = Application.ThisWorkbook
                                    Set fd = Application.FileDialog(msoFileDialogFolderPicker)
                                    If fd.Show = True Then
                                       klasör = fd.SelectedItems(1)
                                    Else
                                       Exit Sub
                                    End If
                                    For Each ws In wb.Worksheets
                                       ws.Copy
                                       'Burada bi versiyon kontrolü yapılmasında fayda var, ama örneği basitleştirmek adına onu es geçiyorum ve default formatta kaydetmesine izin veriyorum
                                       dosya = klasör & "\" & Application.ActiveWorkbook.Sheets(1).Name & ".xlsx"
                                       ActiveWorkbook.SaveAs dosya
                                       ActiveWorkbook.Close False
                                    Next
                                    Call Shell("explorer.exe " & klasör, vbNormalFocus)
                                    Application.ScreenUpdating = True
                                    Exit Sub
                                    hata:
                                    Application.ScreenUpdating = True
                                    MsgBox Err.Description
                                    End Sub
                            
                        
                    Tüm sayfaları Unhide etme
Bu örnekte tüm gizli sayfaları açıyoruz. Buna QuickAccessBardan erişmek isteyebilirsiniz, ben öyle yapıyorum açıkçası.
                            
                                Sub tümsayfalarunhide()
                                  For i = 1 To Sheets.Count
                                     Sheets(i).visible = True
                                  Next i
                                  Sheets(1).Select
                                End Sub
                            
                        
                    İlk sayfa hariç tümünü hide etme
Diyelim ki bir sayfasında Karne, diğer sayfalarında bu karneyi besleyen sayfaların olduğu bir dosyanız var. Sık sık sayfaları Unhide ve tekrar Hide etme ihtiyacınız oluyor. Bir üstteki kod ile tüm sayfaları Unhide etmiştik. Datayla oynadıktan sonra şimdi tekrar gizleyeceğiz. Bunu da QuickAccessBara eklerseniz müthiş pratiklik sağlar. Bu kodu Karne sayfasındayken çalıştırmanız gerekiyor.
                        
                                Sub aktifhariç_hideall()
                                Dim ws As Worksheet
                                Set ws = ActiveSheet
                                For i = 1 To Sheets.Count
                                    If i <> ws.Index Then
                                        Sheets(i).visible = False
                                    End If
                                Next i
                                End Sub
                            
                        
                    Tüm sayfalarda ilk kolonda A'dan Z'ye sıralama
Diyelim ki size birçok sayfası olan bir dosya geldi. Ama sayfaların hiçbiri sıralı değil. Bu örnekte tüm sayfalarda A'dan Z'ye sıralama işlemini tek seferde yapıyoruz
                        
                               Sub tümsayfalarda_sırala()
                                    For i = 1 To Sheets.Count
                                        Sheets(i).Select
                                        ActiveWorkbook.Sheets(i).Sort.SortFields.Clear
                                        ActiveWorkbook.Sheets(i).Sort.SortFields.Add Key:=Range("A1"), _
                                            SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
                                        With ActiveWorkbook.Sheets(i).Sort
                                            .SetRange Range(Range("A2"), Range("a2").End(xlDown).End(xlToRight))
                                            .header = xlNo
                                            .MatchCase = False
                                            .Orientation = xlTopToBottom
                                            .SortMethod = xlPinYin
                                            .Apply
                                        End With
                                    Next i
                                End Sub