Bu siteye giriş yaparak Çerez kullanımını kabul etmiş oluyorsunuz. İşbu sitede; çerez olarak, sadece son giriş tarihiniz ve eğer üye olursanız oturum statünüz tutulacaktır. Bunlar dışında başka hiçbir bilgi tutulmamaktadır. Çerezler için detaylı bilgi için buraya tıklayınız.
ANLADIM

DUYURULAR

Yeni eklenen ve/veya güncellenen sayfaları görmek için buraya tıklayınız.

Güncel ödev ve test listesini görmek için buraya tıklayınız.

Sitede yapılan iyileştirmeAer ve hata düzeltmelerine ait tüm bilgilendirmeleri görmek içinburaya tıklayınız.

Baş
Udemy
Konular
Son
Konular
Workbook
DortTemelNesne
VBAMAkro
VBAMakroDört Temel Nesne3

Workbook

Giriş

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.

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. (Bu detayları yeri geldikçe göreceğiz). 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 event handlerına benzer bir de Auto_open prosedürü 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.

Biz henüz eventlere(olaylara) gelmedik, neden bundan bahsediyorum. İş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.

Sub versiyonkontrol()
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
End Sub

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'm 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 Hayalet Protokol 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)

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

Logger "Giris", 0, "Giris yapildi ve 21:00e 'kapat' schedule ediliyor"
Application.OnTime TimeValue("21:00:00"), Procedure:="kapat" '10 dk sonrasına tekrar refreshliyorum

'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 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 bunun 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)

isim=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 ProtectStructure ö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.

TEST SORULARI

Son Sorumuz şuymuş:Bir metindeki tüm noktaları yoketmek istiyorsunuz. Hangi fonksiyonu kullanırdınız?
Soru:

A şıkkı:

B şıkkı:

C şıkkı:

D şıkkı:

Doğru Cevap Etiketler

İlişkili konuyu seç

194068

Label
* Sorulara verilen yanlış cevaplardaki esprili yorumlarım için hoşgörünüze sığınıyorum.
* Test ve Ödevlerdeki bazı detaylar burada anlatılmamış olabilir. Bunları kendiniz araştırıp bulmalısınız.
* Birden çok konuya ait içeriği olan ödevler var. Algoritmik açıdan bakıldığında o an en uygun konuya adreslenmiştir.
Dikkat! Bir soruya cevap verdikten sonra geri dönemezsiniz.
1
0
0
0

Soru No:96. Aşağıdakilerden hangisi yanlıştır?





ÖDEVLER

4
0
Ödev No:20. Worksheet sayfasındaki19 nolu ödevde indirdiğiniz ekli dosyadasındaki(dörttemelnesne_2.xlsx) her bir sayfayı ayrı workbook olarak kaydedin. Dosyaların kaydolacağı klasörü kullanıcıya sorsun.
Çözüme bakın(Başka türlü de çözülebilir tabi, bu benim çözümüm.)

Sub Odev_20()
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 = ActiveWorkbook
  
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
 
Application.ScreenUpdating = True
Exit Sub
 
hata:
Application.ScreenUpdating = True
MsgBox Err.Description
End Sub



=YORUMLAR ve SORULAR=


DEVİR UYARISI

Herkese merhaba. Hosting maliyetlerinin aşırı artması yüzünden sitemi yakın zamanda(en geç Mayıs 2023) kapatmaya karar vermiştim. Ancak, siteyi yakından takip eden bir arkadaş siteyi devralmak istemiştir. Siteyi, Mayıs ayında kendisine devir etmeye karar verdim. Üyelik bilgilerini bana güvenerek girdiğiniz için, hepsini silmiş bulunuyorum, yani mail adreslerinizi kimseyle paylaşmamış olacağım. Bilginizi rica ederim.