Funkcje Daty i Czasu

Funkcja Timer 

Funkcja Timer zwraca liczbę typu Single, która zawiera informację, ile minęło sekund od północy.

Przykład1

MsgBox "Od północy minęło: " & Timer & " sekund"

Przykład2

Dim Godziny As Long
Godziny = Int(Timer / 3600)   '3600=60*60
Debug.Print "Od północy minęło: " & Godziny & " pełnych godzin"

Funkcja Date

Funkcja Date zwraca dzisiejszą datę w domyślnym formacie systemowym. Jest to odpowiednik Excelowej funkcji DZIŚ()

Przykład użycia:

Debug.Print "Dzisiaj mamy: " & Date

Funkcja Time

Funkcja Time zwraca aktualny czas.

Debug.Print "Aktualna godzina: " & Time

Funkcja Now

Funkcja ta zwraca aktualną datę wraz z godziną. Jest to odpowiednik Excelowej funkcji TERAZ()

Debug.Print "Obecna data z godziną: " & Now

Funkcje Day, Month, Year

Funkcje te z zmiennej typu Date wyciągają kolejno: dzień, miesiąc lub rok. Są to odpowiedniki Excelowych funkcji DZIEŃ, MIESIĄC i ROK.

Sub DayMonthYear()
    Dim Data As Date
    Dim Dzien As Byte, Miesiac As Byte, Rok As Integer
    
    Data = Date 'Zapisz do zmiennej dzisiejszą datę
    Dzien = Day(Data)
    Miesiac = Month(Data)
    Rok = Year(Data)
    
    If Dzien > 15 Then
        MsgBox "No to już mamy z górki"
    Else
        MsgBox "Dopiero co się miesiąc zaczął a już byś chciał iść na urlop"
    End If
End Sub

Funkcja WeekDay

Funkcja ta zwraca numer dnia tygodnia. Domyślnie pierwszym dniem tygodnia jest niedziela. Przykład:

Debug.Print Weekday(Date)

Domyślnie funkcja zwraca liczbę od 1 (niedziela) do 6 (sobota). Jeśli chcemy, aby dzień tygodnia był liczony od np. poniedziałku, należy jako drugi parametr funkcji podać początek tygodnia np.

Debug.Print Weekday(Date, vbMonday)

Dopuszczalne wartości dla drugiego parametru:

StałaWartośćOpis
vbUseSystem0Użyj ustawień NLS API
vbSunday1Niedziela (wartość domyślna jeśli pominiemy drugi parametr)
vbMonday2Poniedziałek
vbTuesday3Wtorek
vbWednesday4Środa
vbThursday5Czwartek
vbFriday6Piątek
vbSaturday7Sobota

Funkcje Hour, Minute, Second

Funkcje te z zmiennej typu Date wyciągają kolejno: godziny, minuty i sekundy. Są to odpowiedniki Excelowych funkcji: GODZINA, MINUTA, SEKUNDA.

Sub GodzinaMinutySekundy()
    Dim Czas As Date
    Dim Godzina As Byte, Minuty As Byte, Sekundy As Byte
    
    Czas = Time
    Godzina = Hour(Czas)
    Minuty = Minute(Czas)
    Sekundy = Second(Czas)
    
    If Godzina >= 8 And Godzina <= 16 Then
        MsgBox "Pewnie siedzisz teraz w pracy"
    Else
        MsgBox "Pewnie teraz jesteś w domu"
    End If
End Sub

Dwa słowa o typie Date

Jeśli używamy zmiennych zawierających Datę lub Czas to należy przypisać taką wartość do zmiennej typu Date. Jest to może na początku nieco nieintuicyjne, gdyż zmienna typu Date może przechowywać albo samą datę, albo sam czas albo datę i czas. Myślę, że ten prosty przykład rozwieje Twoje wątpliwości:

Sub TestTypuDanychDate()
    Dim TylkoData As Date, TylkoCzas As Date, DataCzas As Date
    
    TylkoData = Date
    TylkoCzas = Time
    DataCzas = Now
    
    Debug.Print "Aktualna data: " & TylkoData
    Debug.Print "Aktualny czas: " & TylkoCzas
    Debug.Print "Data i czas: " & DataCzas
End Sub

Tak naprawdę zmienna typu Date przechowuje datę (jako liczbę zmiennoprzecinkową) podobnie jak Excel.

Jeśli przypiszemy do zmiennej typu Date godzinę to wewnętrznie ta zmienna przechowuje ułamek doby jaki minął od północy (czyli godzina 06:00 rano to tak naprawdę ułamek 0,25, godzina 12:00 to jest ułamek 0,5 18:00 to ułamek 0,75 a 23:59 to nieco ponad 0,9993).

Jeśli do zmiennej typu Date przypiszemy samą datę (np. 06.07.2024) to przechowuje ona wartość jako liczba dni które upłynęły od 1 stycznia roku 1900 czyli dla tej daty będzie to wartość 45479.

Z kolei jeśli do zmiennej przypiszemy Datę i czas (np. wartość zwróconą przez funkcję Now) to zmienna ta zawiera liczbę dni, które upłynęły od 1 stycznia 1900 plus ułamek doby (czyli dla wartości 06.07.2024 06:00:00 zmienna ta ma wartość 45479,25).

Szybkie dodawanie/odejmowanie dni

Ponieważ zmienna typu Date to tak naprawdę liczba przechowująca ile dni minęło od 1 stycznia roku 1900 to zwiększając lub zmniejszając wartość tej zmiennej możemy generować daty odległe o x dni względem danej daty.

Sub TestZmiennejDate()
    Dim Dzis As Date
    
    Dzis = Date
    Debug.Print "Wczorajsza data: " & Dzis - 1
    Debug.Print "Dzis: " & Dzis
    Debug.Print "Jutrzejsza data: " & Dzis + 1
End Sub

Funkcja DateSerial

Funkcja DateSerial jest odpowiednikiem Excelowej funkcji DATA. Jeśli masz poszczególne składowe daty w osobnych zmiennych a potrzebujesz daty w postaci jednej zmiennej, to możesz użyć tej funkcji.

Sub DateSerialTest()
    Dim Dzien As Byte, Miesiac As Byte, Rok As Integer
    Dim Data As Date
    
    Rok = 2024
    Miesiac = 4
    Dzien = 12
    Data = DateSerial(Rok, Miesiac, Dzien) '2024-04-12
    
    MsgBox Data
End Sub

Funkcja ta w połączeniu np. z funkcjami Month, Day, Year przydaje się również gdy chcesz skonstruować datę typu pierwszy dzień bieżącego miesiąca tego roku.

Sub PierwszyDzienTegoMiesiaca()
    Dim Dzien As Byte, Miesiac As Byte, Rok As Integer
    Dim Data As Date
    
    Rok = Year(Date)
    Miesiac = Month(Date)
    Dzien = 1
    Data = DateSerial(Rok, Miesiac, Dzien)
    
    MsgBox "Pierwszy dzien tego miesiaca: " & Data
End Sub

Funkcja TimeSerial

Funkcja ta jest odpowiednikiem Excelowej funkcji CZAS. Jeśli masz zapisane zmienne godzina, minuta sekunda jako osobne zmienne a chcesz utworzyć zmienną typu Date to możesz użyć tej funkcji.

Sub TimeSerialTest()
    Dim Czas As Date
    Dim Godz As Integer, Min As Integer, Sek As Integer
    
    Godz = 12
    Min = 15
    Sek = 30
    
    Czas = TimeSerial(Godz, Min, Sek)
    MsgBox Czas
End Sub

Możemy też użyć tej funkcji np. do wygenerowania obecnej pełnej godziny

Sub ObecnaPelnaGodzina()
    Dim Czas As Date
    Dim Godz As Integer, Min As Integer, Sek As Integer
    
    Godz = Hour(Time)
    Min = 0
    Sek = 0
    
    Czas = TimeSerial(Godz, Min, Sek)
    MsgBox Czas
End Sub

Aby otrzymać następną pełną godzinę użyjemy podobnego kodu, ale tutaj musimy wprowadzić drobne zabezpieczenie (godzina nie może być większa od 23 gdyż najpóźniejszy możliwy czas to godzina 23:59:59 sekundę później mamy już godzinę 0:00). Tutaj możemy użyć funkcję Mod (reszta z dzielenia przez 24).

Sub NastepnaPelnaGodzina()
    Dim Czas As Date
    Dim Godz As Integer, Min As Integer, Sek As Integer
    
    Godz = Hour(Time) + 1
'Zabezpieczenie: Jeśli Godz=24 to Godz=0, jeśli Godz=25 to Godz=1 itp.

    Godz = Godz Mod 24 
    Min = 0
    Sek = 0
    
    Czas = TimeSerial(Godz, Min, Sek)
    MsgBox Czas
End Sub

Aby wygenerować dokładną datę wraz z godziną np. 17:00 obecnego dnia możemy do zmiennej typu Date dodać czas zwrócony przez funkcję TimeSerial. Oto prosty przykład:

Sub NajblizszyTeleexpress()
    Dim Teleexpress As Date
    
    If Hour(Date) < 17 Then
        Teleexpress = Date + TimeSerial(17, 0, 0)
    Else
        Teleexpress = Date + 1 + TimeSerial(17, 0, 0)
    End If
    
    MsgBox "Najbliższy Teleexpress będzie w TV: " & Teleexpress
End Sub

Funkcja IsDate

Jeśli użytkownik wprowadza datę, musimy sprawdzić czy to co wprowadził, wygląda jak data. Oto przykładowy fragment (pobieramy od użytkownika datę urodzenia za pomocą funkcji InputBox)

Sub TestDaty()
    Dim U As Variant
    
    U = InputBox("Podaj datę urodzenia", "Data ur", "1991-01-02")
    
    If IsDate(U) Then
        MsgBox "Rok urodzenia: " & Year(CDate(U))
    Else
        MsgBox "Wpisałeś nieprawidłową datę", vbExclamation
    End If
End Sub

Jeśli w instrukcji InputBox użytkownik poda datę (w formacie takim, jaka jest data według ustawień regionalnych) to wyświetl się jego rok urodzenia. Ale jeśli użytkownik wpisze datę w złym formacie lub jakieś błędne dane (np. swoje imię) to funkcja IsDate  zwróci wartość fałsz.

Funkcja IsDate jest „w miarę” inteligentna. Tj. jeśli wprowadzisz datę w formacie rrrr-mm-dd lub mm/dd/rrrr to potraktuje to jako prawidłową datę. Natomiast data w formacie dd.mm.rrrr zostanie przez funkcję potraktowana jako poprawna data tylko wtedy gdy domyślny format daty systemowej jest właśnie ustawiony w tym formacie (co jest domyślne dla polskojęzycznych wersji systemu Windows od czasów Windows 10, w starszych Windowsach domyślny format daty to rrrr-mm-dd więc tam data w formacie dd.mm.rrrr nie przechodzi).

Uwaga: zawsze gdy pobieramy dane od użytkownika (np. odczytujemy wartość z komórki, odczytujemy wartość z pliku, użytkownik wpisuje dane w formularzu i/lub okienku InputBox) należy sprawdzić, czy to co wprowadził użytkownik wygląda na datę. Gdybyśmy użyli np. funkcji Hour na zmiennej, która nie zawiera daty (a np. imię użytkownika) to ta funkcja zwróci błąd.

Wskazówka: aby zobaczyć jaki mamy ustawiony domyślny format daty na komputerze możemy użyć następującego kodu:

Msgbox Date

Albo dla konkretnej daty:

Msgbox DateSerial(1991, 01, 02)

DateAdd

Funkcja DateAdd dodaje (lub odejmuje) do danej daty określoną liczbę danych jednostek (np. dni). Funkcja ta zwraca datę. Funkcja przyjmuje 3 argumenty:

  • Interwał
  • Liczba
  • Data od której dodajemy/odejmujemy odpowiednią liczbę jednostek interwału
InterwałOpis
yyyyRok
qKwartał
mMiesiąc
yNumer dnia roku (np. 15 luty = 46)
dNumer dnia miesiąca
wDzień tygodnia (od 0 do 6)
wwTydzień roku
hGodzina
nMinuta
sSekunda

Może to naukowo zabrzmiało, ale zerknij na ten oto przykład a wszystko się rozjaśni

Sub TestDateAdd()
    Dim DataUr As Date
    Dim Osiemnastka As Date
    
    DataUr = DateSerial(1990, 3, 2)
    Osiemnastka = DateAdd("yyyy", 18, DataUr)
    
    MsgBox "Pełnoletność osiągnąłem dnia: " & Osiemnastka
End Sub

Sub TestDateAdd2()
    Dim Tabletka As Date
    Dim NastepnaDawka As Date
    
    ' Następna dawka za 6 godzin od teraz
    Tabletka = Now
    NastepnaDawka = DateAdd("h", 6, Tabletka)
    
    MsgBox "Następną dawkę lekarstwa należy zażyć: " & NastepnaDawka
End Sub

Wskazówka: Liczba jak najbardziej może być ujemna (np. jak chcesz obliczyć datę/czas z przeszłości)

DateDiff

Funkcja ta „w przybliżeniu” jest odpowiednikiem nieudokumentowanej w Excelu funkcji DATA.RÓŻNICA.

Funkcja zwraca liczbę jednostek czasu pomiędzy dwiema datami. Pierwszy argument funkcji do Interwał (patrz powyższa tabela) a dwa kolejne to daty pomiędzy którymi obliczamy różnicę.

Sub TestDateDiff()
    Dim StanWojenny As Date
    Dim Dzisiaj As Date
    
    StanWojenny = DateSerial(1981, 12, 13)
    Dzisiaj = Now
    
    MsgBox "Od stanu wojennego minęło " & DateDiff("yyyy", StanWojenny, Dzisiaj) & " lat kalendarzowych"
End Sub

Uwaga – funkcja DateDiff działa nieco inaczej niż DATA.RÓŻNICA. Np. DATA.RÓŻNICA oblicza ile minęło PEŁNYCH lat między dwiema datami a funkcja DateDiff(„yyyy”, DateSerial(2023, 12, 1), DateSerial(2024, 1, 1)) zwróci wartość 1 pomimo, że między tymi datami minął jeden dzień a NIE jeden PEŁNY rok.

DatePart

Funkcja ta wyciąga ze zmiennej typu Date odpowiednią wartość (według tabeli interwał). Szczerze mówiąc to jej za bardzo nie używam, gdyż w większości przypadków inne funkcje (np. Day, Month, Year, Hour, Minute, Second, WeekDay) robią to samo a są czytelniejsze.

Funkcji Datepart raczej używam tylko wtedy gdy chcę zwrócić wartość, do których w VBA nie ma odrębnych funkcji tj.

  • numer kwartału dla danej daty (q),
  • numer dnia roku (y)
  • numer dnia tygodnia (ww)
Sub TestDatePart()
    'Taki sam efekt da: MsgBox Year(Now)
    MsgBox DatePart("yyyy", Now) 
End Sub

Sub TestDatePart2()
    Dim Kw As Byte
    
    Kwartal = DatePart("q", Now)
    MsgBox "Mamy teraz " & Kw & " kwartał roku"
End Sub

Format

Funkcja ta jest odpowiednikiem funkcji TEKST z Excela. Formatuje ona liczbę według zadanego formatu.

Nie jest to typowa funkcja daty i czasu ale umieszczam ją w tym zestawieniu, gdyż jest bardzo przydatna.

Funkcja ta zwraca tekst, którym jest liczba (a data i czas to tak naprawdę są liczby) według zadanego formatu. Najczęściej używam tej funkcji do generowania nazw plików, które w sobie zawierają odpowiednio sformatowaną datę (i/lub czas) utworzenia raportu (lub wystąpienia błędów itp.)

Oto prosty przykład:

Sub TestFormat()
    Dim Plik As String

    Debug.Print "Data w formacie yyyy-mm-dd"
    Debug.Print Format(Date, "yyyy-mm-dd")
    
    Debug.Print "Data w formacie 2 cyfry roku, miesiąc z zerem wiodącym, dzień z zerem wiodącym"
    Debug.Print Format(Date, "yymmdd")
    
    Debug.Print "Czas w formacie hhmm (bez dwukropka w środku)"
    Debug.Print Format(Time, "hhmm")
    
    Debug.Print "Czas w formacie hh:mm"
    Debug.Print Format(Time, "hh:mm")
    
    Plik = "[" + Format(Now, "yyyy-mm-dd hh:mm:ss") + "] raport.txt"
    Debug.Print "Nazwa pliku: " & Plik
End Sub

TestFormatDateTime

Funkcja ta wyświetla Datę i/lub czas w określonym formacie korzystając z ustawień systemowych. Pierwszym argumentem jest zmienna typu Date a drugim format w jakim ma zostać zwrócona data/czas (gdy nie podamy drugiego argumentu to domyślnie przyjmuje się wartość vbGeneralDate).

Oto drugi argument:

StałaWartośćOpis
vbGeneralDate0Wyświetlanie daty i/lub godziny. Jeśli dostępna jest część z datą, wyświetl ją jako datę krótką. Jeśli dostępna jest część z godziną, wyświetlana jest jako czas w formacie długim np. 2024-07-06 12:57
vbLongDate1Wyświetlanie daty przy użyciu długiego formatu daty określonego w ustawieniach regionalnych komputera np. 6 lipiec 2024
vbShortDate2Wyświetlanie daty przy użyciu skróconego formatu daty określonego w ustawieniach regionalnych komputera np. 2024-07-06
vbLongTime3Wyświetlanie godziny przy użyciu formatu czasu określonego w ustawieniach regionalnych komputera np. 12:57:04
vbShortTime4Wyświetlanie czasu w formacie 24-godzinnym (hh:mm) np. 12:57
Sub TestFormatDateTime()
    Debug.Print "Data i czas ustawienia domyślne: " & FormatDateTime(Now)
    Debug.Print "Data i czas ustawienia domyślne (inny sposób): " & FormatDateTime(Now, vbGeneralDate)
    Debug.Print "Data długa: " & FormatDateTime(Now, vbLongDate)
    Debug.Print "Data krótka: " & FormatDateTime(Now, vbShortDate)
    Debug.Print "Czas ustawienia regionalne: " & FormatDateTime(Now, vbLongTime)
    Debug.Print "Czs w formacie hh:mm (bez ss): " & FormatDateTime(Now, vbShortTime)
End Sub

Funkcja FileDateTime

Funkcja ta zwraca datę i czas kiedy ostatniej modyfikacji danego pliku. Oto prosty przykład:

Sub TestFileDateTime()
    Dim DataMod As Date
    
    DataMod = FileDateTime("c:\pliki\raport.xlsx")
    MsgBox "Raport był zmodyfikowany dnia: " & DataMod
End Sub

Uwaga: funkcja ta zwraca błąd, gdy podasz nazwę pliku, który nie istnieje. Dlatego przed jej użyciem warto sprawdzić, czy plik o podanej nazwie istnieje lub dodać obsługę błędów.

Odpowiedniki funkcji Excel w języku VBA

Funkcja w ExceluFunkcja w VBA
DZIŚ()Date
TERAZ()Now
TERAZ() – DZIŚ()Time
DZIEŃDay
MIESIĄCMonth
ROKYear
GODZINAHour
MINUTAMinute
SEKUNDASecond
DATADateSerial
CZASTimeSerial
DZIEŃ.TYGWeekDay
DATA.RÓŻNICA*DateDiff
TEKST**Format

* Uwaga – funkcja DateDiff działa nieco inaczej niż DATA.RÓŻNICA. Np. DATA.RÓŻNICA oblicza ile minęło PEŁNYCH lat między dwiema datami a funkcja DateDiff(„yyyy”, DateSerial(2023, 12, 1), DateSerial(2024, 1, 1)) zwróci wartość 1 pomimo, że między tymi datami minął jeden dzień a NIE jeden PEŁNY rok.

** Nie jest to typowa funkcja Daty i czasu, ale ponieważ korzystam z tej funkcji do formatowania wyników zwróconych przez inne funkcje daty i czasu to pozwoliłem sobie ją dodać do tego zestawienia

Uwaga powyższe funkcje w VBA i arkuszu Excel nie są w 100% identyczne. Np. funkcja DateDiff posiada więcej parametrów niż funkcja DATA.RÓŻNICA. Oprócz tego funkcje mogą się nieco różnić kodami formatów np. dla funkcji Format w VBA dla roku używamy formatu yyyy a w arkuszowej funkcji TEKST będzie to rrrr.