Dosya okuma ve yazma
İçine veri yazılan birçok dosya tipi bulunmaktadır, ancak biz VBA konsepti içinde genellikle text(csv dahil) dosyalarıyla çalışacağız. SQL kodlarını depoladığınız ".sql" uzantılı dosyaları da bu kapsamda düşünebilirsiniz. Excel dosyalarla çalışmayı zaten Workbook ve Application bölümlerinde görmüştük.
Text dosyaları bilgi depolayıp okumanın kolay bir yolunu sunarlar. Özellikle settings(ayar) bilgileri veya aşamalı bir sürecin durum bilgilerini(log) okumakta/yazmakta oldukça kullanışlıdırlar.
VBA'de iki tür okuma/yazma yöntemi bulunuyor. Öncelikle biz VB6'dan miras gelen klasik okuma yazma yöntemine bakacağız.
UYARI:Buradan itibaren aşağıda göreceğiniz tüm dosya okuma işlemlerinde, dosya okuma hep sağa ve aşağı yönlüdür. Döngüsel işlemlerde "bir sağ kolona/karaktere veya bir alt satıra geç" tarzında ilave bir kod ifadesi yoktur. Bu işlem otomatik olmaktadır.
Dosya Açma ve Kapama
Dosya Açma
Okuma işlemi için de yazma işlemi için de öncelikle dosyanın açılması gerekir. Bunun için Open fonksiyonu kullanılır. Aşağıdaki gibi bir syntax'a sahiptir:
Open dosyayolu For mod [Erişim tipi] [lock] As Dosyano
- Dosyayolu: Dosyanın bulunduğu tam adres. Ör:
C:\deneme\deneme.txt
- Mod: Input ise okuma, Output ise yazma, Append ise dosya sonuna ekleme yapılır. 2 tane daha var ama bize bu üçü yeter. Output seçildiğinde mevcut dosya varsa ezilip içeriği yeniden oluşturulur, olmayan bir dosya girildiyse bu dosya yaratılır.
- Erişim tipi ve Lock tipi: Opsiyoneldirler. Dosya açıkken, başkalarının ne yapabileceğini gösterir. Biz bunları kullanmayacağız, o yüzden default değerleri devreye girecek.
Freefile
Dosyalar açıldığında onlara bir sıra numarası verilir. Bu numara manuel belirtilebileceği gibi, çok sayıda okuma yazma yapılan bir prosedür içinde o andaki müsait sıra numarasını veren Freefile deyimi de kullanılabilir. Manuel giriş için sıra numarası # ile kullanılır. #1 gibi.
Dosyayı Kapama
Dosyayı Close ifadesi ile kaparız, ancak parametre olarak dosya adresi değil, numarasını alır.
Dosyayı kapatmazsak, tekrar aynı dosyayı açmaya çalıştığımızda "Dosya zaten açık" hatası alırız.
Kod
Bu durumda, örnek bir dosya açma kodu aşağıdaki gibi olacaktır:
adres = "C:\Users\Volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As #1 'veya 1 veya FreeFile
'çeşitli işlemler
Close #1
Dosyadan Veri Okuma
Kolon Kolon Bilgi Okumak
Aşağıdaki bilgileri içeren bir text dosyamız olsun. Kişinin adı, yaşı ve baba adı bilgileri var:
volkan ,38 ,ismail
ayşe ,40 ,murat
serkan ,35 ,osman
Buradan ilk kaydın yaş bilgisini almak istiyoruz diyelim. Bunun için Input deyimini kullanıp, istediğimiz kolon sayısı kadar değişken belirleyip kolon bilgilerini bu değişkenlere atıyoruz.
Sub teksatırdan_tekkolon_okuma()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
Input #1, adı, yaş 'kolon sayısı kadar parametre alır. # zorunlu
Debug.Print yaş '38 verir
'ikinci bir Debug.Print yaş yazsak bile yine 38 yazar. sadece tek satır okuması var.
Close 1
End Sub
Bu kod tabii ki sadece ilk satır için bilgi döndürür. Satırda ilerleme yapamıyoruz. Özellikle her defasında üzerine yazma yapılan tek satırlık bilgi içeren dosyalarda kullanışlıdır. Mesela ikinci kolonunda, bilginin yazdırıldığı tarihi veya kişiyi gösteren bir dosyadan bu tarihi veya kişiyi elde etmek isteyebiliriz. Böylece bu dosyaya en son ne zaman bilgi yazıldığını veya kimin tarafından yazıldığını elde edebiliriz.
Tek Satırdan Kısmi Bilgi Okuma
Input ifadesini Input(karakteradedi, dosyano)
şeklinde kullandığımızda belirli adette karakter okumuş oluruz.
Sub teksatır_kısmen_okuma()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
x = Input(6, 1) '1 nolu dosyadan 6 karakter oku
Debug.Print x 'volkan
End Sub
İlk Satırın Tamamını Okuma
Yine yukarıdaki dosyamız elimizde bulunsun. Bu sefer ilk satırın tamamını elde edeceğiz. Bunu Line Input deyimi ile yapıyor ve içeriği ikinci parametredeki değişkene atıyoruz.
Sub teksatır_tamamını_okuma()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
Line Input #1, metin 'ilk satırı oku ve metin değişkeninde depola
Debug.Print metin 'volkan,38,ismail yazar
Close 1
End Sub
x Adet Satırı Tek Tek Okuma
Bu işlem Line Input'un bir For Next döngüsü ile kullanımı ile yapılabilir. Belli sayıda satır bilgisinin yeterli olduğu durumlarda kullanılır.
Sub x_adet_satır_oku()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
For i = 1 To 2
Line Input #1, metin
Debug.Print metin
Next i
Close 1
End Sub
Dosyadaki Tüm Metni Okuma
1. Yöntem: Dosyadaki Karakter Sayısı Kadar Okumak
Bunu LOF ifadesi ile yapıyoruz. Bu, Length Of File'ın kısaltılmışıdır, yani dosyadaki karakter sayısını verir. Input ile birleştirerek de dosyadaki tüm karakter sayısını oku demiş oluruz. "volkan naber" şeklinde 12 karakterli bir metni içeren bir dosyada:
LOF(1): 12
döndürürInput(LOF(1), 1): 1
nolu dosyayı tamamen okur: "volkan naber"
Örnek bir kodumuz ise şöyledir. Bu kodda ayrıca Seek ifadesini de kullandık. Bununla dosyada belirli bir sıradaki karaktere konumlanıyoruz, ki bunu genelde belirli bir sırayla ilerledikten sonra tekrar ilk karaktere dönmek için kullanırız. Syntax: Seek dosyano, konum
Sub DosyaOkuTümü1()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
Debug.Print LOF(1) 'Length Of File Of File
içerik = Input(LOF(1), 1) '1 nolu dosyanın hepsini oku
Debug.Print içerik
Seek 1, 1 '1 nolu dosyanın 1. karakterine yani en başa git
içerik = Input(LOF(1) - 10, 1) '1 nolu dosyanın son 10 karakteri hariç oku
Debug.Print içerik
Seek 1, 5 '1 nolu dosyanın 5. karakterine git
içerik = Input(10, 1) '1 nolu dosyanın 5. karakterinden sonraki ilk 10 karakterini oku
Debug.Print içerik
Close 1
End Sub
Aynı mantıkla bir şekilde dosyanın ilk x karakterini okumak için içerik değişkenine Input(x, 1)
; son x karakteri hariç okuma yapmak isterseniz içerik değişkenine Input(LOF(1) - x, 1)
şeklinde atama yaparsınız.
Bu yöntemde dosya içindeki metnin kaç satırda yer aldığı önemli değildir. Tüm metin tek bir değişkende depolanır.
2. Yöntem: Dosya Sonuna Kadar Satır Satır Okumak
Yukarıda gördüğümüz belli sayıdaki satırları tek tek okumadan farklı olarak tüm satırları tek tek okuyoruz. Satırların bittiğini EOF (End Of File'ın kısaltması) özelliği ile anlıyoruz.
Sub DosyaOkuTümü2()
tamadres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open tamadres For Input As 1
Line Input #1, satırmetni
içerik = satırmetni
Do Until EOF(1)
Line Input #1, satırmetni
içerik = içerik & vbNewLine & satırmetni
Loop
Debug.Print içerik
Close 1
End Sub
NOT: İçerik değişkenini oluştururken kayıtlar arasında vbNewLine
koyarak satırbaşı yapıyoruz. Ancak ilk başta değişkenin içi boş olacağı için fazladan bir boş satır oluşmaması için en başta bir kezliğine döngüye girmeden ilk satırın atamasını yapıyorum, sonrasında döngü içinde vbNewLine
ekliyorum.
Bu arada istenirse ilgili metinler vbNewLine
denmeden satır satır değil de ardışık bir şekilde de bir araya getirilebilir.
Tüm İçeriği Bir Diziye Aktarmak
Bunu da kendi içinde iki ayrı yöntemle yapabiliriz. İlk yöntemde satır satır okur ve her satırı bir collection'a atarız. Özellikle her satırın başına/sonuna başka bir metin eklemek gereken durumlarda bunu kullanabiliriz. İkinci yöntemde ise tüm metni okuyup Enter'ları (vbCrLf
veya vbNewLine
) Split ederek diziye atayabilirsiniz.
'1) Collection'a atama
Do Until EOF(1)
Line Input #1, metin
coll.Add metin
Loop
'2) Diziye atama
içerik = Input(LOF(1), 1)
dizi = Split(içerik, vbCrLf)
Bu iki yöntemle de yukarıdaki örneği yapalım.
Sub dosyaoku3()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
Debug.Print "------önce dizi yöntemi-----"
içerik = Input(LOF(1), 1)
dizi = Split(içerik, vbCrLf)
For Each satır In dizi
Debug.Print "Prefix:" + satır + " -Suffix"
Next satır
'veya
Debug.Print "------collection yöntemi-----"
Seek 1, 1
Dim coll As New Collection
Do Until EOF(1)
Line Input #1, metin
coll.Add metin
Loop
For Each satır In coll
Debug.Print "Prefix:" + satır + " -Suffix"
Next satır
Close 1
End Sub
Virgülle Ayrılmış Metinleri Hücrelere Yazdırmak
Virgülle ayrılmış tüm değerleri farklı kolonda olacak şekilde satır satır Excel'e yazdırmak isteyebilirsiniz. Bunun için satır satır okuma yapmamız gerekir ve her satırı Split ile bir diziye atayabilir, sonra da ilgili hücrelere bu dizi elemanlarını döngüsel şekilde yazdırabiliriz.
Dosyadaki Tüm Metni Okuma
1. Yöntem: Dosyadaki Karakter Sayısı Kadar Okumak
Bunu LOF ifadesi ile yapıyoruz. Bu, Length Of File'ın kısaltılmışıdır, yani dosyadaki karakter sayısını verir. Input ile birleştirerek de dosyadaki tüm karakter sayısını oku demiş oluruz. "volkan naber" şeklinde 12 karakterli bir metni içeren bir dosyada:
LOF(1): 12
döndürürInput(LOF(1), 1): 1
nolu dosyayı tamamen okur: "volkan naber"
Örnek bir kodumuz ise şöyledir. Bu kodda ayrıca Seek ifadesini de kullandık. Bununla dosyada belirli bir sıradaki karaktere konumlanıyoruz, ki bunu genelde belirli bir sırayla ilerledikten sonra tekrar ilk karaktere dönmek için kullanırız. Syntax: Seek dosyano, konum
Sub DosyaOkuTümü1()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
Debug.Print LOF(1) 'Length Of File Of File
içerik = Input(LOF(1), 1) '1 nolu dosyanın hepsini oku
Debug.Print içerik
Seek 1, 1 '1 nolu dosyanın 1. karakterine yani en başa git
içerik = Input(LOF(1) - 10, 1) '1 nolu dosyanın son 10 karakteri hariç oku
Debug.Print içerik
Seek 1, 5 '1 nolu dosyanın 5. karakterine git
içerik = Input(10, 1) '1 nolu dosyanın 5. karakterinden sonraki ilk 10 karakterini oku
Debug.Print içerik
Close 1
End Sub
Aynı mantıkla bir şekilde dosyanın ilk x karakterini okumak için içerik değişkenine Input(x, 1)
; son x karakteri hariç okuma yapmak isterseniz içerik değişkenine Input(LOF(1) - x, 1)
şeklinde atama yaparsınız.
Bu yöntemde dosya içindeki metnin kaç satırda yer aldığı önemli değildir. Tüm metin tek bir değişkende depolanır.
2. Yöntem: Dosya Sonuna Kadar Satır Satır Okumak
Yukarıda gördüğümüz belli sayıdaki satırları tek tek okumadan farklı olarak tüm satırları tek tek okuyoruz. Satırların bittiğini EOF (End Of File'ın kısaltması) özelliği ile anlıyoruz.
Sub DosyaOkuTümü2()
tamadres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open tamadres For Input As 1
Line Input #1, satırmetni
içerik = satırmetni
Do Until EOF(1)
Line Input #1, satırmetni
içerik = içerik & vbNewLine & satırmetni
Loop
Debug.Print içerik
Close 1
End Sub
NOT: İçerik değişkenini oluştururken kayıtlar arasında vbNewLine
koyarak satırbaşı yapıyoruz. Ancak ilk başta değişkenin içi boş olacağı için fazladan bir boş satır oluşmaması için en başta bir kezliğine döngüye girmeden ilk satırın atamasını yapıyorum, sonrasında döngü içinde vbNewLine
ekliyorum.
Bu arada istenirse ilgili metinler vbNewLine
denmeden satır satır değil de ardışık bir şekilde de bir araya getirilebilir.
Tüm İçeriği Bir Diziye Aktarmak
Bunu da kendi içinde iki ayrı yöntemle yapabiliriz. İlk yöntemde satır satır okur ve her satırı bir collection'a atarız. Özellikle her satırın başına/sonuna başka bir metin eklemek gereken durumlarda bunu kullanabiliriz. İkinci yöntemde ise tüm metni okuyup Enter'ları (vbCrLf
veya vbNewLine
) Split ederek diziye atayabilirsiniz.
'1) Collection'a atama
Do Until EOF(1)
Line Input #1, metin
coll.Add metin
Loop
'2) Diziye atama
içerik = Input(LOF(1), 1)
dizi = Split(içerik, vbCrLf)
Bu iki yöntemle de yukarıdaki örneği yapalım.
Sub dosyaoku3()
adres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open adres For Input As 1
Debug.Print "------önce dizi yöntemi-----"
içerik = Input(LOF(1), 1)
dizi = Split(içerik, vbCrLf)
For Each satır In dizi
Debug.Print "Prefix:" + satır + " -Suffix"
Next satır
'veya
Debug.Print "------collection yöntemi-----"
Seek 1, 1
Dim coll As New Collection
Do Until EOF(1)
Line Input #1, metin
coll.Add metin
Loop
For Each satır In coll
Debug.Print "Prefix:" + satır + " -Suffix"
Next satır
Close 1
End Sub
Virgülle Ayrılmış Metinleri Hücrelere Yazdırmak
Virgülle ayrılmış tüm değerleri farklı kolonda olacak şekilde satır satır Excel'e yazdırmak isteyebilirsiniz. Bunun için satır satır okuma yapmamız gerekir ve her satırı Split ile bir diziye atayabilir, sonra da ilgili hücrelere bu dizi elemanlarını döngüsel şekilde yazdırabiliriz.
Sub DosyaOkuTümü4()
tamadres = "C:\Users\volkan\Desktop\denemeler\dosya1.txt"
Open tamadres For Input As 1
i = i + 1
Do Until EOF(1)
Line Input #1, x
dizi = Split(x, ",")
For j = 0 To UBound(dizi)
Cells(i, j + 1) = dizi(j)
Next j
i = i + 1
Loop
Close 1
End Sub
Dosyaya Veri Yazma
Sıfırdan Yazma
Dosyaya veri yazdırmak için dosyayı Output modunda açmamız gerekir. Yazdırma eylemi için iki fonksiyonumuz var: Write ve Print. Write, yazdırılan ifadeyi " " içine alarak yazarken Print böyle bir işlem yapmaz.
Örenğin:
Dosyaya veri yazma
Sıfırdan yazma
Dosyaya veri yazdırmak için dosyayı Output modunda açmamız gerekir. Yazdırma eylemi için iki fonksiyonumuz var. Write ve Print. Write, yazdırılan ifadeyi " " içine alarak yazarken Print böyle bir işlem yapmaz.
Her iki deyim de ardışık kullanımlarında satır satır yazdırır. Yani birbirini takip eden metinler şeklinde yazılmaz. Örneğin;
ad="Volkan"
soyad="Yurtseven"
Print ad
Print soyad
'bu kodun çıktısı aşağıdaki gibidir
'Volkan
'Yurtseven
'VolkanYurtseven değil
Eğer yazdırılan metinlerin ardışık yazdırılması isteniyorsa aşağıda anlattığım TextStream nesnesini kullanmanız gerekir.
Şimdi veri yazdırmaya ait küçük bir kod yazalım.
Sub DosyaYazTekSatır()
tamadres = "C:\Users\volkan\Desktop\denemeler\dosya2.txt"
ff = FreeFile ' o an uygun olan dosya numarası verilir.
Open tamadres For Output As ff
Print #ff, "bu ilk satır"
Print #ff, "bu da ikinci satır"
Close ff 'kapatırken kaydeder, ayrı bir save işlemi yoktur
End Sub
NOT: Eğer dosya mevcut değilse otomatikman oluşturulur, varsa ezilir ve üzerine yazılır.
Varolan dosyaya ekleme yapmak
Varolan bir dosyanın sonuna ekleme yapmak istiyorsak bu işi Append deyimi ile yaparız. Eğer dosya mevcut değilse Outputta olduğu gibi otomatikman oluşturulur.
Sub DosyaAppend()
tamadres = "C:\Users\volkan\Desktop\denemeler\dosya2.txt"
ff = FreeFile ' o an uygun olan dosya numarası verilir.
Open tamadres For Append As ff
Print #ff, "bu üçüncü satır"
Close ff 'kapatırken kaydeder, ayrı bir save işlemi yoktur
End Sub
Excelden okuyup dosyaya yazma
İçiçie iki For Next ile satır ve sütunlarda dolaşırız, araya "," veya istediğimiz başka bir ayraç ekleriz.
Aşağıdaki örnekte 10 satır 3 kolondan oluşan bir listeyi metin dosyasına yazdırıyoruz.
Sub Exceldenyaz()
tamadres = "C:\Users\volkan\Desktop\denemeler\dosya3.txt"
ff = FreeFile
Open tamadres For Output As ff
For i = 1 To 10
For j = 1 To 3
If j = 3 Then
satırmetin = satırmetin + Trim(Cells(i, j).Value)
Else
satırmetin = satırmetin + Trim(Cells(i, j).Value) + ","
End If
Next j
Print #ff, satırmetin
satırmetin = ""
Next i
Close ff
End Sub
Metin değişikliği yapmak
Bazen tek bir dosyada bazense birçok metin dosyasında aynı anda bir metin değişikliği yapmak isteriz. Birçok dosyayı elde etmeyi bir önceki sayfada görmüştük. Bir döngü ile bu klasörleri/dosyaları elde ettikten sonra yapmanız gereken iş 4 aşamadan oluşur:
- Önce dosyayı açmak
- Metni okumak
- Aradığımız metni bulup değiştirmek
- Dosyaya tekrar yazdırmak
Sub MetinDeğiştir()
Dim adres As String
Dim içerik As String
adres = "C:\deneme\deneme.txt"
Open adres For Input As 1
içerik = Input(LOF(1), 1)
Close 1
içerik = Replace(içerik, "abc123", "abc345")
Open adres For Output As 1
Print #1, içerik
Close 1
End Sub
Yapılan değişkliği illa dosyaya kaydetmek zorunda değilsiniz. Mesela benim bazı SQL'leri tuttuğum metin dosyalarım var, içinde değişkenlerin olduğu bölümler var. Bu dosyaları bir nevi şablon olarak tutuyorum, onların üzerinde değişiklik yapmıyorum, onun yerine dosyayı okuyup bi değişkene atıyorum ve onun üzerinde replace işlemi yapıp, SQL metni olarak işleme sokuyorum. En aşağıdaki örnekler bölümünde bu işlemi görebilirsiniz.
Dosyalara yazma ve okumanın bir diğer yolu da TextStream nesnesi yoluyladır.
Niye böyle bir yöntem daha var? Bu sınıf, aslında web sayfalarında VBScript diliyle yazılmak üzere tasarlanmış bir sınıftı ama sonradan VBA içinde de kullanıma alındı. O yüzden Scripting Runtime library'si içindedir ve references menüsünden eklenmesi gerekir.
Ben şahsen hem okunurluk hem de kullanım kolaylığı açısından TextStream nesnesini kullanmayı tercih ediyorum, ancak her zaman olduğu gibi başkalarının yazdığı kodları okumanız/kullanmanız gerekebileceği için her yöntemi bilmekte fayda var. Aşağıda göreceğiniz üzere TextStream'in bazı ek özellik ve metodları da onu ayrıcalıklı kılmaktadır.
Erişim & Yaratım
Bir TextStream nesnesine erişmek için FSO'nun CreateTextFile
veya OpenTextFile
metodlarını kullanabileceğimiz gibi File nesnesinin OpenAsTextStream
metodunu da kullanabiliriz.
CreateTextFile
Syntax: fso.CreateTextFile(dosyadı,Overwrite?,UnicodeDesteği?)
Aşağıdaki kod ile varolan bir dosyayı, eğer mevcutsa üzerine yazdırarak (yani içini boşaltarak) Türkçe karakterleri de destekleyecek şekilde açıyoruz.
'global fso nesnesinin var olduğunu düşünerek ilerliyoruz
Dim ts As TextStream
Set ts = fso.CreateTextFile("c:\deneme\deneme.txt", True, True)
Eğer ikinci parametreyi False olarak kullanmak yani dosya mevcutsa onu ezmeyelim istiyorsak, aşağıdaki gibi dosyanın varlığını kontrol ederek açmalıyız yoksa "dosya zaten mevcut" hatası alırız.
If Not fso.FileExists("C:\Users\Volkan\Desktop\denemeler\deneme1.txt") Then
Set ts = fso.CreateTextFile("C:\Users\Volkan\Desktop\denemeler\deneme1.txt", False, True)
ts.Write ("merhaba")
End If
OpenTextFile
Syntax: fso.OpenTextFile(dosyadı,I/O tipi,MevcutDeğilseYaratılsınmı?,Format)
Set ts = fso.OpenTextFile("C:\deneme\deneme.txt",ForWriting,True,TristateFalse)
I/O tipi, ForWriting açıldığında içerik ezilir. Bu CreateTextFile'ın ikinci parametresinin True olarak açılmasıyla aynı etkidedir.
ForReading ile okuma yaparsınız, yazmaya izin verilmez.
ForAppending ile en sona konumlanır ve oraya yazarsınız, böylece mevcut içerik silinmemiş olur.
Üçüncü parametreyi, dosya mevcut değilse yaratmak istediğinizde True olarak kullanırız. Eğer burası False ise ve aradığınız dosya yoksa hata alırsınız. O yüzden ya burayı True yapmalısınız ya da dosyanın mevcut olup olmadığını kontrol etmelisiniz. Mesela aşağıdaki kod ile, dosya mevcut ise sonuna ekleme yapmak istiyoruz, mevcut değilse yaratarak açıyoruz.
If Not fso.FileExists("C:\Users\Volkan\Desktop\denemeler\deneme2.txt") Then
Set ts = fso.OpenTextFile("C:\Users\Volkan\Desktop\denemeler\deneme2.txt", ForWriting, True, TristateFalse)
Else
Set ts = fso.OpenTextFile("C:\Users\Volkan\Desktop\denemeler\deneme2.txt", ForAppending, False, TristateFalse)
End If
Son parametre Unicode desteği ile olup olmayacağını belirtir.
OpenAsTextStream
Elinizde bir File nesnesi varsa bunun OpenAsTextStream
metodunu kullanarak da metin dosyalarını açabilirsiniz. Gerçi File nesnesi için de yine bir FSO nesnesi gerekiyor. O yüzden her ikisini de yaratmak gerekecek. Eğer File nesnesini başka bir şey için kullanmayacaksanız boşuna bu zahmete gerek yok, direkt FSO ve onun metodları yeterli olacaktır.
Syntax: File.OpenAsTextStream(I/O modu,Format)
İki parametre de opsiyonel olup default değerleri sırasıyla ForReading ve TristateFalse'tur. Aşağıda bir örnek bulunmakta.
'Örnek kullanım
Dim f As File
Set f = fso.GetFile("C:\deneme\deneme.txt")
Dim ts As TextStream
Set ts = f.OpenAsTextStream(ForReading, TristateFalse)
TextStream Üyeleri
Metin okuma şekilleri
ts.Read(5) 'Bulunulan yerden itibaren 5 karakter okur
ts.ReadLine 'Bulunulan satırı okur
ts.ReadAll 'Tüm dosya içeriğini okur
Üç yöntemde de bir değişkene atama işlemi yapılmalıdır.
Ör: içerik=ts.ReadLine
Yazma şekilleri
ts.Write(metin): Dosyaya metni yazar
ts.WriteLine(metin): Dosyaya metni yazar ve bir alt satıra geçer
ts.WriteBlankLines(5): Dosyaya 5 adet boş satır ekler
Line
ile cursor'ın o anki satır numarasını elde ederiz.
Close
metodu ile TextStream nesnesini kapatarız.
Dosyada okuma yaparken, belirli koşullar durumunda o satırı SkipLine
ile atlayarak bir sonraki satıra geçebiliriz. Aşağıdaki kod ile, sayısal bir ifadeyle başlayan her şeyi bir collection'a atayıp en son da bunları yazdırıyoruz. Read
ile bir karakter okuduktan sonra kalanını ReadLine
yaparken başına ilk okuduğumuz kısmı eklediğimize dikkatinizi çekmek isterim. Örnek dosyamız aşağıdaki gibi olsun:
1-birinci satır
2-ikinci satır
falanfilan
3-üçüncü satır
falanfilan
4-dördüncü satır
Sub Satıratla()
Dim ts As TextStream
Dim col As New Collection
Set ts = fso.OpenTextFile("C:\Users\Volkan\Desktop\denemeler\deneme1.txt", ForReading, False, TristateMixed)
Do
kelime = ts.Read(1)
If IsNumeric(kelime) Then
col.Add kelime + ts.ReadLine
Else
ts.SkipLine
End If
Loop Until ts.AtEndOfStream
For Each Item In col
Debug.Print Item
Next Item
End Sub
Çıktı ise şöyle olacaktır:
1-birinci satır
2-ikinci satır
3-üçüncü satır
4-dördüncü satır
Hepsi bir arada bir örnek
Sub çeşitli_üyeler()
Dim ts As TextStream
Const dosya As String = "C:\Users\Volkan\Desktop\denemeler\ts_üyeler.txt"
Set ts = fso.CreateTextFile(dosya, True, True)
ts.WriteLine ts.Line & "-" & Now
ts.Write ts.Line & "-": ts.WriteBlankLines (1) 'Dosyaya 1 adet boş satır ekler
ts.WriteLine ts.Line & "-" & Environ("username")
ts.WriteLine ts.Line & "-" & "selam"
ts.WriteLine ts.Line & "-" & "naber"
Debug.Print ts.Line
ts.Close
Set ts = fso.OpenTextFile(dosya, ForReading, False, TristateMixed)
x = ts.ReadLine ' Bulunulan satırı okur
ts.skipline 'ilgili satırı atlar
y = ts.Read(5) 'Bulunulan yerden itibaren 5 karakter okur, artık 3. satırdayız: 3-Vol
z = ts.ReadAll 'Cursordan itibaren tüm dosya içeriğini okur, baştan itibaren değil :kan4-selam5-naber
Debug.Print z
End Sub
Otomasyon süreçlerinde Logger kullanımı
Diyelim ki aşağıdaki prosedür günün belirli saatlerinde çalışıyor. Çalışmanın belirli aşamalarını (kritik önemde veya ana işlerin öncesinde/sonrasında) kayıt altına alıyoruz. Ayrıca bir hata oluşursa yine bunu da kayıt altına alalım.
Otomasyon süreçlerinde Log tutmanın bir alternatifi kendinize veya ilgili kişilere mail attırmak olacaktır. Ancak çalışan çok fazla iş varsa mail kalabalığında boğulursunuz. O yüzden log sistemi daha güzel bir seçenektir.
Şimdi aşağıdaki örnekte Log dosyamızda Tarih/Saat, Kullanıcı, bilgisayar adı, rapor adı, log tipi, varsa hata kodu, açıklama kolonları olmak üzere 7 kolon bilgi bulunmaktadır. Bunun ilk 3'ü Logger fonksiyonu içinde dinamik olarak ele alınmakta, son 4 parametre ise Logger fonksiyonuna KrediRaporu modülünden argüman olarak gönderilmektedir. Diğer hususlar şöyledir:
- Rapor ismi toplamda 50 hane olacak şekilde ayarlanır. 50'den kısa olan rapor isimleri için başına 50'ye tamamlanacak kadar boşluk eklenir. Bunun amacı datayı Excel'e aktardığınızda aynı hizada görünmelerini sağlamaktır. Bu sizin dünyanızda daha yüksek bir sayıya ayarlanabilir.
- Bilgisayar ismi de yine aynı şekilde 10 haneye tamamlanmaktadır. Bu da sizin dünyanızda daha yüksek ayarlanabilir.
- Hata yoksa hata kodu olarak 0 gönderilmektedir.
'*****Logger'ı çağıran prosedür*****
Sub KrediRaporu()
On Error GoTo hata
raporLoggerAd="KrediRaporu"
'çeşitli işler
Logger WorksheetFunction.Rept(" ", 50 - Len(raporLoggerAd)) & raporLoggerAd, "OK", 0, "Bölme işlemi başlayacak"
'çeşitli işler
Logger WorksheetFunction.Rept(" ", 50 - Len(raporLoggerAd)) & raporLoggerAd, "OK", 0, "Bölme işlemi bitti"
'çeşitli işler
Logger WorksheetFunction.Rept(" ", 50 - Len(raporLoggerAd)) & raporLoggerAd, "OK", 0, "Rapor başarıyla çalıştı"
Exit Sub
hata:
Logger WorksheetFunction.Rept(" ", 50 - Len(raporLoggerAd)) & raporLoggerAd, "Hata", Err.Number, Replace(Err.Description, vbNewLine, vbNullString)
End Sub
'*****Logger prosedürümüz*****
Sub Logger(rpr As String, logtip As String, hatano As Integer, açıklama As String)
On Error GoTo hata
Dim dosya As String
Dim dosyano As Variant
dosyano = FreeFile
dosya = gunlukklasor + "\GünlükRaporlarLog.txt"
Open dosya For Append As #dosyano
Print #dosyano, CStr(Now), Environ("UserName"), WorksheetFunction.Rept(" ", 10 - Len(Environ("computername"))) & Environ("computername"), rpr, logtip, hatano, açıklama
Close #dosyano
Exit Sub
hata:
Call mail_logger_hata(rpr, alicilar) 'Log prosedüründe bir şekilde hata önceden berlirlenmiş alınırsa alıcılara özel formatta mail atılır
End Sub
Kokpit uygulamalarında Logger kullanımı
Userform konusunda gördüğümüz Kokpit uygulamalarında, uygulamayı kullanan kişilerin aktivitelerini aşağıdakine benzer bir kod ile kayıt altına alabiliriz.
'Form üzerindeki bir butona tıklanınca
Sub Btn_KrediRaporAc()
On Error Goto hata
'rapor açma kodları
Rapor="KrediRapor"
frekans="Günlük"
Call detayraporlogu(Rapor, frekans)
Exit Sub
hata:
On Error Goto -1
On Error Goto hata2
'burada hata kaydını tutan bir log kaydı(aşağıdaki log prosedürünü gölgede bırakmasın diye detayına girmedim)
Exit Sub
hata2:
'Diskte yer olmaması, veya kullanıcının ilgili diske yazma yetkisinin olmaması gibi bir sebeple hata olması durumunda
Call LogHata 'bu sefer maille size bilgilendirme yapılır
End Sub
'*****Logger prosedürümüz*****
Sub detayraporlogu(ByVal Rapor As String, ByVal frekans As String)
If Environ("UserName") = sizinuserınız Then Exit Sub 'kendimizi loglamıyoruz
i = FreeFile
Open adres & "Kokpitlog_detayrapor.txt" For Append As i
Print #1, Environ("UserName"), Date, Time, frekans, Rapor
Close #1
End Sub
Daha sonra bu text dosyasını bir Excel dosya içine aktarır veya her açıldığında refresh olan bir bağlantı kurarak gelen data üzerinde pivot tablolarınızı oluşturabilirsiniz. Metin dosyalarından bağlantı kurmak için buraya bakabilirsiniz.
Logger içinde hata
Bir sebeple logger fonksiyonu içinde de hata olursa bunu da başka bir hata bloğuyla ele alabilirsiniz. Veya ana gönderici modülde On Error GoTo -1
deyip 2. bir hata bloğu açabilirsiniz. Yukarıdaki ilk örnekte Logger fonksiyonu içinde hata bloğu ile yakaladık. İkinci örnekte ise ana prosedürde On Error GoTo -1
yöntemini kullandık.
Settings işlemleri
Bir dosyadan bir database'in kullanıcı adı ve şifresini okuma, veya bir dosyanın path'ini okuma gibi işlemler de bu sayfada öğrendiklerimizle yapılabilir.
Diyelim ki jenerik bir Add-in yaptınız. Bu Add-indeki makrolardan bir tanesi bir klasördeki bir Excel dosyasını açacak. İşte bu Excel dosyanın yerinin sabit olmasının mümkün olmadığı, bunun hangi klasörde olacağını kullanıcıya bırakmanız gereken durumlar olabilecektir. SettingforAddin1.txt gibi bir dosya içine bu klasörün tam path'i yazılabilir. Hatta buna birden fazla dosya için birden fazla klasör de eklenebilir. İstenirse ";" ile ayırılır, istenirse satır satır yazılır, hiç farketmez. Yukarıdaki yöntemlerden biriyle ilgili adresi elde etmek oldukça kolaydır.
SQL metinlerini değiştirme
Diyelim ki raporlama araçlarınız çok hantal ve katı. Siz de gerek kendiniz gerek departmanınız için Excel içinden çalışan hızlı ve esnek bir raporlama platformu oluşturdunuz. İlgili raporların SQL'ini bir metin dosyası içine koydunuz. Kullanıcıya tarih ve müşteri listesi gibi sorular sordurarak dosyadaki parametrik kısımlarla kullanıcının verdiği cevapları replace ettirerek nihai SQL'inizi elde edersiniz. Böylece uzun bir SQL'i VBA içine satır satır yazmaktan kurtulmuş olursunuz. VBA içine de SQL kodu yazılabilir ama bu hem kodun uzun ve çirkin görünmesine neden olur hem de çok zahmetli bir iştir, özellikle SQL onlarca hatta yüzlerce satırdan oluşuyorsa.
Sub SQLDeğiştir()
tarih=InputBox("tarihi girin")
If tarih=vbNullString Then Exit Sub
adres="C:\SQLller\kredi.txt"
Open adres For Input As #1
içerik=Input(LOF(1),1)
Close #1
strSQL=Replace(içerik,"trh",tarih) 'SQLi elde ettik
'bundan sonra SQL'i çalıştıracak kodlar devreye girer
End Sub