Banner Access
Tekst informacyjny o polityce Cookies Close   

Błędy obsługi pól typu Data przez MS Access

Moim zdaniem obsługa pól typu Data przez Access pozostawia wiele do życzenia.
Nigdy nie ma pewności, czy wpisana data zostanie prawidłowo zinterpretowana przez Access.
Dla przykładu: Format daty krótkiej w ustawieniach regionalnych: dd-MM-rr
Interpretacja roku dwucyfrowego:  1930 do 2029
Dla formantu formularza bez ustawionej maski wprowadzania możliwości popełnienia błędu są bardzo duże:

Tabela 1. Błędy wprowadzania danych
Bez maski wprowadzania:
Wartość wprowadzona: dd-MM-rrOtrzymana Data
11-111 1-11-111
1-11 1-11-2004
111-11-11 11-11-111
12-1313-12-2004
12-13-1413-12-2014
Maska wprowadzania: data krótka - 99-99-00;0;_
9-13-8813-09-1988
32-04-2424-04-1932
31-11-3030-11-1931

Jak widać wprowadzanie daty do formantów bez maski jest zupełnie pozbawione sensu. W przypadku zastosowania maski ilość błędów zostaje ograniczona, ale nie do końca. Dodatkowym utrudnieniem jest szybkie wprowadzania dat gdzie dzień, miesiąc i rok są jednocyfrowe np.      1-2-3   (01-02-2003)

W przypadku maski 99-99-09;0;_ możemy taką datę najłatwiej wprowadzić wpisując 1 separator  2  separator 3 - czyli praktycznie musimy wprowadzić 5 znaków. Ale przy takiej masce nie jesteśmy w stanie wprowadzić daty 1-2-1234. Musimy maskę zamienić na 09-09-0999;0;_.

I znowu problem - jeżeli użytkownik zmieni format daty krótkiej na rr-MM-dd, to nie będziemy w stanie wpisać tej daty w postaci 1234-2-1. Ponieważ nie jesteśmy w stanie przewidzieć, jaki format daty będzie miał użytkownik, więc respektując jego upodobania maskę tworzyć będziemy dynamicznie:
Dla formatu daty krótkiej:

  • dd-MM-rr) tworzymy maskę w postaci 99/99/99;0;_
  • dd-MM-rrrr i MM-dd-rrrr tworzymy maskę w postaci 99/99/9999;0;_
  • rrrr-MM-dd tworzymy maskę w postaci 9999/99/99;0;_
Maski takie umożliwiają szybsze wprowadzenie daty typu 1-2-3 poprzez wpisanie:
1 separator 2 separator 3
ale i tak i tak maska w formancie obsługującym datę praktycznie zawsze spowoduje jakieś problemy. Najmniej problemów jest, gdy maska zawiera same 9. Co prawda nie wymusza wpisywania odpowiednich znaków, a jedynie informuje użytkownika o formacie wprowadzanych danych. Sprawdzaniem poprawności daty zajmie się Access i procedury pomocnicze.

Ale i tak i tak maska w formancie obsługującym datę praktycznie zawsze spowoduje jakieś problemy. Najmniej problemów jest, gdy maska zawiera same 9. Co prawda nie wymusza wpisywania odpowiednich znaków, a jedynie informuje użytkownika o formacie wprowadzanych danych. Sprawdzaniem poprawności daty zajmie się Access i procedury pomocnicze.

Po wprowadzeniu daty do formantu pozostaje nam odczytanie składowych daty i sprawdzenie poprawności wartości daty za pomocą jednego z wyrażeń: Dt1 = DateSerial(CInt(sYear(i)), CInt(sMonth(i)), CInt(sDay(i)))
Dt2 = DateValue(sDay(i) & cShDateSep & sMonth(i) & cShDateSep & sYear(i))
Dt3 = DateValue(sMonth(i) & "/" & sDay(i) & "/" & sYear(i))
Dt4 = Eval("#" & sMonth(i) & "/" & sDay(i) & "/" & sYear(i) & "#")

Tabela 2. Format daty krótkiej dd-MM-rr
Lp. d(i) M(i) y(i) DateSerial (d-M-y) DateValue (d-M-y) DateValue (M/d/y) Eval(M/d/y)
1. 10 31 2004 10-07-2006 31-10-2004 31-10-2004 31-10-2004
2. 10 31 0004 10-07-2006 31-10-2004 31-10-2004 04-10-1931
3. 02 15 2004 02-03-2005 15-02-2004 15-02-2004 15-02-2004
4. 02 15 0004 02-03-2005 15-02-2004 15-02-2004 04-02-2015
5. 12 15 2004 12-03-2005 15-12-2004 15-12-2004 15-12-2004
6. 12 15 0004 12-03-2005 15-12-2004 15-12-2004 04-12-2015
7. 11 31 2004 11-07-2006 ERROR ERROR ERROR
8. 11 31 0004 11-07-2006 ERROR 04-11-1931 04-11-1931
9. 00 00 2004 30-11-2003 ERROR ERROR ERROR
10 00 00 0004 30-11-2003 ERROR ERROR ERROR
11. 32 12 2004 01-01-2005 ERROR ERROR ERROR
12. 32 12 0004 01-01-2005 04-12-1932 ERROR ERROR
13. 01 01 0100 01-01-100 01-01-100 01-01-100 01-01-100
14. 31 12 0099 31-12-1999 31-12-1999 31-12-1999 31-12-1999

Jak widać w Tabeli 2 DateSerial nie nadaje się do sprawdzanie poprawności daty. W zasadzie należałoby porównać Dt2, Dt3 i Dt4 (gdyż wyniki zależne są od kolejności części składowych daty krótkiej w Ustawieniach Regionalnych) i w przypadku zgodności wszystkich trzech wartości mamy 90% pewności, że data jest prawidłowa.
Niestety, pozostaje pewien procent niepewności: patrz poz.1 i poz.5

Dlatego też musimy wcześniej sprawdzić poprawność wprowadzonej wartości Miesiąca (w obu przypadkach miesiąc jest większy od 12), ale wprowadzony dzień jest prawidłową wartością dla miesiąca i Access w ten "inteligentny" sposób dopasowuje sobie datę, trochę niezgodnie z zamiarem użytkownika. Przypadek ten nie zachodzi dla poz.7 i poz.8 gdyż dzień 31 nie jest prawidłową wartością dla listopada.


BraShortDate_1 wielkość: 49 KB. Status: free

Sprawdzenie poprawności wprowadzanej daty.

  1. Typowy formant - bez maski - jedynie w celach porównawczych
  2. Testowy - bez maski - dla formantu nie jest tworzona maska wpisywania.
  3. Testowy - z maską:
    • 99/99/99;0;_ dla każdego formatu daty z dwucyfrowym rokiem
    • 9999/99/99;0;_ dla formatu daty krótkiej typu rrrr-MM-dd
    • 99/99/9999;0;_ dla formatu daty krótkiej typu dd-MM-rrrr i MM-dd-rrrr
    • Jeżeli separatorem daty jest znak "_" to znak maski zmieniany jest na "-"
  4. Dla formantów Testowych wpisywanie znaków ograniczone jest do cyfr i znaku separatora daty.
    Maksymalnie można wpisać 9 znaków.
    Data wprowadzana powinna być zgodnie z ustawieniami systemowymi, jakie ma data krótka, ale rok może zawierać od 1 do 4 znaków.
    Interpretacja jedno - i dwucyfrowego roku zgodna z ustawieniami systemowymi.
    Zablokowana jest obsługa wklejania tekstu - Ctrl+V
  5. Wszystkie formanty są polami związanymi, więc Access w wielu wypadkach wykonuje za nas sprawdzanie poprawności wprowadzonej daty, jednak czasami mechanizm Accessa zawodzi, zwłaszcza dla formantu bez maski wprowadzania.

W miarę możliwości w przykładzie zostały eliminowane wyżej opisane błędy wprowadzania daty, a zwłaszcza:

  • Zamianę dnia z miesiącem, gdy omyłkowo wprowadzimy wartość miesiąca większą niż 12 przy wcześniejszym wpisaniu wartości dnia mniejszego od 13.
  • Zamianę dnia z rokiem, gdy wpiszemy wartość dnia większą od możliwej dla danego miesiąca, a dwucyfrowy rok będzie miał prawidłową wartość dla danego miesiąca.
UWAGA:
  • Rozwiązanie to może zawierać błędy i przed zastosowaniem należy je gruntownie przetestować by uniknąć ewentualnych błędów!
separator
BraShortDate_2 wielkość: 208 KB. Status: free

Niezależny od ustawień systemowych wybór formatu daty oraz sprawdzenie poprawności wprowadzanej daty.

Jest to rozwinięcie tematu prezentowanego powyżej. W przykładzie tamtym jesteśmy uzależnieni od ustawień Regionalnych w Panelu Sterowania takich jak:

  • - znak separatora
  • - kolejność wyświetlania składników daty,
  • - czy jednocyfrowy dzień i miesiąc będzie poprzedzony zerem
  • - sposób interpretacji dwucyfrowego roku

Zwłaszcza sposób interpretacji dwucyfrowego roku ma istotne znaczenie, gdy przykładowo wprowadzamy daty z określonego zakresu np. od 1700 do 1799.
W takim przypadku po wprowadzeniu dwóch cyfr Access zinterpretuje je zgodnie z ustawieniami systemowymi, co może być niezgodne z intencjami wprowadzającego.
Przykładowy formularz zawiera dwa niezwiązane formanty, dla których w celach poglądowych ustawione następujące reguły:

  • Me.txtUrodz - reguła poprawności w tRejestr.[Urodz] >=#01-01-1950# And Not Is Null
    W formularzu: wymagane, osoba musi mieć minimum 15 lat, w przypadku korekcji daty zmieniana data musi być mniejsza niż Me.txtWypis (jeżeli jest wypełniony).
  • Me.txtWypis - data wypisania musi być większa od daty urodzenia i mniejsza lub równa od daty bieżącej.
  • zachowano obsługę klawiszy: Ctrl+: - bieżąca data, Ctrl+" - poprzedni rekord oraz klawisza ESC (w pewnym zakresie).
  • Zablokowana jest obsługa wklejania tekstu - Ctrl+V
UWAGA:
  • Rozwiązanie to może zawierać błędy i przed zastosowaniem należy je gruntownie przetestować by uniknąć ewentualnych błędów!