28.12.2017 tarihinde,VBA konularına Dosya Okuma/Yazma sayfası eklenmiştir.

20.12.2017 tarihinde,sitem mobil uyumlu hale gelmiştir.

02.12.2017 tarihinde,Excel Fonksiyon konularına "Dizi Formülleri ve SUMPRODUCT" sayfası eklenmiştir.

31.10.2017 tarihinde,VBA Dictionary sayfasına Dictionary, Collection ve Collection dizisinden oluşan ilginç bir örnek eklenmiştir.

26.10.2017 tarihinde,Excel Fonksiyon konularına "İsatistiki ve Matematiksel fonksiyonlar" sayfası eklenmiştir.

VBAMakroDört Temel Nesne3

Workbook

Excel uygulamasında o anda açık olan tüm dosyalar Workbooks koleksiyonunu oluşturur ve Workbook nesnesi de bu Workbooks koleksiyonunun bir üyesidir.Bu site boyunca bazen Workbook ifadesini bazen dosya ifadesini kullanacağım.

Bu arada bir de Window nesnesi vardır ki, çoğu durumda Workbook nesnesi ile özdeş kullanılabilir. Window'un farkı şudur, bir dosya açtığınızda bu tek bir workbooktur, ancak bunu birkaç pencere şeklinde gösterebilirsiniz, işte bunların her biri Window nesnesidir. Bu nesneye de yer yer değinip onun özelliklerini de incelyeceğiz. Bu window(pencere) konusunu tam bilmiyorsanız Google'da Excel Window araması yapabilir, ek bilgi alabilirsiniz. Basit bir konu olduğu için sitenin Excel bölümünde buna değinmeye gerek görmedim.

Temeller

Erişim

Workbooklar 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 Workbooks.Items(1) ile Workbooks(1) tamamen özdeştir. Koleksiyonlarda indexler 1'den başlar, ilk açılan dosyanın indexi 1'dir.

Workbooklara index numarasıyla olduğu gibi dosya adı ile de, Workbooks("Bütçe2016.xlsx") gibi, ulaşabiliriz. Dosya ismini Window nesnesi ile de kullanabiliriz. Windows("Bütçe2016.xlsx") gibi.

Mevcut bir Workbook'u Açma

Diskte kayıtlı olan bir dosyayı Open metodu ile açarız. Hemen makro kaydedici ile bir dosya açıyorum ve koduma bakıyorum.

Sub Macro3()
     Workbooks.Open Filename:="C:\Users\Volkan\Desktop\deneme.xlsx
End Sub

NOT:Bunu yazarken Filename ifadesini kullanmadan veya parantez içinde şöyle de yazabilirdim: Workbooks.Open ("C:\Users\Volkan\Desktop\a.xlsx"). Parametre yazımının detayları için buraya bakınız.

Open metodunun birçok parametresi var ama ben burada sadece önemli olduğunu düşündüğüm 2 parametreden bahsetmek istiyorum. Bunlardan ilki ReadOnly parametresi. Şimdi diyelim ki, kullanıcılar için UserForm kullanarak bir arayüz veya bir Add-in oluşturdunuz. Oradaki bir buton da bir dosyayı açacak, ama dosyada ara ara güncellemeler yapmanız gerekiyor, hatta dosyayı schedule programına aldınız ve gece belirli bir saatte açılıp refresh olacak ve kaydedilecek. Bunun için dosyanın kimsede açık olmaması lazım. O yüzden kullanıcılar bu butona tıkladıklarında bunun Readonly açılmasını sağlamak akıllıca olurdu. İşte bu parametre ile bunu yapabiliyoruz, tabi buna True değerini atayarak.

Peki, diyeceksiniz ki, "Bizim bölümdeki bazı kullanıcılar çok cin veya umarsız, onlara hazırladığım arayüzü/add-ini değil de doğrudan dosyanın bulunduğu klasörden dosyayı açabilirler". Bunun da çözümü var, Dosyanın Workbook_Open event modülüne dosyanın Readonly açılıp açılmadığını kontrol eden bir kod yazarsınız. Kodlar şöyle olacaktır:

'dosyayı açmaya yarayan kod
Sub dosyaac()
    Workbooks.Open "C:\Users\Volkan\Desktop\deneme.xlsx", ReadOnly:=True
End Sub

'bu dosyanın Workbook_Open modülü
Sub Workbook_Open()
'ilk başta açan kullanıcının sizin dışında bir kullanıcı olup olmadığı kontrolü yapaım
If Environ$("computername") = "bilgisayar adınız" then Exit Sub 'veya username ile de kontrol edilebilir

If Me.Readonly=False Then 
	MsgBox "Lütfen Add-in üzerinden giriş yapınız"
	Me.Close SaveChanges:=False
End If
End Sub

İkinci önemli parametre de Updatelinks'tir. Bu parametre ile, dosya açıldığında içinde başka workbooklara link varsa bunların güncellenip güncellenmeyeceğini belirtmiş oluruz. Eğer bu parametre belirtilmediyse Excel bize sorar. DisplayAlerts=False kullanımının baskılayamadığı tek uyarı şekli budur, o yüzden bunu kendi içinde halletmemiz gerekir. 0, güncelleme yapılmasın; 3, yapılsın demektir.

Linklerle ilgili bir başka önemli metod da LinkSources metodu olup, bir dosyanın başka bir dosyadan(veya MS uygulamasından) link alıp almadığını gösterir. Bu metodun dönüş değeri dizidir. Tüm linkleri bir dizi içinde ayrı elemanlar olarak depolar. Eğer link yoksa dizi boştur ve IsEmpty ile yakalanabilir.

linkler = ActiveWorkbook.LinkSources(xlExcelLinks) 
If Not IsEmpty(linkler) Then 
 For i = 1 To UBound(aLinks) 
    MsgBox "Link " & i & ":" & Chr(13) & linkler(i) 
 Next i
Else
  MsgBox "Dosya başka dosyalara link içermemektedir."
End If	

Auto_open makrosu

Workbook_Open makrosuna benzer bir de Auto_open makrosu vardır. Bu, daha çok eskiden kullanılırdı, ancak Excel 2000'den sonra Workbook_Open event makrosu devreye girdiği için buna pek gerek kalmadı, eski makroları destek adına yaşamaya devam ediyor. O yüzden olur da elinizde sizden önce birilerinin yazdığı bir Auto_open kodu varsa ve bunu değiştirmek istemiyorsanız aşağıdaki bilgi önemli olacaktır.

İşte, VBA içinden çalışan bir Open metodu Auto_open makrosunu tetiklemez, bu makro sadece dosya manuel olarak yani Excel içinden veya Windows Explorerdan açıldığında tetiklenir. Bunun için ayrıca dosyayı açtıktan sonra bir de şu kodu eklemek lazım.

Workbooks.Open "C:\Users\Volkan\Desktop\deneme.xlsx"
ActiveWorkbook.RunAutoMacros xlAutoOpen

Bu arada Workbook_Open makrosunda dosyanın nasıl açıldığı önemli değildir. Manuel de açılmış olsa, kod ile de açılmış olsa tetiklenir.

Dosya Kapatma

Close metodu ile dosyalar kapatılır.

Bu metodun en önemli parametresi kapatırken kaydedip kaydetmemeye yarayan Savechanges parametresidir.

Aşağıdaki kod ile, aktif dosyayı kaydederek kapatıyoruz.

Sub kapama()
   Activeworkbook.Close savechanges:=True
End Sub

Open metodunda olduğu gibi, eğer bir Auto_close makrosu varsa, bu makro Workbook.Close metodu ile tetiklenmez, dosya X işaretine basılarak kapatıldığında tetiklenir. Bunun için Open metodunda olduğu gibi şu kod eklenmelidir, ancak bu sefer close işleminden önce eklenmelidr.

ActiveWorkbook.RunAutoMacros xlAutoClose
ActiveWorkbook.Close Savechanges:False

Aşağıdaki örnekte, açık olan tüm dosyaları kapatan ama kapatmadan önce kaydetip kaydedilmeyeceklerini soran bir kod bulunuyor. Tabi Personal.xlsb gibi gizli dosyalarda bu işlemi atlıyoruz, yoksa tüm Excel kapanır. Ayrıca henüz kaydedilmemiş dosyalar için ayrı bir işlem uyguluyoruz.

Sub tümdosyaları_kapat()
Dim wb As Workbook

cevap = MsgBox("Kapatırken save edeyim mi", vbYesNoCancel)
If cevap = vbYes Then
    a = True
ElseIf cevap = vbNo Then
    a = False
Else
    Exit Sub
End If


For Each wb In Application.Workbooks
    Workbooks(wb.Name).Activate
    If Windows(wb.Name).Visible = True Then
        If InStr(ActiveWorkbook.Name, ".") = 0 Then 'henüz kaydedilmemiş bir dosyaysa
            wb.SaveAs Filename:=Application.DefaultFilePath & "\" & wb.Name & ".xlsx", _
                FileFormat:=Application.DefaultSaveFormat, CreateBackup:=False
                ActiveWindow.Close
        Else
            wb.Close savechanges:=a
        End If
    End If
Next wb
End Sub 

Yeni Dosya Yaratma

Yeni bir dosya yaratacağımız zaman Add metodunu kullanırız. Bağımsız bir satırda kullanacağımız gibi aynı anda bir değişkene de atayabiliriz.

Sub yenidosya()
Dim wb as Workbook

Set wb=Workbooks.Add
End Sub

Dosya Kaydetme

Basit kaydetme işlemi Save metodu ile, farklı kaydetme işlemi ise SaveAs metodu ile yapılır. Save metodu parametre almaz, dosyayı sadece kaydeder. SaveAs metodunun birkaç parametresi vardır.

Tüm syntax şöyle: SaveAs(FileName,  FileFormat,  Password, WriteResPassword, ReadOnlyRecommended,  CreateBackup, AccessMode, ConflictResolution, AddToMru,  TextCodepage, TextVisualLayout, Local)

FileName ile dosyaya ne isim vereceğimizi belirtiriz, bu isim klasör ismini de içerebilir, klasör belirtilmezse Default kaydetme klasörüne kaydedilir.

FileFormat ile dosya formatının ne olacağına karar veririz.

Belli başlı dosya formatları şöyle olup, tüm listeye buradan ulaşabilirsiniz. Parantez içindeki değerler enumaration sabitleridir, kodlarınızda parantez içi de dışı da kullanılabilir.

İsim(Değer)Açıklama ve uzantı
xlExcel12(50)2007 sonrasında binary format, xlsb
xlWorkbookDefault(51)2007 sonrasında gelen klasik format, xlsx
xlOpenXMLWorkbookMacroEnabled(52)2007 sonrasında gelen makrolu format, xlsm
xlExcel8(56)2007 sonrasında eski klasik format, xls
xlWorkbookNormal(-4143)2007 öncesinde klasik format, xls

Dosya kaydetme işlemlerinde Excel versiyon kontrolünü de yapmak, zorunlu olmasa da, hataları ele alması açısından akıllıca bir yol olacaktır. (Versiyon numaralarına buradan ulaşabilirsiniz.)

Aşağıda örnek bir kod bulunmaktadır.

Dim wb As Workbook
Dim uzantı As String
Dim frmt As Integer

Set wb = ActiveWorkbook
 
If Val(Application.Version) < 12 Then
'2007 öncesini kullanıyorsunuzudur
   uzantı = ".xls": frmt = -4143
Else
'2007 sonrasını kullanıyorsunuzudur
cevap = MsgBox("Eski formatta mı kaydetmek istiyorsunuz?", vbYesNo)
   If cevap = vbYes Then
      uzantı = ".xls": frmt = 56 'belki bu dosyayı 2003 kullanan bir alıcıya göndereceksinizidr
   Else
      uzantı = ".xlsx": frmt = 51
   End If
End If
 
wb.SaveAs Filename:="Yenidosya" & uzantı, FileFormat:=frmt

Bir kaydetme metodu daha vardır, bu metod dosyanın o anda bulunan halini (kendi üzerinde kayıt işlemi yapmadan) başka bir yere kaydetmeye yarayan SaveCopyAs metodudur. Mevcut dosya üzerinde kayıt işlemi yapmadan, ama bu halini de saklaması adına güzel bir metoddur. Yani özetle, SaveAs açık dosyayı o andaki değişiklikleriyle kaydederken, SaveCopyAs, açık dosyayı aynen bırakır, buna herhangi bir kaydetme işlemi uygulamaz, ancak son değişklikleri içeren halini farklı bir isimde kaydeder. Bu da SaveCopyAs'i yedekleme amacına hizmet etmesi için harika bir metod yapar.

Mesela aşağıdaki kod Ribbonunuzda kısayol tuşu olarak bile atayabileceğiniz güzel bir koddur.(FileDialog işlemlerini ayrıca göreceğiz)

Sub anlık_yedekal()
'kodun sağlıklı çalışması için References içinde Microsoft Scripting Runtime kütüphanesi eklenmiş olmalı
'eğer bu kütühane ekli değilse ve şuan eklemeyi tam bilmiyorsanız aşağıdaki satırı diğer iki set cümlesinin altına ekleyin
'Set fso = CreateObject("Scripting.FileSystemObject")
 
Dim adres As String
Dim isim As String
Dim fd As FileDialog
Dim wb As Workbook
Dim fso As New FileSystemObject
 
Set wb = ActiveWorkbook
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
 
fd.ButtonName = "Seçin"
fd.Title = "Kayıt yeri seçin"
fd.InitialFileName = wb.path
 
If fd.Show = -1 Then
    adres = fd.SelectedItems(1)
    isim = InputBox("Dosya ismi ne olsun", Default:=fso.GetBaseName(wb.Name) & ".... yapmadan önceki yedek")
   
    wb.SaveCopyAs (adres + "\" + isim + "." + fso.GetExtensionName(wb.Name))
End If
End Sub	

Network üzerinde kaydetme işlemi

Network üzerinde bir yere kayıt yaparken bazen bir bug(hata) nedeniyle kaydetme işlemi ekranda takılı kalmaktadır. Bunun ne zaman olacağı asla kestirilememekte(%3-5 ihtimal diyebilirim) ve Microsoft da malesef bu soruna bir çözüm bulabilmiş değildir. Eğer schedule edilmiş bir iş sırasında başınıza bu gelirse sonrasında çalışması gereken tüm makrolar durmaktadır, bu da gününüzün iyi geçmemesi için yeterli bi gerekçe olabilir.

Bununla beraber bu konuda bir çözüm bulunmaktadır. Sırayla şu adımlar uygulanmalıdır.

  • Dosya önce yerel makinaya kaydedilir
  • Sonra bu dosya kapatılır
  • Sonra dosya kapalıyken yerel diskten networkteki klasöre kopyalanır
  • Yerel diskteki dosya silinir

Bunun kod örneği aşağıdaki gibidir.

Sub çağıran()
  '.....
  '.....
  hedef=ActiveWorkbook.FullName
  saveas_islemi(hedef)
End Sub

Sub saveas_islemi(ByVal hdf As String)
  Application.DisplayAlerts = False
  ActiveWorkbook.SaveAs Filename:="C:\geçici\geçici.xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled 'burda dosya isminin ne olduğu önemli dğeil bile
  Kaynak = ActiveWorkbook.FullName

  ActiveWorkbook.Close 'filecopy yapmadan önce dosyayı kapatmak lazım yoksa izin vermiyor
  FileCopy Kaynak, hdf
  Kill Kaynak
  Application.DisplayAlerts = True
End Sub

NOT:Eğer bu işlemin Workbook_Open prosedürü içinde yapılması gerekirse ikinci bi geçici dosya daha yaratmak gerekecektir.

İleri Seviye işlemleri

Workbook kaydedilmiş mi kontrolü

Dosya üzerinde, son açıldığından beri bir değişiklik yapılıp yapılmadığını görmek için Saved özelliği kullanılır. True dönerse, son açılışından beri bir değişiklik yapılmadığını gösterir.

Bu property, özellikle Excel'i kapatırken işe yarar. Şöyle ki, diyelim ki belli bir saatte Excel'i kapatmak istiyorsunuz, kapatırken de o anda tüm açık dosyaları sanki kayıtlıymış gibi göstermeniz gereken durumlar olabilir. Olayı daha somutlaştırmak adına yine kendi işimden örnek vermek istiyorum.

Normalde işimi yaptığımı PC'mde dışında Application.Ontime örneklerinde bahsettiğim bir de laptop'ım var, orda da scheduled makrolar çalışıyor. Bunların dışında bir üçüncü bilgisayar daha var ki, bu da bir televizyona bağlı. Televizyonda 10 dk'da bir refresh olan birkaç rapor var, oradan tüm departman anlık olarak bu rapor sonuçlarını görüyor.

Bu bilgisayarı her akşam 21:00'de kapanacak, her sabah 08:30'da da açılacak şekilde ayarladım. Kapama işlemini makroyla, sabah açma işlemini Windows Task Scheduler'a yaptırıyorum. Sabah açılır açılmaz, 21:00'de kapatacak makroyu schedule ediyorum. Schedule etme işinin detaylarını bu sayfada detaylıca göreceğiz.

Bu projeyi örnek projeler bölümünde detaylıca ele alacağım. Şimdi sadece bizi ilgilendiren kısmının kodlarını inceleyelim.

Ön bir bilgi daha:Task Scheduler Exceli açar açmaz, XLSTART klasöründeki schedule.xlsb dosyası da açılıyor. Bunun Workbook_Open eventinde da birkaç dosyayı açan bir kod var. Açılan ilk dosya "Kredi raporu", aşağıdaki kodlar da bu kredi raporuna aittir.

'Öncelikle Workbook_Open makrosuna bakalım
Private Sub Workbook_Open()
'Öncül kodlar(tanımlamalar vs)
Static runCount As Integer 'statik değişken tanımlıyorum, her refreshte 1 artırılıyor. 

If Environ$("computername") = "A12345" Then 'TV bilgisayarıysa diye bakıyor. Çünkü bu dosyayı düm departmandakiler açabilir. Sadece TVye bağlı bilgisayrda otomatik refresfh devreye girmeli
   'kodlar
    Application.OnTime Now + TimeValue("00:10:00"), Procedure:="TVRefresh"
   'kodlar
End If

If runCount = 0 Then 'ilk kez açıldığında kapama scheule edilsin. bi dosya kaç kere açılır ki? diye düşünebilirsiniz. Cevap şu. Ana sayfada bir buton var, ona tıklandığında da Workbook_Open makrosunu çalıştırttırıyorum, o yüzden sayaç koydum
    Logger "Giris", 0, "Giris yapildi ve 21:00e 'kapat' schedule ediliyor"
    Application.OnTime TimeValue("21:00:00"), Procedure:="kapat"
    runCount = runCount + 1
End If

'Diğer kodlar

End Sub

'-------------------------------------------------------------------------
'şimdi de Workbook_BeforeClose'a bakalım
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error GoTo hata 'kapatma tuşuna basıp tüm bunlar yapıldıktan sonra hiç iptal edilecek schedule işşemi kalmıyor ama en son "şu dosyaları save edeyim mi" diye bi dialog çıkarıyor ya, buna cancel dediğimde Excelde kalmış oluyoruz, sonra ikinci bi kapat dediğinde iptal edecek bi schedule olmadığı için hata oluyor, o yüzden hata kontrolü koydum

If Hour(Now) < 21 Then
    Application.OnTime TimeValue("21:00:00"), Procedure:="kapat", Schedule:=False '21den önce kapatılırsa kapat'ın schedulını iptal ediyoruz
    Logger "Kapanis", 0, "21den once BeforeClose'a girildi ve SCH iptal edildi"
Else
    Logger "Kapanis", 0, "21de BeforeClose'a girildi ve kapanıyor"
End If
Exit Sub
hata:
If Err.Number = 1004 Then Resume Next
End Sub

'---------------------------------------------------------------------------
'son olarak da kapat makrosuna bakalım, bizim esas ilgilendiğimiz kısım burası
Sub kapat()
On Error GoTo hata

    If Environ$("computername") = "A12345" Then
        '.....
        
        For Each wb In Workbooks
            wb.Saved = True 'işte Saved özelliğini burada kullanıyorum,
        Next wb

        Logger "OtoKapanma", 0, "kapat makrosu ile TV'de kapaniyor"
        Application.Quit 'Burası ile de Excel kapatılıyor
    Else
        Logger "OtoKapanma", 0, "kapat makrosu ile kapaniyor"
        Windows("Anlık Kredi Raporu.xlsm").Close savechanges:=False
    End If
Exit Sub

hata:
Logger "Hata", Err.Number, "Kapat makrosunda hata:" & Err.Description
End Sub

Neden böyle yapıyoruz, bunu açıklayayım.

  • Kapat makrosu içine direkt Application.Quit dersem, Excel bana "şu şu dosyaları kaydedeyim mi" diye sorar ve ekran öylece kalır. Bu istediğim birşey değil.
  • Neden Workbook.Close deyip Savechanges özelliğine False atamıyorum? Çünkü böyle dersem kodun çalıştığı kredi dosyası kapanırsa(ki ilk o kapanacaktır çünkü ilk açılan dosya o) kalan dosyalar için kapatma işlemi uygulanmaz.
  • Tüm dosyaları kaydedip neden kapatmıyorum? Çünkü dosyalar readonly açılıyor, kaydedilemez; gerçi readonly açılmasa bile kaydetme işlemini TV bilgisayarında yaptırmazdım.
  • O yüzden dosyaların Saved özelliğine True atayıp, onları sanki kaydedilmiş gibi gösteriyorum ve böylece Excel'in bana soru sormamasını sağlıyorum.

Açık dosyalar arasında dolaşma

Tüm açık dosyalarda dolaşmak ve onlarda işlem yapmak için aşağıdaki basit kodu kullanabilrisiniz.

Sub wbisimleri()
Dim i As Integer

For i = 1 To Workbooks.Count
	'buraya diğer kodlar yazılır
Next i

End Sub	

Bazen Personal.xlsb gibi dosyaları hariç tutarak işlem yapmak isteriz.  Örneğin, açık olan tüm dosyalarınızı kapatmak isterseniz yukardaki kodu alıp araya Workbooks(i).Close dersek, bu kodu yerleştirdiğimiz Personal.xlsb de kapandıktan sonra hiç açık dosya kalmayacağı için Excel de kapanmış olur. O yüzden gizli dosyalar hariç bakalım demeliyiz. Ancak Workbook nesnesinin Visible diye bir özelliği yok, bunun yerine Window nesnesinin bu özelliğini kullanacağız. Bu durumda kodumuz aşağıdaki gibi olur.

Dim wb As Workbook
For Each wb In Workbooks
    If Windows(wb.Name).Visible = True Then
	'diğer kodlar buraya
    End If
Next wb	

Açık dosyalar arasında Window nesnesnin metodları aracılığı ile de dolaşabiliriz. Window nesnesi birçok açıdan Workbook'a benzese de, bir workbook içnde birden fazla window olduğu durumlarda biraz farklılaşma yaşanabilir. Pencereler arasında dolaşma ActiveWindow.ActivateNext ve ActiveWindow.ActivatePrevious metodları aracılığı ile olur, ilki bir sonraki pencereyi(workbooku) aktive ederken ikincisi bir öncekini aktive eder. İki dosya arasında git gel yaptığınız durumlarda oldukça kullanışlıdır. Ancak birden fazla dosyanın açık olduğu durumlarda karışıklığa neden olacağı için kullanmanızı tavsiye etmem.

ActiveWorkbook & ThisWorkbook & Me

Çoğu zaman birbiri yerine kullanılabilecek olan bu terimler arasında küçük farklar bulunmaktadır. ActiveWorkbook, o anda aktif olan dosya iken ThisWorkbook, kodun çalıştığı dosyadır. Mesela, bizim ana kod dosyamız olan Personal.xlsb dosyası gizli bir dosya olduğu için genelde activeworkbook dosya o olmayacaktır, ancak eğer ondaki bir kod çalışıyorsa ThisWorkbook o olacaktır.

Sayfa gibi bir nesnenin önünde Workbook ifadesi belirtilmediyse Excel bununu ActiveWorkbookun bir sayfası olduğunu düşünür. Bunun bir istisnası vardır: Eğer bir Workbook modülüne(ThisWorkbook) girildiyse ve burada bir Workbook adı belirtilmeden bir nesne mesela bir sayfa adı kullanılıyorsa, bu durumda bu nesne Activeworkbooka ait değil kodun çalıştığı workbooka ait olarak algılanır.

Başka bir örnek ise şöyle olabilir: Diyelim ki Kredi Format.xlsm diye bir dosyanız var, gece belli bir saatte çalışacak şekilde programlanmış olsun. Bu dosya ilgili saatte açıldığında, Workbook_Open makrosu devreye girsin ve bazı kodları çalıştırsın. Kodların bir bölümünde PersonelBilgileri.xlsx diye bir dosyayı açıp bundan sicil kodlarının yanına personelin ismini getirsin ve eğer kredi dosyasında personelbilgi dosyasında olmayan bir sicil varsa bunu bu dosyaya eklesin. Bu durumda kredi dosyasından copy yapılıp personel dosyasına paste işlemi yapılacağı için son açık görünen dosya yani activeworkbook, personelsicil dosyası olacaktır. O yüzden paste işleminden hemen sonra Activeworkbook.Close denirse, personelsicil dosyası kapatılmaya çalışılır. Thisworkbook.Close denirse, aktif dosya personel dosyası olduğu halde kredi dosyası kapatılmaya çalışılır, zaten o kapanırsa kod da durur, ve personel dosyası açık bir şekilde bekler.

Bu örneği biraz da aşama aşama görelim, yazım tekrarı olmaması adına ThisWorkbook'un kod boyunca hep Kredi dosyası olacağını söyleyelim ve sadece Activeworkbook'un değişimini izleyelim:

  • Kredi dosyası açılır açılmaz Workbook_Open devreye girdi --> Activeworkbook=Kredi
  • Personel dosyası açıldı-->Activeworkbook=Personel
  • Personelden krediye lookup yapılacak, kredi aktive edilir--> Activeworkbook=Kredi
  • #N/A gelenler Personel dosyasına eklenecek, personel aktive edildi ve yeni siciller yapıştırıldı --> Activeworkbook=Personel.
  • Önce personel dosyasını kapatmak için Activeworkbook.Close Savechanges:=True denir
  • Akabinde ThisWorkbook.Close Savechanges:=True denir ve kredi dosyası da kapanır

Bir de Me ifadesi vardır. Eğer kodumuz ThisWorkbook modülü içindeyse bu ifade, ThisWorkbook anlamında kullanılabilir. (Ancak Me'nin başka anlama geleceği durumlar da olabilir. Eğer, kodumuz bir sayfa modülü içindeyse mesela Sheet1 modülünüdeyse, Me=Sheet1'dir. Onun dışında Me'nin en çok kullanıldığı yer sanırım UserFormlardır. Bu durumda da Me, formun kendisi olmaktadır. Bunu formlar bölümünde göreceğiz.)

Dosya ismi ve adresi/klasörü

Dosyanın ismine Name özelliği ile ulaşırız. İsimden kastımız uzantı dahil isimdir. Ör:"Krediler.xlsx". Worksheet'in Name özelliğinden farklı olarak bu özellik Readonly'dir(Nesne model tanımınıda "Sets" yok, sadece "Returns" vardır), yani dosya adı dosya açıkken değiştirilemez. Ancak SaveAs veya SaveCopyAs ile dosyaları farklı isimde kaydetme imkanımız olabilir.

Name özelliği dosyanın sadece adı ve uzantısını verirken, Fullname özelliği tüm path'i de verir. Ör: "C:\Users\Volkan\Desktop\deneme.xlsx"

Bazen de dosya adını uzantısı olmadan almak isteriz, mesela uzantısız ismi alıp bu ismin sonuna bir ek ekleyip sonra tekrar uzantıyı eklemek isteyebilirsiniz. Bunun için birkaç yöntem var. Hepsini de göstermeye çalışacağım, başka yöntemler de bulunabilir tabiki, VBA'de bir sonucu elde etmenin binbir türlü şekli var sonuçta.

1.yöntem: FileSystemObject objesinin GetBaseName özelliğini kullanmak. Bu kanımca en ideal yöntemdir, zira her versiyon ve uzantıda işe yarar. Bunu yukarda anlık_yedek al makrosunda kullanmıştık.

CreateObject("Scripting.FileSystemObject").GetBaseName(ActiveWorkbook.name)

2.yöntem: Uzantının ne olduğunu biliyorsak, bunu "" yani sıfır uzunluklu metinle replace ederiz.

isim = Replace(ActiveWorkbook.Name, ".xlsx", "") 

3.yöntem: Dosya isminde nokta işareti olmadığından eminsek, noktanın yerini bulup oraya kadar olan ismi almaktır.(Dosya isminde nokta varsa bu yöntem işe yaramaz)

Left(ThisWorkbook.Name, (InStrRev(ThisWorkbook.Name, ".", -1, vbTextCompare) - 1))

4.yöntem: Uzantı kadar karakteri hariç tutup soldan yeterli sayıda karakter seçmek. Bu örnekte bir de versiyon kontrolü yapılabilir.

Dim i As Integer
If Application.Version = 12 Then 'Excel 2007 ve sonrasıysa
	If ActiveWorkbook.FileFormat=56 then 'xls uzantılıysa
		i=4
	Else
		i=5
	End If
Else 
	i = 4 
End If
   uzantısızisim= Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - i) 

Ve isterseniz bütün bunları bir fonksiyona da atayabilirsiniz.

Function uzantısızisim() As String
    Dim i As Integer 
    If Application.Version >= 12 Then
        If ActiveWorkbook.FileFormat=56 then
	   i=4
        Else
           i=5
	End If
    Else 
	i = 4 
    End If 
    uzantısızisim= Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - i) 
End Function 

Dosyanın bulunduğu klasör ismine Path özelliği, uzantısına da yine isminde olduğu gibi birkaç yolla ulaşılabilir, ben örnek olarak sadece FileSystemObject objesinin GetExtensionName özelliğini söyleyeyim, diğer yolları siz düşünün.

FileSystemObject nesnesine ayrıca bakacağımız için burada daha fazla detaya girmiyorum.

Workbook Protection

Excel'in Review menüsünden konulup kaldırılan şifre işlemleri elebetteki VBA ile de yapılabilmektedir.

Mesela genel kullanıma açık olan bir dosyanızda otomatik refresh işlemleri olduğunu düşünelim. Dosya gece çalışıp içindeki sorgular refresh edilecek ve bazı copy paste işlemleri olacak diyelim. Dosya genel kullanıma açık olduğu ve kimsenin gizli sayfalardaki veriye ulaşmasını istemediğiniz için dosyayı korumaya almış olabilirsiniz. Ancak gece dosya otomatik açıldığında işlemlerin öncesinde korumayı kaldırmalı, işler bitince tekrar korumayı aktive etmelisiniz. İşte kodumuz:

Private Sub Workbook_Open()

ThisWorkbook.UnProtect (1234)
'işlemler yapılır

ThisWorkbook.Protect (1234)
ThisWorkbook.Close Savechanges:=True

End Sub

Bir dosyada koruma olup olmadığını görmek için de özelliği kullanılır. Aşağıdaki örnekte belirli bir grup dosyada toplu connection şifre değişikliği gerçekleşecek ancak öncesinde her dosya için protection kontrolü yapılıyor.

'Belirli dosyaları files isminde bir collectiona atadım ve bu collection içinde dolanarak çeşitli işlemler yapacağım
For Each file In files
    Workbooks.Open Filename:=file
    Set wb = ActiveWorkbook
    If wb.ProtectStructure = True Then
        protectlimi = True
        wb.Unprotect (1234) 
    End If
        
    For Each cn In wb.Connections
        If InStr(cn.ODBCConnection.Connection, eski) > 0 Then
            cn.ODBCConnection.Connection = Replace(cn.ODBCConnection.Connection, eski, yeni)
        End If
    Next cn

    'protection olanlarda tekrar koyalım
    If protectlimi = True Then wb.Protect (1234)
    protectlimi = False 'tekrar false yapıyorum ki, döngüye tekrar girdiğinde True olarak gitmesin    
Next file	

Diğer

Workbook'un başka özellik ve metodları da bulunmaktadır. Ben burada önemli olduğunu düşündüklerimi vermeye çalıştım. Sizler diğer üyeleri araştırabilir ve kendiniz deneyebilirsiniz.

Bununla beraber RefreshAll ve Connection gibi üyeleri ise VeriTabanı işlemlerinde ayrıca ve detaylıca ele alacağım için burada değinmedim.

YORUMLAR