PivotTable, Slicer ve Chart nesneleriyle çalışmak

Giriş

Pivot(Özet) tablolarla çalışmaya başlamadan önce Excel tarafında konuya hakim olmak önemlidir. Buraya kadar geldiğinize göre konuyu bildiğinizi varsayıyorum ancak bilgilerinizi tazlemek isterseniz sizi şöyle alayım.

Baştan belirtmekte fayda var; Pivot tablo(bundan sonra PT diye anılacak) konusu VBA tarafında biraz alengirli bir hal alır, zira Excel önyüzde görmediğimiz bir nesneyle çalışmamız gerekmektedir. Bunun adı PivotCachedir. Onun dışında aslında recorder ile üreteceğiniz birkaç kodu elden geçirmekle kolaylıkla öğrenebileceğiniz bir konudur. O yüzden ben bu sayfada gereksiz yere recorderla elde edebileceğiniz detayları koymamaya karar verdim. Onun yerine refresh işlemleri, birkaç önemli işlem, birkaç event ve sonrasında da slicerlarla olan ilişkisini anlatmak istiyorum. Tabiki otomasyon projelerinizde data üretimi sonrasında kodun bir PT da üretmesi gerekiyorsa PT yaratmayı bilmeniz lazım ama dediğim gibi bunu recorderla çok rahat görebilirsiniz, gereksiz fazlalıkları atmak size kalıyor.

Size tavsiyem öncelikle birkaç işlemi(pivot oluşturma, filtre koyma, filtre kaldırma, repeat all items yapma v.s) recorder ile yapın ve kodu inceleyin. Yine de "ben recorderla uğraşamam" diyorsanız MSDN'den detay bilgi edinebilirsiniz. İngilizceniz yoksa ve pivot detaylarını yine de yazmamı isterseniz bu sayfanın altına yorum bırakın, uygun bir zamanda bunları da eklerim, ama dediğim gibi gerçekten burada anlatacaklarım dışında nerdeyse herşeyi recorderla kolaylıkla elde edebilirsiniz ve bunlarla ilgili olarak dikkat çekecek bir husus bulunmamaktadır.

Veri Seti

Üzerinde çalışacağımız data seti, Excel konularındaki örnek data setidir, buradan indirebilirsiniz.

Mesela aşağıda, bu dosyanın "calculatedlar" sayfasındaki dataya uyguladığımız PT'ın recorderla elde edilmiş kodu bulunuyor. Tabi bu kodu şu an çalıştırsanız sizde çalışmaz zira sayfa isimleri değişmiş olacak. Onun yerine kendiniz yeni bir recorder çalıştırıp görün derim.

                        
                                    Sub Macro1()
                                    '
                                    ' Macro1 Macro
                                    '
                                    '
                                        Sheets.Add
                                        ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
                                            "calculatedlar!R1C1:R175C6", Version:=6).CreatePivotTable TableDestination _
                                            :="Sheet1!R3C1", TableName:="PivotTable1", DefaultVersion:=6
                                        Sheets("Sheet1").Select
                                        Cells(3, 1).Select
                                        With ActiveSheet.PivotTables("PivotTable1")
                                            .ColumnGrand = True
                                            .HasAutoFormat = True
                                            .DisplayErrorString = False
                                            .DisplayNullString = True
                                            .EnableDrilldown = True
                                            .ErrorString = ""
                                            .MergeLabels = False
                                            .NullString = ""
                                            .PageFieldOrder = 2
                                            .PageFieldWrapCount = 0
                                            .PreserveFormatting = True
                                            .RowGrand = True
                                            .SaveData = True
                                            .PrintTitles = False
                                            .RepeatItemsOnEachPrintedPage = True
                                            .TotalsAnnotation = False
                                            .CompactRowIndent = 1
                                            .InGridDropZones = False
                                            .DisplayFieldCaptions = True
                                            .DisplayMemberPropertyTooltips = False
                                            .DisplayContextTooltips = True
                                            .ShowDrillIndicators = True
                                            .PrintDrillIndicators = False
                                            .AllowMultipleFilters = False
                                            .SortUsingCustomLists = True
                                            .FieldListSortAscending = False
                                            .ShowValuesRow = False
                                            .CalculatedMembersInFilters = False
                                            .RowAxisLayout xlCompactRow
                                        End With
                                        With ActiveSheet.PivotTables("PivotTable1").PivotCache
                                            .RefreshOnFileOpen = False
                                            .MissingItemsLimit = xlMissingItemsDefault
                                        End With
                                        ActiveSheet.PivotTables("PivotTable1").RepeatAllLabels xlRepeatLabels
                                        With ActiveSheet.PivotTables("PivotTable1").PivotFields("KANAL")
                                            .Orientation = xlRowField
                                            .Position = 1
                                        End With
                                        With ActiveSheet.PivotTables("PivotTable1").PivotFields("URUN")
                                            .Orientation = xlColumnField
                                            .Position = 1
                                        End With
                                        ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
                                            "PivotTable1").PivotFields("TUTAR"), "Sum of TUTAR", xlSum
                                    End Sub
                                                
                                            

Yukarıda da bahsettiğim gibi recorder kodunda gereksiz bir sürü kısım var, zira artık bildiğiniz üzere recorder bir nesneye ait tüm propertylere değer atıyor.

PivotCache nesnesi

Yukarıdaki koddan göreceğiniz üzere bir pivot table yaratılmadan önce PivotCache(Bundan sonra PC olarak anılacak) nesnesi yaratılıyor. PC, veri kaynağının bellekte özetlenmiş halidir . Her PT'ın arka planda dayandığı bir PC vardır. Neden böyle bir şeye ihtiyaç var diye sorabilirsiniz. PT'lar bence ve birçok kişi tarafından Excel'in en güçlü aracı olarak kabul edilir. Bunların gücü, birçok gruplama işini çok hızlı yapmasında yatıyor. İşte bu hız, bellekteki PC tarafından sağlanır, aksi halde her defasında veri kaynağına gitmek gerekseydi ki bu da hızın düşüşü anlamına gelecekti. İşte bu yüzden öncelikle PC yaratılır.

Excel 2007'den önce bir veri kaynağından üretilen her PT'ın ayrı bir PC'si olurdu, bu da bellek tüketimi için çok iyi olmazdı ve dosya boyutunu da gereksiz yere şişirirdi. Excel 2007 ile birlikte aynı kaynaktan üretilen PT'ların PC'si ortaklaştırıldı. Bununla beraber bazı durumlarda bunların PC'sini ayrıştırmak gerekebilir, bunu nasıl yapacağımızı aşağıda göreceğiz.

Rakamlarla örnek vermek gerekirse; 2007 öncesinde kaynak datanız 1 MB büyüklüğündeyse ve 3 PT yarattıysanız dosya boyutu 3 MB daha artıyordu. 2007 ve sonrasında sadece 1 MB artıyor. Bu 1 MB'dan da tasarruf etmek için "save source data" yapabilirsiniz.

Aşağıda benim üzerinde çalıştığım birkaç dosyanın boyutunu görebilirsiniz(Edit:Dosya adlarındaki baştaki "pivot"u görmezden gelin):

post-thumb

Daha detaylı analiz ettiğimizde;

  • Boş bir dosya 9 KB
  • Sadece kaynak datayı içerdiğinde 57 KB. Demekki datanın getirdiği net yük: 57-9=48 KB
  • Bu dosyada tek bir PT yaratınca boyut 79'a çıkıyor. Demekki, cache + pivot sayfasındaki özet data=79-48=31 KB(Gerçi özet alanında hiç veri koymasam da boyut yine 79, demek özet veri ihmal edilebilir)
  • 2. PT yaratınca boyut 79’dan 93’e çıkıyor. Bu da cache’den 14 KB. Bu da pivot alanı için 7 KB bir alan tanıyor demek.
  • 3. PT yaratınca boyut 93'ten 107'ye çıkıyor. Yani son PT'ya 14 KB daha tanımış oluyorum. Bu da son PT'nın cache ile ilgili olarak 14 KB'lık bir alana sahip olduğu anlamına geliyor.
  • Hepsi için toplamda 48+31+14+14=107

Yukarıda gördüğünüz üzere aslında data kaynağına gidip her seferinde veri almak yerine, bellekte bir PC tutarak, bunun üzerinden özetleme işlemlerini gerçekleştiriyor.

Sonuç olarak; Her PT için bir PC oluşturmak ve bunları eklemek gerekli. İşte bu yüzden kod içerisinde yukarıdaki gibi "PivotCaches.Create" ile PC yaratmak durumundayız.

Pivot Tabloların Oluşturulması

PT oluşturmak için yukarıda gördüğümüz kodu kullanabiliriz. Burada dikkat edilmesi gereken husus PivotCaches.Create metodu. Bunun dışında bazı propertiesler üzerinden de işlem yapmamız gerekebilir. Aşağıdaki gibi bir kod ile PT yaratılabilir.

                        
                                Sub PivotTableOlustur()
                                    Dim pc As PivotCache
                                    Dim pt As PivotTable
                                    Dim ws As Worksheet
                                    Dim wsData As Worksheet
                                    Set ws = Worksheets.Add
                                    Set wsData = Worksheets("calculatedlar")
                                    Set pc = ActiveWorkbook.PivotCaches.Create( _
                                        SourceType:=xlDatabase, _
                                        SourceData:=wsData.Range("A1:F175"))
                                    Set pt = pc.CreatePivotTable( _
                                        TableDestination:=ws.Range("A3"), _
                                        TableName:="PivotTable1")
                                End Sub
                                            
                                        

Yukarıdaki kodda dikkat edilmesi gereken nokta "SourceData" alanıdır. Burada yine belirtilen veri aralığına dikkat etmek önemlidir. Bu aralık dışında PT yaratmaya çalışırsanız hata alırsınız. O yüzden aralık kontrolü yapmak iyi bir yöntem olacaktır. Bu noktada birkaç tane error handling metodu kullanılabilir. Bunları aşağıda görmeye çalışacağız.

Aralık Kontrolü

Pivot tabloyu oluştururken belirli bir aralığın kontrolünü sağlamak gerekir. Bunun için aşağıdaki yöntem kullanılabilir:

                                                        
                                Sub PivotTableOlustur()
                                    On Error GoTo Hata
                                    Dim pc As PivotCache
                                    Dim pt As PivotTable
                                    Dim ws As Worksheet
                                    Dim wsData As Worksheet
                                    Dim aralik As Range
                                    Set ws = Worksheets.Add
                                    Set wsData = Worksheets("calculatedlar")
                                    Set aralik = wsData.Range("A1:F175")
                                    If Application.WorksheetFunction.CountA(aralik) = 0 Then
                                        MsgBox "Veri kaynağı boş. Lütfen kontrol ediniz."
                                        Exit Sub
                                    End If
                                    Set pc = ActiveWorkbook.PivotCaches.Create( _
                                        SourceType:=xlDatabase, _
                                        SourceData:=aralik)
                                    Set pt = pc.CreatePivotTable( _
                                        TableDestination:=ws.Range("A3"), _
                                        TableName:="PivotTable1")
                                    Exit Sub
                                Hata:
                                    MsgBox "Hata oluştu: " & Err.Description
                                End Sub
                                            
                                        

Yukarıdaki kodda veri aralığı kontrol ediliyor. Application.WorksheetFunction.CountA fonksiyonu ile aralıkta veri olup olmadığı kontrol ediliyor. Eğer aralık boşsa kullanıcıya bir mesaj veriliyor ve kod çalışmayı durduruyor. Eğer bir hata oluşursa, On Error ifadesi ile hata mesajı gösteriliyor.

Pivot Tabloların Yeniden Oluşturulması

Eğer tabloyu yeniden oluşturmak gerekirse, PT üzerinde PivotTable.ClearTable metodu ile tablo temizlenebilir. Daha sonra yukarıdaki gibi yeniden oluşturulabilir.

                        
                            Sub PivotTableTemizle()
                                Dim ws As Worksheet
                                Dim pt As PivotTable
                                Set ws = Worksheets("Sheet1")
                                Set pt = ws.PivotTables("PivotTable1")
                                pt.ClearTable
                            End Sub
                                        
                                    

Yukarıdaki kodda belirtilen tablo temizleniyor. Eğer tablo tamamen silinmek istenirse PivotTable.Delete metodu kullanılabilir. Bunu yaparken dikkat edilmesi gereken bir husus, tablo silindikten sonra o tabloya referans veren herhangi bir kod varsa, çalışmayacaktır.

PT'daki bir Field'da filtreli elemanları elde etme

Bir field'da seçili olan elemanları elde etmek VisibleItems özelliği ile oldukça kolaydır. Aşağıda, parametre olarak sayfa, PT adı ve field adını alan bir fonksiyonumuz ve bu fonksiyonu çağıran bir test prosedürümüz bulunuyor. Bu arada fonksiyonumuzun dönüş tipi PivotItems olup döngüsel olarak içinde dönerek elemanları yazdırıyoruz. (Dönüş tipini collection olarak da belirleyebilirdik, ancak bu sefer elemanları tek tek geçici bir Collection nesnesine atmak gerekirdi. Bu örneği Slicerdaki seçili elemanları getirme örneğinde yapacağız.)

                    
                                Function Pivotun1FieldındakileriGetir(ws As Worksheet, ptName As String, ptfield As String) As PivotItems
                                    'tek bir field için basit örnek
                                    Dim pt As PivotTable
                                    Dim pf As PivotField

                                    Set pt = ws.PivotTables(ptName)
                                    Set pf = pt.PivotFields(ptfield)
                                    Set Pivotun1FieldındakileriGetir = pf.VisibleItems
                                End Function
                                    Sub test_pivot_seçili_elemanlar()
                                        'Örnek olarak, Tarihsl Datanın Pivot ve Slcr sayfasındayken çalıştırabilirsiniz. Pivotta bikaç bölge filtreli olsun
                                        Dim kimlerseçili As PivotItems

                                        Set kimlerseçili = Pivotun1FieldındakileriGetir(ActiveSheet, "ptBolgekodUrun", "Bölge Kodu")
                                        For Each vi In kimlerseçili
                                            Debug.Print vi.Name
                                        Next vi
                                    End Sub
                                    
                                    

PT'daki birden fazla fieldda seçili olan elemanları elde etme

Bu sefer, hangi fieldda hangi değerlere filtre konmuş, bunları elde edeceğiz. Tabi şimdi işimiz biraz daha zor, o yüzden farklı bir bakış açısıyla yaklaşmak lazım. Aslında bu paragrafın ilk cümlesi bize bir dictionary'nin gerekliliğini gösteriyor: Hangi fieldda ne seçili, yani bildiğimiz Key ve Value ikilisi. O yüzden fonksiyonumuzun dönüş tipini bu sefer Dictionary olarak tanımlayacağız.

Tekil field örneğinden farklı olarak bu sefer Field isimlerini bir collection'a atayıp gönderiyoruz. Fonksiyonumuzdan gelen bilgileri yazdırırken de "birleştir" isimli yardımcı bir fonksiyon ile her fielddaki itemları yan yana birleştirip öyle yazdırıyoruz.

                    
                                Function PivotunÇokluFieldındakileriGetir(ws As Worksheet, ptName As String, ptfields As Collection) As Dictionary
                                    Dim pt As PivotTable
                                    Dim pf As PivotField
                                    Dim dict As New Dictionary

                                    Set pt = ws.PivotTables(ptName)
                                    For Each p In ptfields
                                        Set pf = pt.PivotFields(p)
                                        dict.Add p, pf.VisibleItems
                                    Next p

                                    Set PivotunÇokluFieldındakileriGetir = dict
                                End Function
                                    Sub test_pivot_seçili_elemanlar_çoklufield()
                                        'Örnek olarak, Tarihsl Datanın Pivot ve Slcr sayfasındayken çalıştırabilirsiniz. Pivotta bikaç bölge ve ürün filtreli olsun
                                        Dim mydict As Dictionary
                                        Dim alanlar As New Collection
                                        alanlar.Add "Bölge Kodu"
                                        alanlar.Add "Ürün"

                                        Set mydict = PivotunÇokluFieldındakileriGetir(ActiveSheet, "ptBolgekodUrun", alanlar)
                                        For Each k In mydict.Keys
                                            Debug.Print k, birleştir(mydict(k))
                                        Next k
                                    End Sub
                                    Function birleştir(pis As PivotItems)
                                        For Each pi In pis
                                            geçici = geçici & "-" & pi
                                        Next pi
                                        birleştir = Mid(geçici, 2)
                                    End Function
                                    
                                    

Aşağıdaki örnek üzerinden çalıştırdığımızda dönen sonuç da şöyle olmaktadır.

Bölge Kodu Başkent 1-Ege 2
                                Ürün ÜÜrün Ürün4-Ürün3-Ürün2
post-thumb

Bir fieldda filtre var mı kontrolü

Burada da AllItemsVisible şeklinde boolean tipli bir property ile sorgulamamızı yapabiliyoruz.

                                                    
                                Function pivot_field_filtrelimi(ws As Worksheet, ptName As String, ptfield As String) As Boolean
                                    pivot_field_filtrelimi = Not ws.PivotTables(ptName).PivotFields(ptfield).AllItemsVisible
                                End Function
                                    Sub test_pivot_field_filtrelimi()
                                        'data sayfasında çalıştırın
                                        Debug.Print pivot_field_filtrelimi(ActiveSheet, "PivotTable1", "Bölge")
                                        Debug.Print pivot_field_filtrelimi(ActiveSheet, "PivotTable1", "Şube Adı")
                                    End Sub
                                    
                                    

Bir fieldda 1 adet filtre kriteri uygulamak

Tek bir field üzerinde 1 adet filtre uygulamanın en pratik yolu PivotFilters nesnesini kullanmaktır. Syntaxı aşağıdaki örnekten görüldüğü üzere oldukça pratiktir. Type argümanının alacağı değerlerin intellisense ile çıkmasını isterseniz PivotFilters nesnesini en başta Dim ile tanımlayıp öyle ilerleyebilirsiniz. Aşağıdaki örnekte spesifik bir tarih ile iki tarih arası değer uygulama örneği bulunmaktadır. Bunların alabileceği değerlerin bir listesini şu sayfadan görebileceğiniz gibi, makro recorder ile denemeler sırasında da elde edebilirsiniz.

                    
                                    Sub pivotta_filtrekoy()
                                        'Tek fieldda tek değer filtreleme
                                        Sheets("Tarihsl Datanın Pivot ve Slcr").Select
                                        Application.EnableEvents = False 'ilgili sayfadaki eventler tetiklenmesin
                                        ActiveSheet.PivotTables("ptAy").ClearAllFilters

                                        ActiveSheet.PivotTables("ptAy").PivotFields("Ay").PivotFilters.Add2 _
                                            Type:=xlSpecificDate, Value1:="31.01.2016"
                                        ActiveSheet.PivotTables("ptAy").ClearAllFilters
                                        ActiveSheet.PivotTables("ptAy").PivotFields("Ay").PivotFilters.Add2 _
                                            Type:=xlDateBetween, Value1:="31.01.2016", Value2:="31.05.2016"
                                        Application.EnableEvents = True
                                    End Sub
                                        
                                        

Diğer PivotFilter örnekleri aşağıdaki gibi olabilir.

                    
                            ActiveCell.PivotField.PivotFilters.Add FilterType := xlThisWeek 
                            ActiveCell.PivotField.PivotFilters.Add FilterType := xlTopCount DataField := MyPivotField2 Value1 := 10 
                            ActiveCell.PivotField.PivotFilters.Add FilterType := xlCaptionIsNotBetween Value1 := "A" Value2 := "G" 
                            ActiveCell.PivotField.PivotFilters.Add FilterType := xlValueIsGreaterThanOrEqualTo DataField := MyPivotField2 Value1 := 10000 
                                
                                

1 fieldda 1 filtre uygulamanın alternatifi

1 fielda sadece 1 adet kriter gireceksek PivotFilter gayet uygun bir yöntemdir. Örnek olarak sadece "A" değerini filtrelemek için aşağıdaki kodu uygulayabilirsiniz.

                    
                                Sub pivotta_1_filtredene()
                                    'Tek fieldda tek değer filtreleme
                                    ActiveSheet.PivotTables("ptBolgekodUrun").PivotFields("Bölge Kodu").ClearAllFilters
                                    ActiveSheet.PivotTables("ptBolgekodUrun").PivotFields("Bölge Kodu").CurrentPage = "A"
                                End Sub
                                    
                                    

Giriş

Slicerlarda da yine PT'larda olduğu gibi bir Slicercache(SC) ve bu cacheden beslenen Slicerın kendisi vardır. Burada da bi recorder çalıştırıp bakalım. Biz tabi PT'da olduğu gibi Slicer eklemeyi de genelde Excel ön yüzde manuel olarak yapmış olacağız. VBA ile daha ziyade Slicerların elemanlarına erişim, bunların seçimini değiştirme, refreshleme v.s gibi işlemler yapacağız ama yine de nasıl bir kod oluşuyor, ona bi bakalım.

Şimdi ilk olarak Data sayfasındaki Table'a(ListObject) Slicer uygulandığında nasıl bir kod oluştuğuna bakalım. Pivot üzerine uygulanan Slicer ile yine pivot üzerine uygulanan Timeline tipli Slicer kodları örnek dosya içinde bulunmaktadır.

                        
                                Sub Macro2()'
                                ' Macro2 Table Slicerı
                                '

                                '
                                    ActiveWorkbook.SlicerCaches.Add2(ActiveSheet.ListObjects("Table7"), "Bölge"). _
                                        Slicers.Add ActiveSheet, , "Bölge", "Bölge", 40.5, 414, 144, 198.75
                                    ActiveWorkbook.SlicerCaches.Add2(ActiveSheet.ListObjects("Table7"), "Ürün Adı") _
                                        .Slicers.Add ActiveSheet, , "Ürün Adı", "Ürün Adı", 78, 451.5, 144, 198.75
                                    ActiveSheet.Shapes.Range(Array("Ürün Adı")).Select
                                    With ActiveWorkbook.SlicerCaches("Slicer_Bölge")
                                        .SlicerItems("Başkent 1").Selected = True
                                        .SlicerItems("Başkent 2").Selected = False
                                        .SlicerItems("Batı Karadeniz").Selected = False
                                        .SlicerItems("Doğru Karadeniz").Selected = False
                                        .SlicerItems("Ege 1").Selected = False
                                        .SlicerItems("Ege 2").Selected = False
                                        .SlicerItems("Güney Akdeniz").Selected = False
                                        .SlicerItems("Güneydoğu Anadolu").Selected = False
                                        .SlicerItems("İç Anadolu").Selected = False
                                        .SlicerItems("İstanbul 1").Selected = False
                                        .SlicerItems("İstanbul 2").Selected = False
                                        .SlicerItems("İstanbul 3").Selected = False
                                        .SlicerItems("Marmara").Selected = False
                                    End With
                                    ActiveWorkbook.SlicerCaches("Slicer_Bölge").ClearManualFilter
                                    With ActiveWorkbook.SlicerCaches("Slicer_Bölge")
                                        .SlicerItems("Başkent 2").Selected = True
                                        .SlicerItems("Başkent 1").Selected = False
                                        .SlicerItems("Batı Karadeniz").Selected = False
                                        .SlicerItems("Doğru Karadeniz").Selected = False
                                        .SlicerItems("Ege 1").Selected = False
                                        .SlicerItems("Ege 2").Selected = False
                                        .SlicerItems("Güney Akdeniz").Selected = False
                                        .SlicerItems("Güneydoğu Anadolu").Selected = False
                                        .SlicerItems("İç Anadolu").Selected = False
                                        .SlicerItems("İstanbul 1").Selected = False
                                        .SlicerItems("İstanbul 2").Selected = False
                                        .SlicerItems("İstanbul 3").Selected = False
                                        .SlicerItems("Marmara").Selected = False
                                    End With
                                    With ActiveWorkbook.SlicerCaches("Slicer_Ürün_Adı")
                                        .SlicerItems("Ürün1").Selected = True
                                        .SlicerItems("Ürün2").Selected = False
                                        .SlicerItems("Ürün3").Selected = False
                                        .SlicerItems("Ürün4").Selected = False
                                    End With
                                    With ActiveWorkbook.SlicerCaches("Slicer_Bölge")
                                        .SlicerItems("Doğru Karadeniz").Selected = True
                                        .SlicerItems("Başkent 1").Selected = False
                                        .SlicerItems("Başkent 2").Selected = False
                                        .SlicerItems("Batı Karadeniz").Selected = False
                                        .SlicerItems("Ege 1").Selected = False
                                        .SlicerItems("Ege 2").Selected = False
                                        .SlicerItems("Güney Akdeniz").Selected = False
                                        .SlicerItems("Güneydoğu Anadolu").Selected = False
                                        .SlicerItems("İç Anadolu").Selected = False
                                        .SlicerItems("İstanbul 1").Selected = False
                                        .SlicerItems("İstanbul 2").Selected = False
                                        .SlicerItems("İstanbul 3").Selected = False
                                        .SlicerItems("Marmara").Selected = False
                                    End With
                                    With ActiveWorkbook.SlicerCaches("Slicer_Bölge")
                                        .SlicerItems("Başkent 2").Selected = True
                                        .SlicerItems("Doğru Karadeniz").Selected = True
                                        .SlicerItems("Başkent 1").Selected = False
                                        .SlicerItems("Batı Karadeniz").Selected = False
                                        .SlicerItems("Ege 1").Selected = False
                                        .SlicerItems("Ege 2").Selected = False
                                        .SlicerItems("Güney Akdeniz").Selected = False
                                        .SlicerItems("Güneydoğu Anadolu").Selected = False
                                        .SlicerItems("İç Anadolu").Selected = False
                                        .SlicerItems("İstanbul 1").Selected = False
                                        .SlicerItems("İstanbul 2").Selected = False
                                        .SlicerItems("İstanbul 3").Selected = False
                                        .SlicerItems("Marmara").Selected = False
                                    End With

                                    ActiveSheet.Shapes.Range(Array("Bölge")).Select
                                    ActiveWorkbook.SlicerCaches("Slicer_Bölge").Slicers("Bölge").Name = "BölgeSlc"
                                    With ActiveWorkbook.SlicerCaches("Slicer_Bölge").Slicers("BölgeSlc")
                                        .Caption = "Bölge"
                                        .DisplayHeader = True
                                        .SlicerCache.CrossFilterType = xlSlicerCrossFilterShowItemsWithDataAtTop
                                        .SlicerCache.SortItems = xlSlicerSortAscending
                                        .SlicerCache.SortUsingCustomLists = True
                                    End With
                                End Sub
                                        
                                    

Görüldüğü üzere sadece bir iki adet işaretleme yapsam bile Slicerdaki diğer seçenekler için de otomatikman False değerini üretti. Manuel yazarken biz sadece istediklerimizi True yazarız, diğerleri mevcut değerleriyle kalır.

Mantıken, bir Slicerda belirli bir anda en az bir eleman seçili olmalıdır. Bu eleman seçiliyken başka bir elamanı da seçmek istersek, sadece onu seçen kodu yazmak yeterli. Ör: Slicerda A,B,C,D,E değerleri var olsun. Şuan sadece A seçiliyse, diğerlerinin Selected değeri False'tur. Biz ilaveten B'yi de seçmek istersek, B.Selected=True yazmak yeterli, ama sadece B seçili olsun istersek, A'ya da false atamak gerekir. Kendi bölge örneğimiz üzerinden gidecek olursak:

                        
            Sub ilave_secim()
                With ActiveWorkbook.SlicerCaches("Slicer_Bölge")
                    'cachelere ya indeks ile ya da "formula name" ile ulaşılır, name ile değil. Name Slicer'ın adıdır, cache'nin değil.
                    .SlicerItems("Ege 1").Selected = True
                End With
            End Sub

            Sub tek_secim()
                With ActiveWorkbook.SlicerCaches("Slicer_Bölge")
                    .SlicerItems("Ege 1").Selected = True
                    .SlicerItems("Doğru Karadeniz").Selected = False
                End With
            End Sub
        
    

Bu arada farkettiyseniz SCs collection'ına bir indeks verince elde ettiğim tekil bir SC üzerinden doğrudan Sliceritemlara ulaşabiliyoruz, yani arada Slicerı seçmeye gerek yok. Zira bunlarda, PT'lardan farklı olarak bir SC ile bir Slicer eşleşiyor gibi bir durum var, zaten aksi garip olurdu.

Yukarıda recorder kodu olarak bir Table Slicer'ı vermiştik. Pivot Slicerı oluşturunca da pek farklı bi durum yok, sadece parametlerde ufak bir iki değişiklik var. Bundan başka Table'larda olmayıp sadece PT'larda olan Timeline da eklenebiliyor, ki bunlar da bir tür Slicer olarak kabul görüyor.

Çeşitli propertyler

Şimdi küçük bir kod üzerinde birkaç özelliğe bakalım.

NOT: OLAP yani PowerPivot gibi bir kaynaktan besleneme durumunda kullanılabilen özellikler(level, visibleitemlist v.s) bu bölümlerin kapsamı dışındadır.

Az önce Timelineların da bir tür Slicer olduğunu söylemiştik, bunların property olarak sadece SlicerCacheTypeları farklı oluyror; Microsoft dokümantasyonunda bu type değeri için sadece 1 ve 2 değerleri var; 1 Slicer, 2 Timeline oluyor ama ben aşağıdaki sorguyu çalıştırdığımda 0 değerini de görüyorum. Zannımca bu 2013te Slicer özelliği gelen Table'lardan üretilen SC'leri ifade ediyor. Microsoftun bunu hala(bu sayfanın hazırlandığı tarih olan Haziran 2019'da) dokümante etmemiş olması ilginç.

                        
'Global değişkenler
Dim sl As Slicer
Dim slc As SlicerCache
Dim sli As SlicerItem
Dim ws As Worksheet

Sub tüm_slicerlarda_dolaşma()
    For Each slc In ActiveWorkbook.SlicerCaches
        For Each sl In slc.Slicers
            Debug.Print slc.SourceName, slc.Index, slc.SlicerCacheType, sl.Name, sl.Parent.Name, sl.Caption, slc.Name
        Next sl
    Next slc
End Sub
    
    

slicer cache type

Çeşitli İşlemler

Seçili olan tek bir elemanı elde etme

Bu örnekte aktif olarak seçili olan elemanı elde edeceğiz.

                                        
                            Sub seçili_eleman()
                                'focuslu ise çalışır, aksi halde hata verir
                                Debug.Print ActiveWorkbook.SlicerCaches("Slicer_Bölge_Kodu").Slicers(1).ActiveItem.Name
                            End Sub
                        
                        

Seçili olan birçok elemanı elde etme

Şimdi de birden çok eleman varsa onları yazdıralım. Tabi burada örnekleri basit tutmak adına elemanları sadece yazdırıyoruz, ihtiyaca göre elemanlar bir collectiona, formdaki listboxa v.s atanabilir.

                        
                    
                                    Sub seçili_elemanlar()
                                        For Each sI In ActiveWorkbook.SlicerCaches("Slicer_Bölge_Kodu").VisibleSlicerItems
                                            Debug.Print sI.Name
                                        Next sI
                                    End Sub
                                    
                        
Bu işlem için birçok forumda aşağıdaki koda benzer bir kod sunuluyor. Biz PT kısmında seçili elemanları elde ederken farklı bir yöntem izlemiştik, orda dönüş tipini PivotItems olarak belirlemiştik ve demiştikki Slicerda Collection yöntemini kullanacağız. Pek tabiki burada da dönüş tipini SlicerItems yapabiliriz. Ancak biz geleneğe uyalım ve Collection yöntemini kullanalım, hemen altında da SlicerItems yöntemini deneriz.

                        
                    
                                    Public Function SlicerdaSeçilileriGetir(SlicerName As String) As Collection
    Dim geçici As New Collection
    Set slc = ActiveWorkbook.SlicerCaches(SlicerName)

    For Each sli In slc.SlicerItems
        If sli.Selected Then
            geçici.Add sli.Name
        End If
    Next
    Set SlicerdaSeçilileriGetir = geçici
End Function
    Sub test_SlicerdaSeçilileriGetir()
        Dim seçililer As Collection
        Set seçililer = SlicerdaSeçilileriGetir("Slicer_Bölge_Kodu")
        For Each s In seçililer
            Debug.Print s
        Next s
    End Sub
                                    
                        
Bu örnekte tekil ve çoklu eleman döndürme işlemini tek bir prosedürle yapmış olduk. Çoklu eleman seçiminde döngüsel olarak dolaşmayı yukarıdaki kodla görmüş olduk. Tek eleman seçiminde ise collection'ın ilk elemanına ulaşmak yeterlidir.

SlicerdaSeçilileriGetir("Slicer_Bölge_Kodu")(1)

SlicerItems dönüş tipli yönteme göre ise kodumuz daha kısa. Neden bu değil de Collection'lı kullanılıyor gerçekten bilmiyorum, Timer ile performans kontrolü de yaptım, ikisi de aynı sürede çalışıyor gibi görünüyor. Her neyse siz ikisini de bilin.

        
Public Function SlicerdaSeçilileriGetirSlicerItemslıYöntem(SlicerName As String) As SlicerItems
    Set SlicerdaSeçilileriGetirSlicerItemslıYöntem = ActiveWorkbook.SlicerCaches(SlicerName).VisibleSlicerItems
End Function

Sub test_SlicerdaSeçilileriGetirSlicerItemslıYöntem()
    Dim kimlerseçili As SlicerItems

    Set kimlerseçili = SlicerdaSeçilileriGetirSlicerItemslıYöntem("Slicer_Bölge_Kodu")
    For Each vi In kimlerseçili
        Debug.Print vi.Name
    Next vi
End Sub
        
    

Tek bir elemanı seçme

Bu yöntemde PT'larda yaptığımız gibi elemanlar üzerinde tek tek dolaşarak ilerleyeceğiz. Parametrelerden son parametreye dikkat, orada elemanların formatı farklı olabilir diye bunu da belirtme seçeceği veriyorum. Eğer bu parametre prosedüre geçirilmezse eleman aynen alınırken, geçirilme durumunda format fonksiyonu ile şekillendirilip öyle seçilir.

        
Sub slicerda_tek_eleman_seç(cacheName As String, eleman As Variant, Optional elemanFormat)
    Dim item As SlicerItem

    Application.EnableEvents = False 'ilgili sayfadaki eventler tetiklenmesin
    ActiveWorkbook.SlicerCaches(cacheName).ClearManualFilter  'Önce tüm filtreleri kaldıralım ki, hiç elamanın seçili olmaadığı mantıksız bi durum oluşmasın
    For Each item In ActiveWorkbook.SlicerCaches(cacheName).SlicerItems
        'pivot örneğinde pivotitem'ı formatlıyorduk, burada filtre değerini
        If item.Name <> IIf(IsMissing(elemanFormat), eleman, Format(eleman, elemanFormat)) Then
            item.Selected = False
        End If
    Next item
    Application.EnableEvents = True
End Sub

Sub test_slicerda_tek_eleman_seç()
    slicerda_tek_eleman_seç "Slicer_Ürün", "Ürün3"
    slicerda_tek_eleman_seç "Slicer_Ay", "29.02.2016", "Long Date"
End Sub
        
    

Çok eleman seçme

Bu örnekte ise birden çok elemanı seçiyoruz. Birden çok değerin varlığını sorgulamak durumunda olduğum için Dictionary kullanıyorum.

        
Sub slicerda_çok_eleman_seç(cacheName As String, elemanlar As Dictionary, Optional elemanFormat)
    Dim item As SlicerItem

    Application.EnableEvents = False
    If Not IsMissing(elemanFormat) Then
        For Each e In elemanlar.Keys
            elemanlar.Key(e) = Format(e, elemanFormat)
        Next e
    End If

    ActiveWorkbook.SlicerCaches(cacheName).ClearManualFilter  'Önce tüm filtreleri kaldıralım ki, hiç elamanın seçili olmağı mantıksız bi durum oluşmasın

    For Each item In ActiveWorkbook.SlicerCaches(cacheName).SlicerItems
        If Not elemanlar.Exists(item.Value) Then
            item.Selected = False
        End If
    Next item
    Application.EnableEvents = True
End Sub

Sub test_slicerda_çok_eleman_seç()
    Dim dict As New Scripting.Dictionary
    dict.Add "Ürün2", 1
    dict.Add "Ürün3", 2

    slicerda_çok_eleman_seç "Slicer_Ürün", dict

    'olmayan veri de gönderelim
    dict.RemoveAll
    dict.Add "29.02.2016", 1
    dict.Add "25.02.2016", 2
    dict.Add "31.03.2016", 3
    slicerda_çok_eleman_seç "Slicer_Ay", dict, "Long Date"
End Sub
        
    

PT eventlerini kullanarak Slicer değişimlerini yakalamak

Yukarıda PT'lar kısmında PT eventlerini görmüştük. Şimdi bu eventleri Slicerlarla birlikte nasıl kullanırız, ona bakacağız.

PT değişimiyle seçili elemanı elde etmek

İster PT üzerinden manuel, ister kod ile, ister Slicer'ın kendisi aracılığı ile PT üzerinde bir seçim yapmış olalım. Bu seçilen elemanı bir hücrede, bir grafik başlığında veya kod içinde her hangibir yerde değişken olarak kullanmak isteyebiliriz.

"Tarihsel Datanın Pivot ve Slicerı" sayfasındaki PT'lardan ptBolgekodUrun isimli olan PT'da bir değişklik olduğunda F1 hücresine ilgil PT'da seçilen elemanı yazdırıyoruz. Birden çok eleman seçilirse ilki yazılır. Bizim kodumuz, özellikle bir eleman seçiminin beklendiği durumlarda anlamlıdır. Zira muhtemelen bunu küçük bir veri bloğunun başlığı halinde kullanacağızdır, "Ege 1 Bölgesi Kredi Rakamları" gibi.

        
Private Sub Worksheet_PivotTableChangeSync(ByVal Target As PivotTable)
    Debug.Print "changesync oldu"
    If Target.Name = "ptBolgekodUrun" Then
        [F1].Value = SlicerdaSeçilileriGetir("Slicer_Bölge_Kodu")(1) & " Bölgesi"
    End If
End Sub
        
    
Dashboard Yönetimi

PT kısmında birden fazla PT aynı PC'yi kullanıyorsa bunlardan birinde yapılan seçimi diğerlerini de otomatikman etkiler demiştik.

Peki ya elimizde PC'leri farklı olan PT'lar varsa ve biz birinde yapılan seçim  hepsinde geçerli olsun istiyorsak?

Mesela aşağıdaki farklı renkle gösterilen bloklardan oluşan bir dashboardda farklı kaynaklardan gelen PT'lar bulunuyor olsun. Bunların her biri için Slicer yapmaya gerek yok. Biz biri için bir Slicer yaparız, bunda seçilen elemanı bi değişkende depolarız(yukarıda gördüğümüz yöntemlerle) ve diğer PT'larda da bu elemanı seçtiririz(yine yukarıdaki yöntemlerle). İkinci kısmı yaptırabilmek için bir haber almamız, yani bir eventin tetiklenmesi lazım, acaba hangi event; tabiki Worksheet_PivotTableChangeSync eventi.

post-thumb

Biz örneğimizi basit tutmak adına sadece iki PT kullacağız. Soldakinin adı ptSol, sağdakinin adı ptSağ. Slicer'ımız soldakine aittir.

post-thumb

Buna göre kodumuz aşağıdaki gibidir.

        
Private Sub Worksheet_PivotTableChangeSync(ByVal Target As PivotTable)
    If Target.Name = "ptLeft" Then
        If Not pivot_field_filtrelimi(ActiveSheet, "ptLeft", "Bölge") Then
            secilen = SlicerdaSeçilileriGetir("Slicer_Bölge2")(1)
            Pivotun1Fieldında1ElemanFiltrele ActiveSheet, "ptRight", "Bölge Kodu", secilen
        Else
            ActiveSheet.PivotTables("ptRight").ClearAllFilters
        End If
    End If
End Sub
        
    

Dikkat ettiyseniz ilk olarak eventin soldaki PT için tetiklenip tetiklenmediğine bakıyoruz. Sağdaki için manuel bir filtre yapılırsa kod ilk If bloğundan sonra çıkar. Bir diğer kontrolümüz de değişklik sonucunda PT'da filtre var mı yok mu kontrolü, varsa esas kodlarımızı işletiyoruz, filtre yoksa sağdaki için de ClearAllFilters yapıyoruz.

Aşağıda seçim sonrası tabloların genel durumu görünüyor.

post-thumb

Table eventlerini kullanmak

Sadece PT eventi değil bir Table eventini kullanarak da Slicerlarla işlem yapabiliriz. Mesela aşağıdaki kod ile, Tarihsel Data sayfasında varsayalım ki bir veritabanı bağlantısı var ve bu tablo belli zamanlarda(dosya ilk açıldığında, sayfa aktive olduğunda v.s) refresh oluyor olsun. Refresh sonucunda mevcut tarihten daha büyük bi tarih gelirse, Slicer da buna göre güncellensin, yani slicerda en büyük tarih seçili olsun.

        
Private Sub Worksheet_TableUpdate(ByVal Target As TableObject)
    Dim maxTarih As String

    maxTarih = Format(WorksheetFunction.Max(Worksheets("Tarihsel Data").Columns(3)), "dd.mm.yyyy")
    Application.EnableEvents = False
    slicerda_tek_eleman_seç "Slicer_Ay", maxTarih, "Long Date"
    Application.EnableEvents = True
End Sub
        
    

Kullanıcılara PT Slicerını Table Slicer'ı gibi kullandırtmak

Bazen olur ki, Table'a ait Slicer üzerinde bir değişklik yaptığınızda bunun bir eventi tetiklemesini istersiniz. Ancak Table'ların filtrelenmesine yönelik böyle bir event yoktur. Sadece TableUpdate eventi var, o da tablo güncellendiğinde devreye girer.

Böyle bir durumda Excel'i kandırma yoluna gidebiliriz. İzleyeceğimiz yollardan biri şudur:

  • Bu tabledan bir PT yaratmak
  • Bu PT üzerine bir Slicer koymak
  • PT' bölgesini gizlemek veya aşağı bir bölgeye almak, yeter ki görünmesin
  • Slicer seçildiğinde PT'ın ChangeSync eventinin tetiklenmesini sağlamak
  • PT eventi tetiklenince seçilen değeri alıp bu değeri Table üzerinde filtre olarak uygulamak(Table üzerinde doğrudan veya ona ait Slicerda dolaylı. Slicer kullanacaksak bunu genelde gizlemeyi tercih ederiz, iki slicer karışmasın diye, ama ben bu sayfadakini gizlemeden bıraktım)
  • ve diğer işlerimizi yaptırmak

Buna ait basit bir örneği aşağıda bulabilirsiniz. Kod Data sayfasına aittir.

        
Private Sub Worksheet_PivotTableChangeSync(ByVal Target As PivotTable)

    'Exit Sub 'Event örneklerini yaptığımızda bu satırı commentleyin, event dışındaki örneklerde açık kalsın

    Application.EnableEvents = False

    If ActiveWorkbook.SlicerCaches("Slicer_Bölge1").VisibleSlicerItems.Count = ActiveWorkbook.SlicerCaches("Slicer_Bölge1").SlicerItems.Count Then 'pivotun slicerı
        ActiveWorkbook.SlicerCaches("Slicer_Bölge").ClearManualFilter 'Tableınki, görünmezdir, veya aşağılarda görünmez olsa da olur
        GoTo çıkış
    Else 'sadece tek seçim yapıldığı varsayılmıştır, çoklu seçimlerde işe yaramaz
        secilen = SlicerdaSeçilileriGetir("Slicer_Bölge1")(1)
        ActiveWorkbook.SlicerCaches("Slicer_Bölge").ClearManualFilter 'önce clear
        slicerda_tek_eleman_seç "Slicer_Bölge", secilen
    End If

çıkış:
    Application.EnableEvents = True
End Sub
        
    

İzleyeceğimzi bir başka yol da Worksheet_Calculate eventinden faydalanmaktır. Her iki alternatifi de göreceğimiz daha anlamlı bir örneği Chart nesnesinden sonraki Örnek Uygulama bölümünde bulabilirsiniz.

Dashboard yönetimi kısmında makroların gücünü döngüler ve koşullu yapıları kullanarak çok güzel görmüştük. Grafiklerde de benzer kolaylıklardan yararlanacağız. Tabiki PT'larda olduğu gibi grafik yaratmayla pek uğraşmayacağız. Otomasyon projelerinde kodunuzun bir grafik yaratması gerekse bile bunu recorder ile ürettiğiniz kodu elden geçirerek yapabilirsiniz.

Mesela yukarıda Slicerlar bölümünde 6 farklı renkli gösterilmiş dashboardu düşünün, orada o bloklar PT'lardan oluşuyordu, şimdi varsayalım ki bunlar birer grafik. Bu sefer her birininin tipini, boyutunu, pozisyonunu, lejandını, renkleri v.s tek seferde değiştirmek istiyoruz, tabiki bunu döngülerle yapacağız.

Veya grafiğe konu olan datasetinde seçilen bir değere göre gragiği dinamik olarak güncellemek gerekecek. Bu gibi işleri yine makro ile başaracağız.

Nesneler hiyerarşisi

Şimdi öncelikle elimizdeki nesneler bi bakalım

  • Chart nesnesi: Bunlar bağımsız grafik sayfaları olabileceği gibi normal bir sayfa(worksheet) içindeki gömülü grafikler de olabilir. Ancak bunlardan sadece bağımsız sayfa olarak bulunanlar Charts koleksiyonunun bir üyesidir, gömülü olanlar değil.
  • ChartObject nesnesi: Worksheet içinde bulunan grafiklerin(Worksheet Chartlarının) konteynerıdır. Esasen bir grafik nesnesi değil, onun kabuğudur. Propertylerine falan bakıldığında grafikten ziyade Shape nesnesinin özelliklerini görürsünüz. ChartObjects koleksiyonunun bir üyesidir. Aynı zamanda Shapes koleksiyonunun da bir üyesidir. Hatta macro recorder ile grafik oluşturduğunuzda Shapes üzerinden oluşturur.

Yani aslında 3 tür nesnemiz var diyebilir.

  1. Worksheetlerdeki gömülü Chart: Chart. Parent nesnesi ChartObjecttir.
  2. Bağımsız Chart: Bu da Chart'tır. Parent nesnesi Workbook'tur.
  3. Worksheet Chartı için kontyner: ChartObject. Buna ulaşmadan içindeki Charta ulaşılamaz. Parent nesnesi Worksheet'tir.

Örnek birkaç erişim şekli şöyle olabilir:

                            
                    'Worksheet içindeki bir Chart'a zincirleme olarak
                    Sheets("Sheet1").ChartObjects("Chart 1").Chart.ChartTitle.Text = "Yeni başlık"
                    'ya da önce konteynerı seçince aktif olan ActiveChart ile
                    Sheets("Sheet1").ChartObjects("Chart 1").Activate
                    ActiveChart.ChartTitle.Text = "Yeni başlık"
                    'bağımsız chart
                    Sheets("Chart 1").ChartTitle.Text = "Yeni başlık" 'sayfa adından
                    ActiveWorkbook.Sheets("Chart1").ChartTitle.Text = "Yeni başlık" 'nesne adından
                            
                        

Bu bilgiler ışığında chartlarda dolaşma şu şekilde olur.

                            
                    Sub chartlarda_dolaşma()

                        Dim chto As ChartObject
                        Dim cht As Chart

                        'sayfa olan chartlarda dolaşalım
                        For Each cht In ActiveWorkbook.Charts
                            Debug.Print cht.Name, TypeName(cht), TypeName(cht.Parent)
                        Next cht

                        'gömülü chartlarda dolaşalım
                        For Each ws In ActiveWorkbook.Worksheets
                            For Each chto In ws.ChartObjects
                                Debug.Print chto.Name, chto.Index, chto.Parent.Name 'Chart'ın adı biraz anlamsız, ChartObject'in adını kullanalım
                            Next chto
                        Next ws

                    End Sub
                            
                        

Yaratım ve değişiklik

Yaratım ve özelliklerdeki değişiklikler için hep recorder kullanmanızı tavsiye ediyorum arkadaşlar. O yüzden buna ait kodları buraya koymuyorum.

Diğer hususlar

Grafik datasının olduğu bölgeyi grafikle kaplamak

Özellikle dashboard sayfalarında grafik datasının ortalıkta görünmesini istemeyiz. Gizli satır/kolon veya sayfanın aşağılarında bir yerlere koymak bir çözüm olabileceği gibi, data alanı çok küçük/büyük değilse bu bölgeyi grafiğin kendisiyle kapatmak bir çözüm olabilir.

Aşağıdaki kod ile bunu yapabiliriz. Kodda bir yardımcı fonksiyon kullanıyorum. Bu fonksiyonda F8 ile ilerleyerek "dizi" değişkenini incelerseniz adres1 ve adres2de ne yaptığımı anlayacaksınız.

Dashboard sayfanızdaki tüm grafiklerde döngüsel olarak çalışacak şekilde bu kodu modifiye edebilirsiniz.

Sub RangeiGrafikleKapla()

    Dim cht As ChartObject
    Dim grafikAlan As Range

    Set cht = ActiveChart.Parent
    Set grafikAlan = GrafikRange(cht.Chart)

    cht.Left = grafikAlan.Left
    cht.Width = grafikAlan.Width
    cht.Top = grafikAlan.Top
    cht.Height = grafikAlan.Height
End Sub	
'Yardımcı fonksiyonumuz
	Function GrafikRange(cht As Chart) As Range
		dizi = cht.SeriesCollection(1).Formula
		adres1 = Split(Replace(Split(dizi, ",")(1), cht.Parent.Parent.Name & "!", ""), ":")(0)
		adres2 = Split(Replace(Split(dizi, ",")(2), cht.Parent.Parent.Name & "!", ""), ":")(1)
		
		Set GrafikRange = Range(adres1, adres2)	
	End Function

Grafikleri silme ve gizleme

Silme ve gizleme işlemlerini Shapeler aracılığı ile yapabileceğimiz gibi ChartObject'in kendisiyle de yapabiliriz. Burada önemli olan Chart nesnesini değil ChartObject nesnesini silebildiğimizdir.

                    
                            ActiveChart.Delete 'çalışmaz
                            ActiveSheet.ChartObjects(1).Delete 'bu 1 nolu chartı siler
                            ActiveSheet.ChartObjects.Delete 'bu sayfadaki tüm grafikleri siler
                    
                

Chart sayfalarını ise normal sayfa siler gibi siliyoruz.