Tarihsel Fonksiyonlar
Ön Bilgiler
Excel’de tüm tarihlerin sayısal bir karşılığı vardır. Aslında karşılığı
vardır demekten ziyade tüm tarihler bir sayıdır demek daha doğru olur. Excel bunları gösterirken
tarih formatında gösterir. Tarihler tam sayı depolanırken saatler küsurlu
formda tutulur. Bu sayı 1.1.1900'den itibaren geçen günsayısıdır. Ör:17.05.2015
arka planda 42141 sayısı olarak tutulur.
Ayraçları, bölgesel ayarlar belirler, ancak tarih “#”
işaretleri arasında yazılırsa bölgesel ayarlardan bağımsız olarak Amerikan
tarih formatına göre belirtilmiş olur:Ay/gün/yıl. Bunu pek
kullanmanızı önermem, ancak görürseniz de şaşırmayın. Biz bildiğimiz
formatta kullanalım, yoksa 5 Temmuz yazacağınız yerde 7
Mayıs gibi sonuçlar
elde edebilirsiniz, bu da önemli hatalara neden olabilir.
Tarihlerle ilgili dikkat edilmesi gereken bir husus var.
Formatlı Gösterim tipi, kaynak tipi veya dönüş tipi. Formatlı Gösterim şekli
her zaman stringtir. Ancak kaynak tip veya dönüş tipi farklı tipler de
olabilir.
Tarihlerin kaynak/dönüş tipi aşağıdakiler olabilir.
- String
- Nümerik
- Tarihsel
- # karakterleri arasında
- Tarihsel bir
fonksiyondan dönen değer olarak. (Excel hücresinden veya Date, DateSerial gibi VBA
fonksiyonlarından)
Konuyla ilgili daha detaylı bilgiye
bu
sayfadan ulaşabilirsiniz.
DateTime modülü
Tarihsel işlemlerimizi yaparken DateTime modülünü kullanıyor olacağız. Bu
modüldeki fonksiyonlara geçmeden önce sık kullanılan property'lere bir
bakalım.
Propertyler
Date ve Date$: O anki günü verirler. İlki Variant döndürürken ikincisi
String döndürür. Aralarındaki fark, Variant olanda null işlemi yapabilmenizdir.
Bir diğer fark da Date ile bir sayıyı matematiksel işleme tabi
tutabilirsiniz ancak Date$ ile bunu yapamazsınız .
Debug.Print Date+1 'yarının tarihini verir
Debug.Print Date$+1 'hata verir. String olduğu için.
Aşağıdaki kod, üzerinde çalıştığımız dosyanın son değişikliğin tarihinin
bugünden küçük olması durumunda çalışır.
'fso tanımının yapıldığı kodlar
If fso.DateModified < Date Then
'diğer kodlar
End if
Time ve Time$: Şu anın saatini verir.
aralarındaki fark Date/Date$ arsındaki farkların aynısıdır.
Now: Şu anın tarih ve saatini verir. Date ve Time'ın birleşimi gibi
düşünülebilir.
Değişken tanımlamalar
DateTime modülünün içindeki Date tipi ile hem tarih hem saat tanımlanabilir.
Aşağıdaki örneklerde tüm değişkenli Variant tanımlıyoruz.
Dim tarih1 'As Date
Dim tarih2 'As Date<
Dim stringtarih1 'As String
Dim stringtarih2 'As String
Dim numeriktarih1 'As Long
Dim numeriktarih2 'As Double
Dim diyezlitarih1 'As Date
Dim diyezlitarih2 'As Date
Dim hucredentarih1 'As Date
Dim hucredentarih2 'As Date
Örnek kodlara geçmeden önce, Range nesnesinin Value ve Value2
özelliklerinin farkını
tekrar edelim. Value, hücrenin içeriğini alırken, Value2 tarihleri numerik
değere çevirerek depolar. (Tabi siz bir değişkeni Date olarak tanımladıysanız, ona
Value2 sonucunu aktarsanız bile sayısal değer değil yine tarihsel formattaki
değeri depolanır.)
Dönüş tipleri
tarih1 = Now
tarih2 = DateSerial(1979, 1, 21)
stringtarih1 = "21.01.1979"
stringtarih2 = "01.01.1979"
numeriktarih1 = 42574
numeriktarih2 = 42574.127
diyezlitarih1 = #1/21/1979# 'amerikan formatında olmak zorunda, önce ay ve ayraç oalrak da "/" girili "." dğeil. gün girerken 01
girsen bile enterea basıp alta geçince kaybolurlar.
diyezlitarih2 = #1/21/1979 4:30:00 AM# 'amerikan
formatında olmak zorunda, önce ay ve ayraç olarak da /
hucredentarih1 = range("a1").Value 'hücre içeriği:24.07.17 13:14
hucredentarih2 = range("a1").Value2 'hücre içeriği:21.01.1979
Şimdi bunların çeşitli özelliklerini yazdıralım.
Debug.Print "tarih1", vbTab, tarih1, TypeName(tarih1),VarType(tarih1), IsDate(tarih1)
Debug.Print "tarih2", vbTab, tarih2, vbTab, TypeName(tarih2), VarType(tarih2), IsDate(tarih2)
Debug.Print "stringtarih1", vbTab, stringtarih1, vbTab, TypeName(stringtarih1), VarType(stringtarih1), IsDate(stringtarih1)
Debug.Print "stringtarih2", vbTab, stringtarih2, vbTab, TypeName(stringtarih2), VarType(stringtarih2), IsDate(stringtarih2)
Debug.Print "numeriktarih1", vbTab, numeriktarih1, vbTab,TypeName(numeriktarih1), VarType(numeriktarih1), IsDate(numeriktarih1)
Debug.Print "numeriktarih2", vbTab, numeriktarih2, vbTab,TypeName(numeriktarih2), VarType(numeriktarih2), IsDate(numeriktarih2)
Debug.Print "diyezlitarih1", vbTab, diyezlitarih1, vbTab,TypeName(diyezlitarih1), VarType(diyezlitarih1), IsDate(diyezlitarih1)
Debug.Print "diyezlitarih2", vbTab, diyezlitarih2, TypeName(diyezlitarih2), VarType(diyezlitarih2), IsDate(diyezlitarih2)
Debug.Print "hucredentarih1", hucredentarih1, vbTab,TypeName(hucredentarih1), VarType(hucredentarih1), IsDate(hucredentarih1)
Debug.Print "hucredentarih2", hucredentarih2, vbTab,TypeName(hucredentarih2), VarType(hucredentarih2), IsDate(hucredentarih2)
Çıktısı aşağıdaki gibi olacaktır.
Dönüşüm İşlemleri
Bazen, gösterim tipi metinsel olan tarihleri tarih tipine çevirip onlar
üzerinden işlemlerinize devam etmek istersiniz. Bunun için VBA bize 4 yöntem
sağlmaktadır. Dördü de küçük nüanslar göstermektedir.
1.Yöntem:CDate(Exp):CDate, bir ifadeyi tarih yaparken tipini de tarih yapar.
Üstelik saat v.s bilgisi varsa bunları da korur. İçine her tür ifadeyi
alabilir.
x1 = CDate(tarih1)
x2 = CDate(tarih2)
x3 = CDate(stringtarih1)
x4 = CDate(stringtarih2)
x5 = CDate(numeriktarih1)
x6 = CDate(numeriktarih2)
x7 = CDate(diyezlitarih1)
x8 = CDate(diyezlitarih2)
x9 = CDate(hucredentarih1)
x10 = CDate(hucredentarih2)
Şimdi bunları yazdıralım.
Debug.Print x1, TypeName(x1), VarType(x1)
Debug.Print x2, TypeName(x2), VarType(x2)
Debug.Print x3, TypeName(x3), VarType(x3)
Debug.Print x4, TypeName(x4), VarType(x4)
Debug.Print x5, TypeName(x5), VarType(x5)
Debug.Print x6, TypeName(x6), VarType(x6)
Debug.Print x7, TypeName(x7), VarType(x7)
Debug.Print x8, TypeName(x8), VarType(x8)
Debug.Print x9, TypeName(x9), VarType(x9)
Debug.Print x10, TypeName(x10), VarType(x10)
Çıktısı şöyle olacaktır:
2.Yöntem:DateValue(Metin): Bu fonksiyon ile
metin formatındaki tarihler gerçek tarihe çevrilir. Saat v.s detayını
korumaz. Argüman olarak sadece metin alır.
DateValue("21.01.1979") '21 Ocak 1979 tarihini verir
DateValue(28876) 'hata verir. Çünkü argüman olarak sadece metin alır.
3.Yöntem:Format(exp,
format): sadece gösterim
şeklini tarihsel yapar,
dönüş tipi Stringtir. Dönen değerle tarihsel işlem yapılamaz.
İkinci parametre olarak
önceden tanımlanmış formatlar da girilebilir,
kullanıcı tanımlı formatlar da. Bunların
detayın
buradan ulaşabilriiniz.
y1 = Format(tarih1, "Short Date") 'önceden tanımlanmış parametre
y2 = Format(tarih2, "dd.mm.yyyy") 'bu ve aşağıdakiler ise kullanıcı tanımılı paremtredir
y3 = Format(stringtarih1, "dd.mm.yyyy")
y4 = Format(stringtarih2, "dd.mm.yyyy")
y5 = Format(numeriktarih1, "dd.mm.yyyy")
y6 = Format(numeriktarih2, "dd.mm.yyyy")
y7 = Format(diyezlitarih1, "dd.mm.yyyy")
y8 = Format(diyezlitarih2, "dd.mm.yyyy")
y9 = Format(hucredentarih1, "dd.mm.yyyy")
y10 = Format(hucredentarih2, "dd.mm.yyyy")
Şimdi de bunların çıktısını alalım
Debug.Print y1, TypeName(y1), VarType(y1)
Debug.Print y2, TypeName(y2), VarType(y2)
Debug.Print y3, TypeName(y3), VarType(y3)
Debug.Print y4, TypeName(y4), VarType(y4)
Debug.Print y5, TypeName(y5), VarType(y5)
Debug.Print y6, TypeName(y6), VarType(y6)
Debug.Print y7, TypeName(y7), VarType(y7)
Debug.Print y8, TypeName(y8), VarType(y8)
Debug.Print y9, TypeName(y9), VarType(y9)
Debug.Print y10, TypeName(y10), VarType(y10)
Çıktı sonucu aşağıdaki gibidir:
4.Yöntem:FormatDateTime(d,constant)):FormatDateTime da string döndürür, ama kullanımı daha
basittir, seçenekler sınırlıdır.
Seçeneklerde constantlar var, ön tanımlı veya
kullanıcı tanımlı parametre yok.
z1 = FormatDateTime(tarih1, vbShortDate)
z2 = FormatDateTime(tarih2, vbLongDate)
z3 = FormatDateTime(stringtarih1, vbLongDate)
z4 = FormatDateTime(stringtarih2, vbLongDate)
z5 = FormatDateTime(numeriktarih1, vbLongDate)
z6 = FormatDateTime(numeriktarih2, vbLongDate)
z7 = FormatDateTime(diyezlitarih1, vbLongDate)
z8 = FormatDateTime(diyezlitarih2, vbLongDate)
z9 = FormatDateTime(hucredentarih1, vbLongDate)
z10 = FormatDateTime(hucredentarih2, vbLongDate)
Şimdi de çıktı alalım.
Debug.Print z1, vbTab, TypeName(z1), VarType(z1), IsDate(z1) 'short olduğu ve içinde gün ismi geçmediği için True, aşağıdakiler false false false
Debug.Print z2, TypeName(z2), VarType(z2), IsDate(z2)
Debug.Print z3, TypeName(z3), VarType(z3), IsDate(z3)
Debug.Print z4, TypeName(z4), VarType(z4), IsDate(z4)
Debug.Print z5, TypeName(z5), VarType(z5), IsDate(z5)
Debug.Print z6, TypeName(z6), VarType(z6), IsDate(z6)
Debug.Print z7, TypeName(z7), VarType(z7), IsDate(z7)
Debug.Print z8, TypeName(z8), VarType(z8), IsDate(z8)
Debug.Print z9, TypeName(z9), VarType(z9), IsDate(z9)
Debug.Print z10, TypeName(z10), VarType(z10), IsDate(z10)
Sonuç aşağıdaki gibi olacaktır:
Toplama Çıkarma
VBA'de, Exceldeki yaptığımız gibi +1/-1 diyerek toplama
çıkarma yapılamıyor. Matematiksel işlemler için belirli fonksiyonlar
kullanılmalıdır.
- DateDiff/DateAdd
- DateValue("21.01.1979")+1
- Dateserial(1979,1,21)+1
- CDate("21.01.1979")+1
- #"li üzerinde işlem: #5/22/97# - #1/10/97#
- Date döndüren herhangi bir fonksiyonla.
(Date/Now veya UDF gibi)
c1 = diyezlitarih1 + 1 'datevalue veya DateAdd demeye gerek kalmadan doğrudan kullanılabilir
c2 = DateAdd("d", 1, stringtarih1)
c3 = stringtarih1 + 1 'istenmeyen sonuç: noktaları uçup ekleme yapar, yani yıla eklenmiş olur, 21011980
c4 = DateValue(stringtarih1) + 1
c5 = CDate(stringtarih1) + 1
c6 = tarih1 - tarih2
c7 = DateDiff("d", tarih2, tarih1)
c8 = (tarih1 - tarih2) / 30 'yaklaşık ay sayısı
c9 = DateDiff("m", tarih2, tarih1) 'kesin ay sayısı
c10 = (tarih1 - tarih2) / 365
Şimdi de çıktılarını alalım.
Debug.Print vbNewLine
Debug.Print c1, vbTab, TypeName(c1), IsDate(c1)
Debug.Print c2, vbTab, TypeName(c2), IsDate(c2)
Debug.Print c3, vbTab, TypeName(c3), IsDate(c3)
Debug.Print c4, vbTab, TypeName(c4), IsDate(c4)
Debug.Print c5, vbTab, TypeName(c5), IsDate(c5)
Debug.Print c6, TypeName(c6), IsDate(c6)
Debug.Print c7, vbTab, TypeName(c7), IsDate(c7)
Debug.Print c8, TypeName(c8), IsDate(c8)
Debug.Print c9, vbTab, TypeName(c9), IsDate(c9)
Debug.Print c10, TypeName(c10), IsDate(c10)
Çıktı şöyle olacaktır:
Diğer işlemler
IsDate ile "Tarih mi?" sorgulaması
Bir değerin tarih olup olmadığını sorgulanması için içeriğin
Short
Date veya saatli
Short
Date olması lazım.
Long Date veya numerik olursa
tarih olarak algılamaz.
Aşağıdaki örnekte, shcedule edilmiş bir makro ile, içindeki dosya
isimleri "Falanfilan raporu - 25.07.2017 Sonuçları.xlsm" gibi olan dosyalara
bakıyor ve belirtilen süreden önce eski olanları sildiriyorum. Belirli süreyi
tespit etme işlemini "Diğer kodlar" bölümünde yapıyorum, şuan bu ksıım
önemli değil. Her rapor için tespit ettiğim bu süre değerini
bir dictionary'de
depoluyorum. Mid(isim, Len(isim) - 19, 10) ile kestiğim kısım 25.07.2017'a
denk gelen kısım ve bunun tarih olup olmadığını sorguluyorum. Ancak bazen
ilgili klasörde manuel kaydedilmiş dosyalar olabiliyor, bunların silinmesini
istemiyorum, keza içinde Format ifadesi geçen dosyaların da silinmesini
istemiyorum.
Sub eskilerisil()
'Diğer kodlar
For Each d In
klasor.Files
isim = fso.GetBaseName(d)
If Len(isim) > 19 Then
If IsDate(Mid(isim, Len(isim) - 19, 10)) Then tarih = DateValue(Mid(isim,Len(isim) - 19, 10))
Else
tarih = DateSerial(2099, 12, 31)
End If
If Not aysonumu( Date - dict(kls)) = True And _
tarih < Date - dict(kls) And InStr(isim, "Format") = 0 Then
Kill d
End If
Next d
End Sub
Saat karşılaştırma
Hour'la, TimeSerial veya TimeValeu ile yapabiliriz.
If Hour(Now)>13 Then 'dakika detayı gerekli değilse
If TimeValue(Now) > #1:00 PM# Then
If TimeValue(Now) > #13:00# Then 'otomatik PM'e çevrilir
If TimeValue(Now) > #13:30:00# Then 'otomatik PM'e çevrilir
If TimeValue(Now) > TimeSerial(13, 0, 0) Then
Bir tarihin belirli kısımlarını alma
Parça fonksiyonları
tarih="31.12.2016 13:35:00"
Debug.Print Year(tarih) '2016
Debug.Print Month(tarih) '12
Debug.Print Day(tarih) '31
'Hour, Minute ve Second ile de saat, dakika e saniye döndürülür
DatePart
Yukarıdak parça parça alan fonksiyonların hepsini tek bir fonksiyon ve
parametre ile de yapabilriz, mesela yıl almak için DatePart("yyyy",tarih)
kullanılabilir. Ancak yukarıdakileri kullamak daha kolaydır. Yani basit
parça alma için bu fonksiyonu kallanmaucağz. Bununla beraber yılın kaçıncı günü,
yılın hangi çeyreği,
yılın hangi haftası v.s için
bu fonksiyon lazım. Mesela bu
söylediğim son 3 amaç için sırayla y,q,ww
parametrelerini kullanırız.
Dikkat:y ile yyyy karıştırmayın. yyyy yılı
veriken tek y yılın gününü verir, d de ayın gününü verir. Parametre
olarak kullanılabilecek tüm fadelere yine yukarda linkini verdiğimiz
bu sayfadan erişebilirsiniz.
Ay ve hafta adı
Debug.Print MonthName(Month(tarih)) 'Aralık
Debug.Print WeekdayName(Weekday(tarih)) 'Pazar
TimeSerial ve DateSerial
Yıl,Ay, Gün veya Saat,Dakika,Saniye bilgilerinin bir yerden temin
edilmesi durumunda da belirli tarih ve saatler elde edilebilmektedir.
Debug.Print DateSerial(2017,1,5)
Debug.Print TimeSerial(8,3,12)
Bazı özel tarihler
Aybaşı:DateSerial(year(Date),month(Date),1)
Aysonu: DateSerial(Year(Date), Month(Date)+1 , 1)-1 veya daha sade olarak DateSerial(Year(Date), Month(Date) + 1, 0)
Haftabaşı: Date - WeekDay(Date, vbUseSystem) + 1 ‘veya vbMonday
Haftasonu:Date - WeekDay(Date, vbUseSystem) + 7
Yılbaşı: DateSerial(Year(Date), 1, 1)
Yılsonu: DateSerial(Year(Date)+1, 1, 0)
Timer ile geçen süreyi hesaplama
Timer property'sini genelde bir prosedürün ne kadar sürede çalıştığını
bumak amaçlı kullanırız.
Sub timerkontrol()
Dim başlangıç As Single
Dim bitiş As Single
Dim i As Long
başlangıç = Timer
For i = 1 To 100000000 'Bu yapı For-Next döngüsüdür. Şimdilik bu döngünün nasıl kullanıldığını bilmiyor olabilirsiniz, buna takılmayın. Sonraki bölümlerde detaylıca incelenecek.
k = k + 1
Next i
bitiş = Timer
MsgBox ("İşlem süresi:" & vbNewLine & Round(bitiş - başlangıç, 2) & " saniyedir.")
End Sub
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ç
25203
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.
3
0
0
0
Soru No:50.
Aşağıdakilerden hangisiyle eldeki tarihin 1 gün sonrasını elde edemeyiz?