Geldik, en kafa karıştıran konulardan birine. Bu bölümde,
Shape(sayfa içi nesneler) ve onların bir alt grubu olan
OleObject kavramlarına değineceğiz.
Burada bu nesnelerin sayfa düzeni, sitil
özellikleri, görünürlük gibi "şekle özgü" özelliklerine bakacağız.
Özellikle kafanızın karışmaması gerek nokta şudur: AutoShape dışındaki şekillerin nesne
modelindeki özelliklerine burada girmeyeceğiz. Örneğin bir Slicer'la
ilgili seçim yapma, filtreleri kaldırma gibi özelliklerden ziyade Slicer'ın
sayfanın neresinde konumlandırılacağı, gösterilip gösterilmeyeceği gibi
özellikler kapsamımızda olacaktır. Bu nesnelerin, nesne modeline ait
konuları kendilerine ait sayafalarda bulunacaktır.
Slicer ve
Chart,
Form kontrolleri gibi.
Şimdi, elimizde aşağıdaki şekilleri içeren bir sayfa olduğunu düşünün.
İsterseniz bunları içeren dosyayı
buradan
indirebilirsiniz.
Burada hemen her türden nesne(Grafik, Slicer, TextBox, Konuşma balonu,
Resim, gömülü pdf dosyası, Form Buton, ActiveX button) var. PivotTable ve
Table dışında buradaki herşey bir Shape nesnesidir ve
bunlar doğal olarak Shapes collection'ının bir üyesidir.
Aslında bir range'e yayılmamış olan herşey bir Shape'tir diye
düşünebilirsiniz. Bu bağlamda, bir range bölgesi olan Table ve
PivotTable'lar Shape olmamakta. Bunlar sırasıyla ListObjects ve
PivotTables
collectionlarının üyeleridir.
OleObject'ler de Shape'lerin bir alt türüdür, yani
her OleObject aynı zamanda bir Shape'tir. Bu yukarıdaki örnekte;
ActiveX commandbutonu, gömülü pdf dosyası ve linkli powerpoint sunumu.
Zaten bunlara tıkladığımızda fonksiyon çubuğunda ya
EMBED ile başlayan bir ifade görürüz:
=EMBED("Forms.CommandButton.1";"") ve =EMBED("Acrobat Document";"") ya da
Link adresi, "=PowerPoint.Slide.12|'C:\Users\Volkan\Videos\Movavi Screen
Capture Studio\Udemy Kurslar\2-ileri vba-makro\dosyalar\İLERİ EXCEL
VBA(MAKRO) EĞİTİMİ - Giriş.pptx'!'!265'"
Şimdi bunlara yakından bakalım.
Yukarıda belirttiğimiz gibi, bir Range'ten ziyade sayfa üzerinde ayrı
bir nesne gibi duran ve mouse ile seçildiğinde köşelerinde ve kenar
ortalarında küçük yuvarlaklar çıkaran herşey Shape'tir.
Shape'lerle ilgili önemli birkaç özellik/metod aşağıdaki gibidir.
Activesheet.Shapes.SelectAll 'sayfadaki tüm shapeleri seçer
Activesheet.Shapes.Count 'sayfadaki shapelerin sayısını verir
Activesheet.Shapes.Addxxx 'xxx yerine şekil tipi gelir, Ör:AddOLEObject
Shape'lere erişim
Tüm diğer collection(workbooks, worksheets v.s) tiplerinde olduğu
gibi shape'lerde de indeks(indeks no veya isim) ile tekil shape'lere
ulaşabiliyor ve sonra bunlara ait özellikler veya metodları
kullanabiliyoruz.
Activesheet.Shapes(i).Delete 'i. şekili siler
ActiveSheet.Shapes("Button 1").Visible = msoFalse 'Button 1 isimli shape grünmez yapar
Tüm shapelerde dolaşmak için aşağıdaki gibi bir döngü kullanabiliriz.
Sub shapelerde_dolaş()
Dim şekil As Shape
For Each şekil In ActiveSheet.Shapes
Debug.Print şekil.Name
Next şekil
End Sub
Type property'si ile de ilgili şeklin
tipinin enumeration değeri döner. Bunlara ait değerleri
buradan görebilirsiniz. Aşağıda en sık kullanılanlara ait bir
tabloyu bulabilirsiniz.
Name |
Value |
Description |
Örnek |
msoShapeTypeMixed |
-2 |
Mixed shape type |
TimeLine |
msoAutoShape |
1 |
AutoShape |
Diktörtgen |
msoChart |
3 |
Chart |
Grafik |
msoEmbeddedOLEObject |
7 |
Embedded OLE object |
Gömü PDF |
msoLinkedOLEObject |
10 |
Linked OLE object |
Linkli PowerPoint |
msoOLEControlObject |
12 |
OLE control object |
ActiveX CommandButton |
msoPicture |
13 |
Picture |
Resim |
msoTextBox |
17 |
Text box |
|
msoSlicer |
25 |
Slicer |
Slicer |
Bu Type özelliği, özellikle If ile kontrol yapıp sadece belirli
şekillerle işlem yapmak istediğimizde kullanışlıdır. Mesela aşağıdaki
kod ile sayfadaki tüm grafikleri silebiliriz.
Sub shapleerde_dolaş()
Dim şekil As Shape
For Each şekil In ActiveSheet.Shapes
If şekil.Type = 3 Then 'veya msoChart
şekil.Delete
End If
Next şekil
End Sub
Aşağıdaki kod ile de grafik ve comment dışındaki tüm şekilleri
siliyoruz.
If şekil.Type <> msoChart And şekil.Type <> msoComment Then şekil.Delete
Insert menüsünden "Object" olarak eklenenler ve Developer menüsünden
eklenen ActiveX objeleri OleObject olarak görünür.
ActiveX dışı OleObjeler
sayfaya gömülü veya linkli olurlar. OLEType özelliği ile ilgili nesnenin linkli mi yoksa gömülü mü
olduğu tespit edilebilir. Alacağı değerler şöyledir:
- Linkli:0(xlOLELink),
- Gömülü:1(xlOLEEmbed) ve
- ActiveX Kontrol:2(xlOleControl).
Nesnelere Erişim
Bunlarda da tekil objelere yine indeks ile ulaşırız.
Activesheet.OLEObjects("ListBox1").Delete 'veya indexno
Yine döngüyle tüm oleobjeleri dolaşalım:
Sub oleobjelerdedolaş()
Dim oleo As OLEObject
For Each oleo In ActiveSheet.OLEObjects
Debug.Print oleo.Name
Next oleo
End Sub
Collectionlarla toplu işlemler de gerçekleştirebiliriz.
Activesheet.OLEObjects.Visible = False 'hepsini gizler
Sayfaya dinamik olarak OleObje eklemek de mümkündür.
Worksheets(1).OLEObjects.Add FileName:="arcade.gif" 'gömülü gif dosyası
Worksheets(1).OLEObjects.Add ClassType:="Forms.ListBox.1" 'ActiveX kontrolü
Nesnelerin
Özelliklerine erişim
Gömülü/Linkli nesneler
Gömülü/Linkli öğelerde daha çok Visible ve Top/Left gibi konum
özellikleriyle ilgilineceğiz.
Gömülü bir pdf dosyasındaki özelliklere erişime bir bakalım.
ActiveSheet.OLEObjects("Ole1_embed_PDF").Visible = True
Bu özelliklerin bir kısmına Shapes collection'ı üzerinden de
ulaşabiliriz. Ne de olsa tüm OleObjectler aynı zamanda bir Shape'tir.
Enabled gibi bazı öellikler Shape class'ında bulunmadığı için bunları
kullanamayız, dolayısıyla mecburen OleObject nesnesini kullanırız.
ActiveSheet.Shapes("Ole1_embed_PDF").Visible = msoFalse 'False yerine msoFalse
'ama
ActiveSheet.OLEObjects("Ole1_embed_PDF").Enabled = True
Özellikler dışında bir de Activate ve Verb gibi metodlarla da
ilgilenebiliriz. Mesela bir pdf dokümanına tıklandığında onu açtıracak
kodu aşağıdaki gibi yazabiliriz.
Sub Ole1_embed_PDF_Click()
ActiveSheet.OLEObjects("Ole1_embed_PDF").Verb xlOpen
End Sub
ActiveX kontrolleri
ActiveX kontrollerinde ise durum biraz karışıktır. Bu case'de
OleObjectler, içinde bu kontrolü barındıran bir sarmalayıcı objeden
oluşur. Bazı durumlarda sarmalayıcının özelliklerini kullanmak bazen
içteki nesneyi bazen de ikisini kullanmak gerekebilir. Yine bunların bir
kısmına Shapes collection'ı üzerinden de ulaşabiliriz.
Bu iç kısımdaki esas objeye ulaşmak için OLEObject nesnesinin
Object
propertysi kullanılır, veya buna Shape nesnesi üzerinden ulaşıyorsak
önce Oleobject'yi elde etmek için OLEFormat'ı, sonra da bunun Object
property'si kullanılır. Özetle aşağıdaki ifadeler özdeştir:
Shapes("Ole1_embed_PDF").OLEFormat.Object ile OLEObjects("Ole1_embed_PDF") 'sarmalayıcı oleobject nesnesi
Shapes("Ole1_embed_PDF").OLEFormat.Object.Object ile OLEObjects("Ole1_embed_PDF").Object 'iç kısımdaki kontrol
Tüm OleObject'lerin aynı zamanda bir Shape de olduğunu söylemiştk. Peki bir
Shape döngüsü içindeyken veya bir şekilde elimizde bir shape nesnesi
varken bunların OleObect özelliklerine erişmek istersek ne
yaparız? Öncelikle OLEFormat özelliğini kullanırız. Bu
bize bir OleFormat nesnesi döndürür, bu nesnenin de
Object özelliğini kullanarak OleObject
nesnesine erişiriz. Bu nesne bir ActiveX nesnesi ise ilk Object property'siyle
sarmalayıcı nesneye erişmiş oluruz. OleObjectin sarmaladığı
içteki esas kontrole ulaşmak için ise bir Object
propertysi daha
kullanırız. Evet çok karışık oldu, farkındayım, şimdi hemen kodlara
bakalım, sonra açıklamayı tekrar okuyalım.
Mesela yukarıdaki pdf dokümanının Click eventine aşağıdaki kodu da
yazabilirdik.
Sub Ole1_embed_PDF_Click()
ActiveSheet.Shapes("Ole1_embed_PDF").OLEFormat.Object.Verb xlOpen
End Sub
Veya tüm Shapelerde dolaşırken OleObject olanların isim bilgisini
öğrenmek için aşağıdaki kodu yazabiliriz.
For Each şekil In ActiveSheet.Shapes
If TypeName(şekil.OLEFormat.Object) = "OLEObject" Then
Debug.Print şekil.OLEFormat.Object.Name
End If
Next şekil
İç kısımdaki objeye ulaştıktan sonra bu sefer onun özelliklerine
erişebilrsiniz. Malesef adından anlaşılacğı üzere bu bir Object olduğu
için intellisense çıkmamaktadır. İnstellisenseten yaralanmak isterseniz
ilgili tipte bir nesne tanımlamanız gerekir. Aşağıdaki örnekte sayfada
duran iki adet CommandButtonun Caption özelliklerine ulaşıyorum, tabi
bunların Caption özelliğine sahip olduklarını bildiğimiz için
intellisense çıkmamış olsa bile ezberden yazabiliyoruz.
Sub oledetay()
Dim şekil As Shape
Dim oo As OLEObject
For Each şekil In ActiveSheet.Shapes
Set oo = şekil.OLEFormat.Object
Debug.Print oo.Name, oo.OLEType, TypeName(oo), TypeName(oo.Object), oo.Object.Caption, oo.Left
Next şekil
End Sub
Sonuç:
CommandButton1 2 OLEObject CommandButton Düğme1 66
CommandButton2 2 OLEObject CommandButton Düğme2 150,6
Dikkat ettiyseniz sarmalayıcının Type'ı OLEObject iken iç nesnelerin
CommandButton çıkıyor.
Özelliklere erişim yöntemleri
Şimdi buraya kadar öğrendiklerimizi yice pekiştirmek adına 3 tür
erişim şekline bakalım.
Gömülü nesne(PDF dokümanı, Word veya PowerPoint dokümanı v.s) için
Visible özelliği
Shape üzerinden
ActiveSheet.Shapes("Ole1_embed_PDF").Visible = msoFalse
OleObject üzerinden
Buna da istersek OleObject nesnesi üzerinden doğrudan veya Shape
üzerinden dolaylı olarak erişebiliriz.
ActiveSheet.OLEObjects("Ole1_embed_PDF").Visible = True 'Doğrudan
'veya
ActiveSheet.Shapes("Ole1_embed_PDF").OLEFormat.Object.Visible = True 'Dolaylı
ActiveX kontrolü ile Visibile özelliğine erişim
Shape üzerinden
ActiveSheet.Shapes("Ole2_embed_ActiveXcmdbuton").Visible = msoFalse
OleObject üzerinden
Buna da istersek OleObject nesnesi üzerinden doğrudan veya Shape
üzerinden dolaylı olarak erişebiliriz.
ActiveSheet.OLEObjects("Ole2_embed_ActiveXcmdbuton").Visible = True 'Doğrudan
'veya
ActiveSheet.Shapes("Ole2_embed_ActiveXcmdbuton").OLEFormat.Object.Visible = True 'Dolaylı
NOT:Visible özelliği sadece sarmalayıcı obje için sözkonusudur,
dolayısıyla içteki Obje'ye ulaşarak bu nesnenin Visible özelliğine değer
atayamayız.
ActiveX kontrolü ile Enabled özelliğine erişim
Shape üzerinden
Shape'in bu özelliği bulunmamaktadır.
OleObject üzerinden
Buna da istersek OleObject nesnesi üzerinden doğrudan veya Shape
üzerinden dolaylı olarak erişebiliriz.
ActiveSheet.OLEObjects("Ole2_embed_ActiveXcmdbuton").Enabled = False 'Sarmalayıcı nesneye doğrudan
'veya
ActiveSheet.Shapes("Ole2_embed_ActiveXcmdbuton").OLEFormat.Object.Enabled = False 'Sarmalayıcı nesneye dolaylı
Ayrıca Enabled özelliği, içteki esas kontrol için de bulunduğu için
içteki nesne üzerinden de ulaşabiliriz.
ActiveSheet.OLEObjects("Ole2_embed_ActiveXcmdbuton").Object.Enabled = True 'İç nesneye doğrudan
'veya
ActiveSheet.Shapes("Ole2_embed_ActiveXcmdbuton").OLEFormat.Object.Object.Enabled = True 'İç nesneye dolaylı
ActiveX kontrolü ile FontSize özelliğine erişim
Shape üzerinden
Shape'in bu özelliği bulunmamaktadır.
OleObject üzerinden
Yukarıdaki Visible özelliğinde
karşılaştığımız durumun tersine Font'un Size bilgisi gibi bilgilere sadece
iç
nesne aracılığı ile ulaşılmaktadır. Dış nesneden bu özelliğe erişim
yoktur.
ActiveSheet.OLEObjects("Ole2_embed_ActiveXcmdbuton").Object.Font.Size = 11 'Doğrudan
'veya
ActiveSheet.Shapes("Ole2_embed_ActiveXcmdbuton").OLEFormat.Object.Object.Font.Size = 14 'Dolaylı
Özelliklere erişimle ilgili örnek
Örnek dosyamız üzerindeki tüm shape'lerin çeşitli bilgilerini
aşağıdaki gibi yazdırmak için bir kod yazalım.
Başlıkları manuel yazdığımızı düşünecek olursak, L2 hücresine
konumlanıp aşağıdaki kou çalıştırınca bu çıktıyı elde ederiz.
Sub shapleerde_dolaş()
Dim şekil As Shape
Dim dict As New Dictionary
'OLEType,FormControlType ve AutoShapeType'lar da dictionary yapılarak isimleri yazdırılabilir
'OleType basit: (0,1,2:Linkli, Embedded, Control)
'https://docs.microsoft.com/en-us/office/vba/api/excel.xlformcontrol,
'https://docs.microsoft.com/en-us/office/vba/api/office.msoautoshapetype
dict.Add 1, "msoAutoShape"
dict.Add 2, "msoCallout"
dict.Add 20, "msoCanvas"
dict.Add 3, "msoChart"
dict.Add 4, "msoComment"
dict.Add 27, "msoContentApp"
dict.Add 21, "msoDiagram"
dict.Add 7, "msoEmbeddedOLEObject"
dict.Add 8, "msoFormControl"
dict.Add 5, "msoFreeform"
dict.Add 28, "msoGraphic"
dict.Add 6, "msoGroup"
dict.Add 24, "msoIgxGraphic"
dict.Add 22, "msoInk"
dict.Add 23, "msoInkComment"
dict.Add 9, "msoLine"
dict.Add 29, "msoLinkedGraphic"
dict.Add 10, "msoLinkedOLEObject"
dict.Add 11, "msoLinkedPicture"
dict.Add 16, "msoMedia"
dict.Add 12, "msoOLEControlObject"
dict.Add 13, "msoPicture"
dict.Add 14, "msoPlaceholder"
dict.Add 18, "msoScriptAnchor"
dict.Add -2, "msoShapeTypeMixed"
dict.Add 19, "msoTable"
dict.Add 17, "msoTextBox"
dict.Add 15, "msoTextEffect"
dict.Add 26, "msoWebVideo"
dict.Add 25, "msoSlicer"
For Each şekil In ActiveSheet.Shapes
'ilk 3ü ole
If şekil.Type = msoEmbeddedOLEObject Then
Dizi = Array(şekil.Type, dict(şekil.Type), şekil.Name, şekil.OLEFormat.progID, şekil.OLEFormat.Object.Name, TypeName(şekil.OLEFormat.Object), "TypeName(şekil.OLEFormat.Object.Object)", şekil.OLEFormat.Object.OLEType)
ElseIf şekil.Type = msoLinkedOLEObject Then
Dizi = Array(şekil.Type, dict(şekil.Type), şekil.Name, "ole ama linkte N/A", şekil.OLEFormat.Object.Name, TypeName(şekil.OLEFormat.Object), "TypeName(şekil.OLEFormat.Object.Object)", şekil.OLEFormat.Object.OLEType)
ElseIf şekil.Type = msoOLEControlObject Then
Dizi = Array(şekil.Type, dict(şekil.Type), şekil.Name, şekil.OLEFormat.progID, şekil.OLEFormat.Object.Name, TypeName(şekil.OLEFormat.Object), TypeName(şekil.OLEFormat.Object.Object), şekil.OLEFormat.Object.OLEType)
'form butonu
ElseIf şekil.Type = msoFormControl Then
Dizi = Array(şekil.Type, dict(şekil.Type), şekil.Name, "N/A", "N/A", "N/A", "N/A", şekil.FormControlType)
'diğer hepsi
Else
Dizi = Array(şekil.Type, dict(şekil.Type), şekil.Name, "N/A", "N/A", "N/A", "N/A", şekil.AutoShapeType)
End If
Range(ActiveCell, ActiveCell.Offset(0, 7)).Value = Dizi
ActiveCell.Offset(1, 0).Select
Next şekil
End Sub