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.

VBAMakro Dosya işlemleri 1

Dosya ve Klasör erişimi

Makro yazarken zaman zaman dosyaların/klasörlerin adını değiştirmek, taşımak, kopyalamak, silmek v.b gibi manipule edici; bazen de bunların adını, bulunduğu klasörü, adresini, dosya uzantısını öğrenmek v.b gibi bilgi edinici işlemler yapmak isteriz.

Bu tür işlemler için iki temel modül var. FileSystemObject(FSO olarak anılacak) Class Modülü ve FileSystem(FS) Modülü.

FS normal bir modül olduğu için bunlardaki fonksiyonları doğrudan kullanabiliyoruz. O yüzden FSO ile yapacak başka işlemimiz yoksa her zaman FS fonksiyonlarını tercih etmeliyiz, tabi FS ile yapılamayan işlemleri de mecburen FSO ile yapmamız gerekecektir.

Şimdi bunlara detaylıca bakalım. (Her zaman olduğu gibi sadece işimize yarayan veya yarama ihtimali olan üyelere bakıyor olacağız. Ayrıca başka sayfanın konusu olan üyelere o sayfalarda yer vereceğiz.)

NOT:Klasör/Dosya açma/seçme v.s gibi işlemleri bu bölümde değil burada görüyoruz.

FileSystemObject(FSO)

Giriş

FSO nesnesi, web server üzerinde VBScript diliyle kullanılmak için yaratılmıştır(ancak tabiki VBA dünyasından da kullanıma girmiştir). Bu yüzden ayrı bir dll(library) içinde bulunur: Scripting Runtime. Bu nesneyi kullanabilmek için Tools>Reference menüsünden aşağıdaki gibi eklemek gerekir.(Tabi ki bu iş early binding için geçerli, late binding için böyle bir işleme gerek yoktur.)

Late binding için ise aşağıdaki gibi bir kod yeterli olacaktır. Ancak biz kodlarımızda genellikle early binding kullanacağımız için devam etmeden önce bu library'yi eklemenizi tavsiye ederim.

Set FSO = CreateObject("Scripting.FileSystemObject") 'Late binding

Nesne Hiyerarşisi

Dosya işlemleriyle ilgili olarak tepede FSO objesi bulunmaktadır. FSO kendi altında sırasıyla şu nesneleri bulundurur.

  • Drive
  • Folder
  • File
  • TextStream

FSO'yu, bu nesnelerle genelde doğrudan değil de metodları aracılığı ile iletişime sokuyoruz. Yani bir klasörü silmek için önce FSO'dan bir Folder nesnesi üretip sonra Folder nesnesinin DeleteFolder metoduyla silme işlemini yapıyoruz.(Her zaman böyle değil tabi, aşağıdaki bu konuyla ilgili detay bilgi bulunuyor). Madem ki bu nesneyi doğrudan kullanmayacağız, ikide bir bu nesneden yaratmamak için bunu global seviyede public olarak tanımlamak akıllıca olacaktır. Public tanımlamayacaksak her prosedürün sonunda buna Nothing değerini atamak bellek yönetimi açısından iyi olacaktır.

Şimdi bu silme işlemine ait örneğe bakalım.

Public fso As New FileSystemObject 'global tanımlama
Sub foldersil()

fso.DeleteFolder "C:\Users\Volkan\Desktop\ıvır zıvır"

End Sub	

FSO'nun en sık kullanacağımız 2 temel metodu şöyledir:

  • GetFolder:Folder(Klasör) nesnesi döndürür.
  • GetFile:File(Dosya) nesnesi döndürür.

Bu ikisinden başka metodlar da var tabi ama bu ikisinin özelliği, diğer 2 temel nesneyi yaratıyor olmaları.

Bu nesnenin metodlarına daha genel bir bakış ise şöyle olacaktır.

Metodlar Görevleri
GetDrive, GetFolder, GetFile Yukarda bahsettik.
CreateFolder, CreateTextFile Yeni klasör ve dosya yaratır.
DeleteFile, DeleteFolder Klasör ve Dosya siler
CopyFile, CopyFolder Klasör ve Dosya kopyalar
MoveFile, MoveFolder Klasör ve Dosya taşır
DriveExists, FolderExists, FileExists İlgili birim mevcut mu kontrolü yapar

NOT:Fso işlemlerinde ilgili dosya/klasör adresi verilirken son karakterin "/" olup olmaması önem arzetmemektedir. Yani "C:\deneme" ile "C:\deneme\" özdeştir.(Ancak daha aşağıda göreceğimiz gibi "Dir" ile kullanırken durum farklıdır.)

Folder ve File işlemleri

Folder/File işlemlerinde akılda tutulması gereken en önemli şey, öncelikle dosyanın varolup olmadığını öğrenmeye alışmaktır. Dosya özellikle Application.FileDialog ile kullanıcıya seçtirilmemişse bu kontrol işlemini mutlaka yapın derim. (FileDilaog ile yapılan seçimlerde bu kontrole gerek yoktur.)

Var mı? kontrolü

Bunun içn FileExists ve FolderExists metotlarını kullanırız. 

Sub kontrol_fso()

If fso.FileExists("C:\Users\Volkan\Desktop\denemeler\deneme.xlsx") Then
    Debug.Print "Dosya var"
End If

If fso.FolderExists("C:\Users\Volkan\Desktop\denemeler\") Then 'sonda \ olup olmaması farketmez
    Debug.Print "Klasör var"
End If

End Sub

Klasör içindeki klasörleri elde etme

Bu işlem için SubFolders property'si kullanılır, bu özellik bize Folders collection'ı döndürür. Gerisi ForEach yapmaktan ibarettir.

Sub KlasördekiKlasörler()

Dim anaklasorStr As String
Dim fol As Folder, alt As Folder

anaklasorStr = "C:\Users\Volkan\OneDrive\Dökümanlar"
Set fol = fso.GetFolder(anaklasorStr)

For Each alt In fol.SubFolders
    Debug.Print alt.Name
    'diğer fso işlemleri
Next

End Sub

NOT:Bu işlemi FS modülündeki Dir ile de yapabiliyoruz. Başka FSO işlemi yapacaksak(FolderExists kullanmak gibi) bu yöntemi kullanaım, yoksa Dir yöntemini.

Klasör içindeki dosyaları elde etme

Bu işlem için Files property'si kullanılır. Folder'da olduğu gibi bi Collection elde eder ve Foreach uygularız.

Sub KlasördekiDosyalar()

Dim anaklasorStr As String
Dim fol As Folder
Dim f As File

anaklasorStr = "C:\Users\Volkan\OneDrive\Dökümanlar"
Set fol = fso.GetFolder(anaklasorStr)

For Each f In fol.Files
    Debug.Print f.Name
    'diğer fso işlemleri
Next

End Sub

NOT:Bu işlemi FS modülündeki Dir ile de yapabiliyoruz. Başka FSO işlemi yapacaksak(FolderExists kullanmak gibi) bu yöntemi kullanalım, yoksa Dir yöntemini.

Klasör içindeki (tüm alt klasörlerin içindekiler dahil) dosyaları elde etme

Bu örnek üsttekilere göre biraz daha karmaşıklık içerir ancak mantığı açısından güzel bir örnektir.

Alt klasörleri işleme dahil etmek için Collection tipinde bir yığın oluşturuyoruz ve her defasında bu yığının ilk üyesi üzerinde işlem yapıyoruz. İşlem yapmadan önce bu ilk elemanı yığından dışarı atıyoruz ki bir daha işleme girmesin. Sonra yığındaki elemanların(klasörlerin) her biri için işlemi yineliyoruz. Bu işlemi anlamanın en iyi yolu, Local penceresi açıkken F8 ile ilerlemek olacaktır.

NOT:Bunun daha hızlı ve basit you aşağıda Dir bölümünde ele alınacaktır. Ancak fso nesnesiyle ilgili başka kontroller veya işlemler yapılması gerekirse bu yöntemin kullanılması tercih edilmelidir. Bu arada internette araştırırsanız başka yöntemler olduğunu da görebilirsiniz. Kullanım tercihi size kalmış.

Bu örnekte bi klasördeki dosyaların adını, bulunduğu klasörü ve dosya boyutunu yazdırıyoruz. Kendi diskinizdeki bir klasör ile yer değiştirerek deneyebilrisiniz.

Sub KlasördekiAltKlasörDahilDosyalar()
    Dim kls As Folder, altkls As Folder
    Dim dosya As file
    Dim klasörYığını As New Collection
    Dim i As Integer
        
    klasörYığını.Add fso.GetFolder("C:\Users\Volkan\OneDrive\Dökümanlar")
    i = 1
    
    'yığındaki eleman sayısı 0 olana kadar yani tüm alt klasörler bitene kadar devam edicez
    Do While klasörYığını.Count > 0
        Set kls = klasörYığını(1)
        klasörYığını.Remove 1 'ilk klasörü yığından çıkarıyoruz
        
        'alt klasörleri yığına ekliyoruz
        For Each altkls In kls.SubFolders
            klasörYığını.Add altkls
        Next altkls
        
        For Each dosya In kls.Files
            ActiveCell(i, 1).Value = dosya.ParentFolder
            ActiveCell(i, 1).Offset(0, 1).Value = dosya.Name
            ActiveCell(i, 1).Offset(0, 2).Value = dosya.Size
            i = i + 1
        Next dosya
    Loop
End Sub

Bu işlemi yapmanın bir diğer yolu da işlemi recursive bir şekilde ele almaktır.

'ana prosedür
Sub recursive_fulldosya()
    
    Dim anaklasorStr As String
    anaklasorStr = "C:\inetpub\wwwroot\aspnettest\excelefendi2\"
    Recursiveİlerle fso.GetFolder(anaklasorStr)
End Sub

'recursive prosedür
Sub Recursiveİlerle(kls As Variant) 'variant çünkü ilk girereken Folder sonra Folders olacak
    Dim altKlasorler As Folder
    Dim dosya As file
    Dim i As Integer
    
    For Each altKlasorler In kls.SubFolders
        Recursiveİlerle altKlasorler
    Next
    i = 1
    
    For Each dosya In kls.Files
        ActiveCell(i, 1).Value = dosya.ParentFolder
        ActiveCell(i, 1).Offset(0, 1).Value = dosya.Name
        ActiveCell(i, 1).Offset(0, 2).Value = dosya.Size
        i = i + 1
    Next
End Sub

Diğer FSO ve File/Folder işlemleri

Dosyaları ReadOnly yapmak

Bu işlemi de FS modülü ile yapabiliyoruz. Neden böyle bir işlemi yapmak isteyeceğimi orada açıklıyorum. Burada sadece kısaca bu işlemin nasıl yapıldığına bakalım. Önceki örneklerde olduğu gibi eğer File nesnesi ile FileSystem ile yapılamayacak başka işlemler yapacaksanız bu yöntemi kullanın, yoksa en hızlısı FileSystem olduğu için onu kullanın.

dosya = "C:\deneme.xlsx" 
Set dosya = fso.GetFile(dosya)
dosya.Attributes = 1 'bu özellik hem okunur hem yazılırdır

Silme işlemi

Yine FS ile de yapılabilir ve öncekilerde olduğu gibi FS'nin Kill fonksiyonunu kullanmak FSO'nun metodlarından daha efektifitr, özellikle büyük çaplı işlemlerde.

Bazı eylemler için FSO'nun metodlarını da File/Folder'ın metodlarını da kullanabiliyoruz,  FS'nin fonksiyonlarını da. Tıpkı silme işleminde olduğu gibi. Aşağıdaki örnekte bu 3 yönteme de bakalım. 

Sub silmeler()
Dim f As file

'1.yöntem:Filesystem modülündeki Kill fonk ile
a = "C:\Users\Volkan\Desktop\a.txt"
FileSystem.Kill a 'FileSystem yazmaya gerek yoktur

'2.yöntem:fso nesnesi ile. Fso'yu başka amaçla da kullancaksak
b = "C:\Users\Volkan\Desktop\b.txt"
If fso.FileExists(b) Then
    fso.DeleteFile b
End If

'3.yöntem:file nesnesi ile. File bilgisi lazımsa
c = "C:\Users\Volkan\Desktop\c.txt"
Set f = fso.GetFile(c)
If f.Size > 1024 Then
    f.Delete
End If

End Sub

Kopyalama

Tek dosya kopyalamak

Kaynak olarak her zaman dosya adı belirtilir. Hedef olarak klasör adı veya dosya adı belirtilebilir.(fso.CopyFile kaynakdosya, hedefklasör)

'hedef: klasör
fso.CopyFile "C:\Users\Volkan\Desktop\denemeler\Şubeliste.xlsx", "C:\Users\Volkan\Desktop\ıvır zıvır\" 'sonda \ olmalı
'hedef: dosya adı, dosyanın adı dğeiştirilebilir
fso.CopyFile "C:\Users\Volkan\Desktop\denemeler\Şubeliste.xlsx", "C:\Users\Volkan\Desktop\ıvır zıvır\ŞubelisteforBölgeler.xlsx"
Aynı tipteki çoklu dosya kopyalama

Aşağıdaki kod ile kaynak klasördeki tüm xlsx, xlsm, xlsb,xls uzantılı dosyaları hedef klasöre kopyalamış oluyoruz.

kaynak = "C:\Users\Volkan\Desktop\denemeler"
hedef = "C:\Users\Volkan\Desktop\ıvır zıvır\"

fso.CopyFile Kaynak & "\*.xl*", Hedef

Yeniden adlandırmak ve taşımak

MoveFile kullanılabileceği gibi MSDN'de dokumente edilmemiş bir Name fonksiyonu var bu da kullanılabilir. MoveFile kullanımı CopyFile'a benzer.

Sub rename()

'kaynak dosya ve hedef klasör belirterek
fso.MoveFile "C:\Users\Volkan\Desktop\denemeler\Şubeliste.xlsx", "C:\Users\Volkan\Desktop\ıvır zıvır\" 'sonda "\" olmalı
'veya kaynak dosya, hedef dosya adı(farklı isim olabilir)
fso.MoveFile "C:\Users\Volkan\Desktop\denemeler\Şubeliste.xlsx", "C:\Users\Volkan\Desktop\ıvır zıvır\ŞubelisteforBölgeler.xlsx"
'veya
Name "C:\Users\Volkan\Desktop\denemeler\Şubeliste.xlsx" As "C:\Users\Volkan\Desktop\ıvır zıvır\ŞubelisteforBölgeler.xlsx"

End Sub

Dosya son değişim tarihi hakkında bilgi almak

Bir dosyanın gün içinde birkaç kez açılma durumu varsa ve dosyada bir kaydetme işlemi uygulanıyorsa, dosyanın daha önce kaydedilip edilmediği bilgisine bakarak sonraki açılışlarda kodun çalışmamasını sağlayabilrisiniz.(veya tamamen başka sebeplerle)

Set f = fso.GetFile(gunlukyol & adres)

If DateValue(f.DateLastModified) = Date Then
   Exit Sub
Else
   'diğer kodlar
End If

Dosya isim, uzantı ve adresleri

Dosya isim, uzantı ve adreslerine sıklıkla ihtiyaç duyuyor olacağız. Bunların açıklmasını doğrudan kod içinde vermek daha kolay olacaktır.

Sub cesitli_fsofilefolder()
    Dim f As file
    Dim k As Folder
    dosya = "C:\Users\Volkan\Desktop\denemeler\deneme.xlsx"
    
    Debug.Print fso.GetAbsolutePathName(dosya) 'C:\Users\Volkan\Desktop\denemeler\deneme.xlsx
    Debug.Print fso.GetBaseName(dosya) 'deneme
    Debug.Print fso.GetDriveName(dosya) 'C:
    Debug.Print fso.GetExtensionName(dosya) 'xlsx
    Debug.Print fso.GetFileName(dosya) 'deneme.xlsx
    Debug.Print fso.GetParentFolderName(dosya) 'C:\Users\Volkan\Desktop\denemeler
    
    Set f = fso.GetFile(dosya)
        
    Debug.Print f.Name 'deneme.xlsx
    Debug.Print f.ParentFolder 'denemeler
    Debug.Print f.Path 'C:\Users\Volkan\Desktop\denemeler\deneme.xlsx
    Debug.Print f.ShortName 'DENEME~1.XLS
    Debug.Print f.ShortPath 'C:\Users\Volkan\Desktop\DENEME~1\DENEME~1.XLS
    
    Set k = f.ParentFolder
    
    Debug.Print k.Name 'denemeler
    Debug.Print k.ParentFolder 'C:\Users\Volkan\Desktop
    Debug.Print k.Path 'C:\Users\Volkan\Desktop\denemeler
    Debug.Print k.ShortName 'DENEME~1
    Debug.Print k.ShortPath 'C:\Users\Volkan\Desktop\DENEME~1
    
End Sub			

FileSystem(FS)

Yukarıda belirttiğimiz gibi FS modülü, class modül olmayıp bunun içindeki fonksiyonları kullanmak için bir FS nesnesi yaratmaya gerek bulunmamaktadır, daha da önemlisi FSO gibi başka bir library'yi reference olarak göstermeye gerek yoktur.

Yine yukarıda belirttiğimiz gibi FSO ve FS'nin ortak üyeleri bulunmaktadır. Amacımız sadece bu metodu kullanmak ise tercih her zaman FS'den yana olmalı, ancak FSO'nun diğer üyeleriyle de işlem yapılacaksa işte o zaman FSO kullanılmalıdır.

Şimdi FS'nin metdolarına bakalım.

Dir

Dir heralde FS'nin en önemli fonksiyonudur. Parametre olarak dosya/klasör adı alır. Bunu kullanırken en sonda hep "\" olmasına dikkat edilmelidir. O yüzden Dir ile ilgili işlem yapmadan önce sağ tarafa "\" olup olmadığna göre aşağıdaki gibi bi düzeltme işlemi yapılmasında fayda var.

If Right(klasor, 1) <> "\" Then
    klasor = klasor & "\"
End If	

Bu fonksiyon FSO'nun FileExists/FolderExists özellikleri yerine de kullanılabilir ancak bunlardan farklı olarak True/False döndürmez, sonuç dönüyorsa dönen sonucu(dosya ise dosya adını, klasör ise ilk dosyanın adını) yazar, yoksa ZLS döndürür. O yüzden sonucun vbNullString olup olmadığına bakmalıyız.

Var mı? kontrolü

Sub kontrol2()

If Dir("C:\Users\Volkan\Desktop\denemeler\deneme.xlsx") <> vbNullString Then
    Debug.Print "Dosya var"
End If

If Dir("C:\Users\Volkan\Desktop\denemeler\") <> vbNullString Then 'sondaki \ işaretine dikkat. Bu klasör mevcut olsa bile \ işareti olmazsa Null döndürür
    Debug.Print "Klasör var"
End If

End Sub

Aşağıda Excel gurularından Ken Puls tarafından bir fonksiyon haline dönüştürülmüş(benim de bir zamanlar sıklıkla kullandığım) versiyonunu görüyorsunuz.

Public Function FileFolderExists(strFullPath As String) As Boolean
'Author       : Ken Puls (www.excelguru.ca)
'Macro Purpose: Check if a file or folder exists

    If strFullPath = vbNullString Then Exit Function
    On Error GoTo EarlyExit
    If Not Dir(strFullPath, vbDirectory) = vbNullString Then FileFolderExists = True
    
EarlyExit:
    On Error GoTo 0
End Function

'Kullanımı
'adres olarak dosya adresi de klasör adresi de verilebilir
If FileFolderExists(adres) Then 
  'diğer kodlar
End If

Yanlız bu tür şeylerin üzerine kafa yorunca siz daha basit çözümler bulabiliyorsunuz. Mesela ben aşağıdaki çözümü buldum. Yaptığım şey basit:Parametre olarak verilen şeyin hem file hem folder için işleyen GetAttr metodu ile attribute bilgisini almaya çalışıyorum; eğer bilgi alabilirsem demek ki dosya veya klasör mevcuttur; bilgi alamıyorsam, ki öyleyse hata üretir, o zaman hata yönetim bloğu ile de fonksiyona False değerini atarım.

Function Mevcutmu(adres As String) As Boolean
On Error GoTo hata
If GetAttr(adres) >= 0 Then Mevcutmu = True
Exit Function

hata:
Mevcutmu = False
End Function

'kullanım
Debug.Print Mevcutmu("C:\Users\Volkan\") 'True
Debug.Print Mevcutmu("C:\Users\Volki\") 'False
Debug.Print Mevcutmu("C:\Users\Volkan\Desktop\denemeler\deneme.xlsx") 'True
Debug.Print Mevcutmu("C:\Users\Volkan\Desktop\denemeler\deneme5.xlsx") 'false

İkinci parametre

Dir'in ikinci parametresi çeşitli constantları alır, bunların en önemlisi vbDirectory'dir. Bu belirtilirse, ilgili klasör altındaki ilk klasörü verir, eğer bir klasör yoksa kendisini verir, kendisini ise "." karakteriyle gösterir.

Aşağıdaki klasör gözönüne alındığında;

Dir("C:\Users\Volkan\Desktop\denemeler\") 'ALORİTMA.xlsx döndürür
Dir("C:\Users\Volkan\Desktop\denemeler\ALGORİTMA.xlsx") 'kendisini verir
Dir("C:\Users\Volkan\Desktop\denemeler\", vbDirectory) 'Kendisi yani '.'

Klasör içindeki klasörleri elde etme 

Bu işlemi FSO altında da incelemiştik. Anak eğer FSO ile ilgili başka bir işlem yapılmayacaksa Dir ile çok daha hızlı yapılır. (Koddaki GetAttr'le ilgili satıra çok taklımayın, bunu şimdilik ezbere kullanın, zira konu biraz karışık, merak edenler için burada detaylı açıklama var.)

Bir diğer konu da Dir'in aynı kod içinde parametresiz olarak mükerrer kullanımı. Böyle bir durumda aynı klasör içinde dosya/klasörlerde sırayla ilerlenmiş olur.

Sub LoopinKlasör()
Dim i As Integer
i = 1

anaklasor = "C:\inetpub\wwwroot\aspnettest\excelefendi2\"
klasor = Dir(anaklasor, vbDirectory)   'ilk klasörü alıyoruz

Do Until klasor = ""   'Dir'den klasor dönmeyene kadar ilerliyoruz
  If (GetAttr(anaklasor & klasor) And vbDirectory) = vbDirectory Then
    ActiveSheet.Cells(i, 1).Value = anaklasor & klasor
    i = i + 1
  End If
  klasor = Dir()   'Parametresiz dier ile sonraki klasöre ilerliyoruz
Loop
End Sub		

Klasör içindeki dosyaları elde etme 

Yine bu işlem de FSO ile yaplabilmekteydi ancak FSO'nun başka kullanımı olmacyasak Dir ile yapmak daha hızlıdır.

İlk parametreli Dir'den sonraki parametresiz Dir ile aynı klasörde ilerleriz. Ayrıca Dir, joker eleman da aldığı için tüm dosyalarda değil belli dosyalar üzerinde de dolaşabilirsiniz.

Aşağıdaki örneklerde, bi klasörde "vba" ifadesi içieren dosya isimlerini yazırıyoruz. 350 dosya içeren bu klasörde Dir'in çalışma hızı 0,17 sn iken FSO 0,53 sn olmuştur. Daha kalabalık klasörlerde fark daha da açılmaktadır.

'Dir ile
Sub dosyalarda_gezin_dir()
Dim bas As Single, bts As Single
bas = Timer
f = Dir("C:\inetpub\wwwroot\aspnettest\excelefendi2\images\*vba*")
Debug.Print f
Do While Len(f) > 0
    f = Dir 'sonraki dosyay geçiyoruz. Sonunda () gerekli değil, olsa da our olmasa da
    Debug.Print f
Loop
bts = Timer
Debug.Print bts - bas
End Sub

'FSO ile
Sub dosyalarda_gezin_fsofilefolder()
   Dim bas As Single, bts As Single

   Dim fso As New FileSystemObject
   Dim kaynak As Folder, 
   Dim dosya As File
   
   bas = Timer
   Set kaynak = fso.GetFolder("C:\inetpub\wwwroot\aspnettest\excelefendi2\images\")
   For Each dosya In kaynak.Files
      If InStr(dosya.Name, "vba") > 0 Then
            Debug.Print dosya.Name
      End If
   Next dosya
   bts = Timer
   Debug.Print bts - bas
End Sub

Klasör içindeki (tüm alt klasörler dahil) dosyaları elde etme

Yine aynı açıklamamız geçerli. FSO ile de yapabiliriz, ancak Dir daha hızlıdır. Eğer ki FSO'yu başka amaçla da kullanacaksak FSO tercih edilmeli, yoksa Dir.

Aşağıdaki örneği buradan aldım. Kendi ihtiyacınıza göre değiştirebilirsiniz. F8 ve Local Windows aracılığı ile değişklikleri izleyerek incelemenizi tavsiye ederim.

Sub recursive_Dir()
     Dim colFiles As New Collection
     RecursiveDir colFiles, "C:\deneme", "*.*", True
     Dim vFile As Variant
     For Each vFile In colFiles
         Debug.Print vFile
     Next vFile
End Sub

'recursive Fonksiyonumuz	
Public Function RecursiveDir(colFiles As Collection, _
                              strFolder As String, _
                              strFileSpec As String, _
                              bIncludeSubfolders As Boolean)
     Dim strTemp As String
     Dim colFolders As New Collection
     Dim vFolderName As Variant
     'Add files in strFolder matching strFileSpec to colFiles
     strFolder = TrailingSlash(strFolder)
     strTemp = Dir(strFolder & strFileSpec)
     Do While strTemp <> vbNullString
         colFiles.Add strFolder & strTemp
         strTemp = Dir
     Loop
     If bIncludeSubfolders Then
         'Fill colFolders with list of subdirectories of strFolder
         strTemp = Dir(strFolder, vbDirectory)
         Do While strTemp <> vbNullString
             If (strTemp <> ".") And (strTemp <> "..") Then
                 If (GetAttr(strFolder & strTemp) And vbDirectory) <> 0 Then
                     colFolders.Add strTemp
                 End If
             End If
             strTemp = Dir
         Loop
         'Call RecursiveDir for each subfolder in colFolders
         For Each vFolderName In colFolders
             Call RecursiveDir(colFiles, strFolder & vFolderName, strFileSpec, True)
         Next vFolderName
     End If
End Function

'Dir kullanırken sondaki \ işareti önemli olduğu için bunu ele alma fonksiyonu
Public Function TrailingSlash(strFolder As String) As String
     If Len(strFolder) > 0 Then
         If Right(strFolder, 1) = "\" Then
             TrailingSlash = strFolder
         Else
             TrailingSlash = strFolder & "\"
         End If
     End If
End Function

Diğer FileSystem üyeleri

ReadOnly yapmak

Bir dosyayı neden Readonly yapmak isteyesiniz ki? Sitenin anasayfasında belirttiğim gibi herşeyi öğrenmeye çalışın, en azından böyle birşeyin var olduğunu bilin, birgün lazım olabilir. Bendeki ihtiyaç şöyle doğdu:

İşyerinde 2 pc ile çalışıyorum. Ana pc'mdeki Personal.xlsb dosyamda yaptığım değişikliklerin dosyanın Workbook_AfterSave eventi ile network üzerindeki ortak alana kaydolmasını sağlıyorum. Diğer pc ve benimle çalışan arkadaşımın da bendeki personal dosyasının en güncel verisyonuna sahip olmasını istiyorum. Bunun için de onların pclerindeki Task Scheduler ile her gece güncel dosyayı kendi pclerine kopyalamasını sağlayan bir Task yarattım(Tabi önce Application.OnTime ile akşam belli bi saatte Excelin kapatılmasını sağlıyorum). Süreç özetle şöyle:

  • Personal.xlsb dosyamda bi değişklik yaparım
  • Dosyanın güncel hali anında ortak alana kaydolur
  • Akşam 21:00'de arkadaşımın pcsinde ve benim diğer pc'mde Excel kapanır
  • Gece 00:00da arkadaşımın ve benim diğer pc'mde Task Scheduler önce güncel dosyayı bunların XLSTART klasörüne kopyalar
  • Hemen arkadasından Excel otomatik açılır

Şimdi burda şöyle bi tehlike var. Eğer ki arkadaşım kendi pc'sindeki Personal.xlsb dosyasında birşeyler denemek isteyip sonrasında bunu da kaydetmek isterse ortak alana da bu değişkliklerle kaydedilmiş olacak. Belki önemli bazı şeyleri bozmuş olacak. O yüzden arkadaşımın bu dosya üzeinde Save etme işlemini engellemem gerekir. Bunun için dosyanın ortak alana kaydolurken Readonly olarak kaydolmasını sağlayabilirim. Böylece bu dosya, arkadaşımda ve benim diğer pc'de readonly açılacak. PC'de sadece otomatik işler çalıştığı için orda zaten save etme endişesi yok, ancak arkadaşım save etmeye çalışınca ona uyarı çıkacak, ya başka isimle kaydetmek zorunda kalacak ya da kaydetme işleminden vazgeçecek. İşte bütün bu olay için kodumuz şöyle:

Private Sub Workbook_AfterSave(ByVal Success As Boolean)
  FileSystem.SetAttr Path & Me.Name, vbNormal 'Varolanın üzerine yazması için önce Readonly özelliğini kaldırıyorum
  FileSystem.FileCopy Me.FullName, path & Me.Name 'FileCopy dosya kopyalar
  FileSystem.SetAttr Path & Me.Name, vbReadOnly 'en son readonly yapıyorum
End Sub

Diğer metodlar

Kill ve RmDir: Sırayla dosya ve klasör silerler. Kill'in iki muadili var, FSO altında karşılaştırması var. RmDir  FSO'daki DelefeFolder muadilidir.

MkDir:Klasör yaratır. FSO'daki CreateFolder muadili

FileCopy: Fso'daki CopyFile'ın muadilidir.

FileLen: File'ın Size muadili.

FileDateTime:Yine File'ın DateLastModified muadili 

GetAttr ve SetAttr: File'ın Attributes muadili.

YORUMLAR