Access

  MS Access 2010+  |  Formularze  |   VBA 7.0



• Jak uatrakcyjnić otwieranie formularza ?

Wiemy już, że formularze są podstawowymi obiektami MS Access. Za ich pomocą możemy prezentować zgromadzone w bazie danych informacje, edytować dane, dodawać nowe oraz usuwać istniejące dane. Skoro jest to najważniejszy obiekt interfejsu bazy danych powinniśmy zadbać o jego wygląd i funkcjonalność. Na stronie O formularzu poznaliśmy dwie właściwości formularza. Pierwsza to właściwość AutoCenter, która zapewnia wyśrodkowanie otwartego formularza w dostępnym obszarze okna aplikacji, druga właściwość to AutoResize, która zmienia  wymiary okna formularza tak, by widoczne były całe rekordy, bez zasłaniania części formantów zawierających dane przez dolne obramowanie formularza, bądź górną krawędź sekcji  stopka formularza.

Właściwość WindowHeight formularza (raportu).

Właściwość WindowHeight jest wartością typu Liczba całkowita i jest tylko do odczytu. Zwraca wysokość formularza (raportu) wyrażoną w twipach. Jest mierzona od lewego górnego do lewego dolnego rogu formularza (raportu). Właściwość WindowHeight dostępna jest jedynie w makrze lub języku Visual Basic.

Właściwość WindowWidth formularza (raportu).

Właściwość WindowWidth jest wartością typu Liczba całkowita i jest tylko do odczytu. Zwraca szerokość formularza (raportu) wyrażoną w twipach. Jest mierzona od lewego górnego do prawego górnego rogu formularza (raportu). Właściwość WindowWidth dostępna jest jedynie w makrze lub języku Visual Basic.

Właściwość WindowLeft formularza (raportu).

Właściwość WindowLeft jest wartością typu Liczba całkowita i jest tylko do odczytu. Zwraca odległość lewego górnego rogu formularza (raportu) od lewej krawędzi roboczego obszaru okna aplikacji MS Access. Jeżeli widoczne jest „okienko nawigacji”, to właściwość WindowLeft określa odległość od prawej krawędzi „okienko nawigacji”. Właściwość WindowLeft dostępna jest jedynie w makrze lub języku Visual Basic.

Właściwość WindowTop formularza (raportu).

Właściwość WindowTop jest wartością typu Liczba całkowita i jest tylko do odczytu. Zwraca odległość lewego górnego rogu formularza (raportu) od górnej krawędzi roboczego obszaru okna aplikacji MS Access, najczęściej jest to dolne obramowanie Wstążki (Ribbon). Gdy formularz jest zmaksymalizowany, zwracana wartość właściwości WindowWidth jest liczbą ujemną równą (u mnie) -372 twipów tj. ok. 31 pikseli, czyli tyle ile ma wysokości pasek tytułowy formularza (raportu), który przy takim ustawieniu jest ukryty. Właściwość WindowTop dostępna jest jedynie w makrze lub języku Visual Basic.

Zmiana rozmiaru i położenia okna formularza

Poznaliśmy podstawowe właściwości formularza za pomocą których możemy pobrać aktualne położenie i rozmiar okna formularza oraz metody AutoCenterAutoResize za pomocą których możemy wycentrować formularz względem dostępnego miejsca w oknie aplikacji oraz wymusić, by formularz miał wysokość tak dobraną, by pokazywał pełne rekordy. Aby zmienić położenie i (lub) rozmiar okna formularza , które musi być oknem aktywnym, możemy użyć poznanej już metody obiektu DoCmd MoveSize.

Przykładowe otwarcie formularza w kierunku od lewego do prawego obramowania.

Formularz do lewej

Od lewego boku do prawego formularza

Spróbujmy otworzyć formularz tak by jego wysokość była stała, a szerokość zwiększała się stopniowo, aż do osiągnięcia docelowej szerokości. Najlepiej jest zmieniać szerokość formularza w procedurze zdarzenia Load formularza.

Private Sub Form_Load()
Dim lWidth      As Long
Dim lWidthTmp   As Long
Dim i           As Long
Const conSpeed  As Long = 250

  ' pobierz docelową szerokość formularza
  lWidth = Me.WindowWidth
  
  For i = 1 To conSpeed
    ' oblicz tymczasową szerokość formularza
    lWidthTmp = lWidth * (i / conSpeed)
    ' zmieniaj tylko szerokość formularza
    DoCmd.MoveSize Me.WindowLeft, Me.WindowTop, lWidthTmp, Me.WindowHeight
  Next

End Sub

Niestety, ten kod nie działa, a raczej działa, ale nie widać efektów. Po prostu formularz nie jest jeszcze widoczny. MS Access pokaże go nam, gdy wykona potrzebne operacje wymagane podczas otwarcia (załadowania). My możemy go pokazać ustawiając na samym początku właściwość formularza  Me.Visible na wartość TRUE 
Po poprawce widać jak formularz stopniowo zwiększa swoją szerokość, ale formanty formularza nie są widoczne. Widoczne jest jedynie tło formularza o bliżej nieokreślonym kolorze. Pełna zawartość formularza staje się widoczna po wykonaniu się całego kodu (pętli For Next).

Spróbujmy w każdym cyklu pętli For Next, za pomocą funkcji DoEvents przekazać sterowanie do systemu operacyjnego, by obsłużył wszystkie zdarzenia z systemowej kolejki. Teraz jest, a w zasadzie prawie jest dobrze. Ładnie widać zawartość formularza wraz ze stopniowym zwiększaniem jego szerokość.


  '....
  ' pokaż formularz
  Me.Visible = True
  
  For i = 1 To conSpeed
    ' oblicz tymczasową szerokość formularza
    lWidthTmp = lWidth * (i / conSpeed)
    ' zmieniaj tylko szerokość formularza
    DoCmd.MoveSize Me.WindowLeft, Me.WindowTop, lWidthTmp, Me.WindowHeight
    '  pozwól na obsłużenie zdarzeń z systemowej kolejki
    DoEvents
  Next
 
End Sub

No i nagle ZONK!. W tym konkretnym przypadku, przy wykonywaniu 137 operacji (z 250 operacji) MS Access 2007 komunikuje, że wystąpił „Błąd dzielenia przez ZERO

Błąd dzielenia przez zero

Błąd dzielenia przez ZERO

Jedynym dzielnikiem w podświetlonej linijce kodu jest stała Const conSpeed As Long = 250
Aktualne wartości zmiennych i stałych możemy sprawdzić w „Okienku Watches”. Nie wiem dlaczego Access 2007 tak dziwnie się zachowuje. Ta sama przykładowa baza otwarta w MS Access 2010 i 2016 nie sprawia żadnych kłopotów. Formularz wyświetla się prawidłowo. Aby się upewnić na 100% utworzyłem nową bazę w programie MS Access 2007 i do nowego formularza wkleiłem przedstawiony powyżej kod. Występuje ten sam „Błąd dzielenia przez ZERO”.

Rozwiązanie tego problemu jest proste, w przeciwieństwie do przedstawienia powodów występowania tego błędu. Wystarczy funkcję DoEvents przeniść linijkę wyżej, przed wywołanie metody DoCmd.MoveSize. Dopisanie funkcji DoEvents w tym miejscu, bez jej usuwania z końca kodu nic nie daje. Funkcja DoEvents nie może w MS Access 2007 występować bezpośrednio za wywołaniem metody DoCmd.MoveSize.
Ewentualnie można zmniejszyć wartość stałej conSpeed do 62 (w tym konkretnym przypadku), ale nie jest to jakakolwiek metoda łatania dziur.

Migotanie okna formularza.

Niestety, podczas otwarcia (ładowania) formularza, przy ustawionej właściwości   Me.Visible = TRUE  występuje nieprzyjemne mrugnięcie okna formularza. Pojawia się na ułamek sekundy zarys (obramowanie) całego formularza.

Formularz - migotanie okna

Zrzut ekranowy. Widoczny zarys całego
formularza i jego pomniejszone okno

Użycie metody Application.Echo = False w celu zablokowania odświeżania ekranu, niestety nie daje efektu. Prowizorycznym rozwiązaniem będzie przeniesienie instrukcji Me.Visible = TRUE  na początek pętli For Next i wywołanie jej np. w 5 cyklu pętli.
If i = 5 Then Me.Visible = True. Praktycznie przez pierwsze kilkanaście, a nawet kilkadziesiąt cykli, formularz nie zmienia szerokości, gdyż jego szerokość nie przekracza minimalnej systemowej szerokości (ok. 1692 twipów).

Jeszcze jednym mankamentem przedstawionego przykładu, zwłaszcza dla dużych wartości licznika pętli For Next jest niebezpieczeństo, że użytkownik w trakcie długiego otwierania formularza, kliknie inny obiekt (przeniesie na niego fokus), to aktywnym oknem stanie się okno tego obiektu i dalsza zmiana rozmiaru i położenia będzie wykonywana na tym właśnie oknie. By się ratować przed taką sytuacją, na końcu pętli wywołamy metodę:
DoCmd.SelectObject acForm, Me.Name, False
Sposób ten jedynie ograniczy możliwość wystąpienia tego przypadku. Dla upartego użytkownika nie będzie to przeszkodą. Dwukrotne kliknięcie na pasek tytułowy innego okna spowoduje zmaksymalizowanie nie tylko klikniętego obiektu, ale również naszego formularza i argumenty RightDown metody DoCmd.MoveSize będą miały nieprawidłową (ujemną) wartość. Podobnie będzie, gdy inny obiekt jest zmaksymalizowany i nastąpi otwarcie naszego formularza.

Formularz -zmaksymalizowany

Ujemne wartośći WindowLeft i WindowTop

Błąd ten (o numerze 2505) spowodowany jest bezpośrednim przekazaniem, jako argumentów metody DoCmd.MoveSize, właściwości Me.WindowLeft, Me.WindowTop, ... , Me.WindowHeight, które są odczytywane w każdym cyklu pętli For Next. Dla zmaksymalizowanego formularz właściwość Me.WindowLeft = -72, a Me.WindowTop = -372. Przekazane ujemnej wartości w argumencie metody DoCmd.MoveSize powoduje wystąpienie błędu o numerze 2505 „Wyrażenie w argumencie 2 ma nieprawidłową wartość”.
Jak widać krótszy kod nie jest wcale lepszy od trochę dłuższego i korzystającego z większej ilości zmiennych.

  • Piersza poprawka do kodu polega na pobraniu położenia (właściwości Me.WindowLeft, Me.WindowTop) i wymiarów (Me.WindowWidth, Me.WindowHeight) formularza na samym początku procedury i przypisania ich do zmiennych. W ten sposób mamy rozwiązany problem zmaksymalizowanego okna oraz maksymalizowanie okna podczas wykonywania kodu. Skoro użytkownik maksymalizuje okna, to niech ma w tym stanie otwierany formularz.
    Uwaga. Zmaksymalizowanie okna nie wstrzymuje działania kodu, jest on wykonywany, ale nie wpływa na zmianę położenia i rozmiaru formularza.
  • Drugą poprawką do przedstawionego kodu jest zrezygnowanie z właściwości Me.Visible = True na rzecz metody DoCmd.SelectObject acForm, Me.Name, False, której wywoływanie w każdym cyklu pętli For Next spowoduje odkrycie okna formularza i w dużum stopniu zabezpieczy przed zaksymalizowaniem innego okiektu, w wyniku którego zostanie zmaksymalizowany nasz formularza.
  • Trzecią poprawką będzie zabezpieczenie się przed błędem „Błąd dzielenia przez ZERO” występującego w MS Access 2007 gdy funkcja DoEvents jest uruchamiana bezpośrednio po wywołaniu metody DoCmd.MoveSize. Funkcję DoEvents trzeba przenieść przed metodę DoCmd.SelectObject. Można dodatkowo wywołać funkcję DoEvents na samym końcu procedury, poza pętlą For Next.
Private Sub Form_Load()

Dim lLeft       As Long
Dim lTop        As Long
Dim lWidth      As Long
Dim lHeight     As Long
Dim lWidthTmp   As Long
Dim i           As Long
Const conSpeed  As Long = 250

  ' pobierz położenie i rozmiar formularza
  lLeft = Me.WindowLeft     ' można wpisać własną wartość
  lTop = Me.WindowTop       ' można wpisać własną wartość
  lWidth = Me.WindowWidth   ' można wpisać własną szerokość
  lHeight = Me.WindowHeight ' można wpisać własną wysokość

  For i = 1 To conSpeed
    ' oblicz tymczasową szerokość formularza
    lWidthTmp = lWidth * (i / conSpeed)
 
    ' zmieniaj tylko szerokość formularza
    DoCmd.MoveSize lLeft, lTop, lWidthTmp, lHeight
    DoEvents
    ' ustawiaj fokus na otwieranym formularzu
    DoCmd.SelectObject acForm, Me.Name, False
  Next
  
  DoEvents

End Sub

Uwagi.
Możemy także w trakcie otwierania formularza w pętli For Next wywoływać metodę Docmd.Restore, która spowoduje przywrócenie rozmiaru formularza. Niestety, towarzyszy temu nieprzyjemne migotanie okna formularza.

Opcje dokumenty kartotekowe

Opcje okna dokumenty

Gdy formularz jest zmaksymalizowany lub gdy domyślnym widokiem „okna dokumentu” bieżącej bazy danych są „dokumenty kartotekowe” kod jest wykonywany, ale nie wpływa na zmianę położenia i rozmiaru formularza.

Słownik użytych terminów.



• sekcja
Część formularza lub raportu, na przykład nagłówek, stopka lub sekcja szczegółów
• stopka formularza
Stopka formularza wyświetlana jest w dolnej części okna formularza i na końcu wydruku. Nie pojawiają się one w widoku „Arkusz danych”. W formularzu wielorekordowym, w sekcji stopki nie można przewijać formantów, więc są one widoczne na ekranie przez cały czas. Często używa się stopki formularza do wyświetlania instrukcji dotyczące korzystania z formularza, przycisków poleceń lub niezwiązane formanty do akceptacji danych wejściowych.
• Liczba całkowita (Integer), typ danych
Podstawowy typ danych służący do przechowywania liczb całkowitych. Zmienna typu Integer jest przechowywana jako liczba 16-bitowa (2-bajtowa) z przedziału od -32 768 do 32 767. Znakiem deklaracji typu jest % (znak ANSI numer 37).
• formularz
Obiekt bazy danych programu Microsoft Access, w którym umieszcza się formanty służące do wykonywania akcji albo do wprowadzania, wyświetlania i edycji danych w polach.
• raport
Obiekt bazy danych programu Microsoft Access, który umożliwia oglądanie informacji sformatowanej i zorganizowanej zgodnie z wymaganiami użytkownika. Przykładami raportów są zestawienia cen, listy numerów telefonów czy etykiety adresowe.
• twip
W programie Microsoft Access jednostka miary równa 1/120 punktu albo 1/1440 cala. Na jeden centymetr przypada 567 twipów.
• makro
Akcja (lub zestaw akcji) wykonywanych krok po kroku, którą tworzy się za pomocą dostępnego w Accessie edytora makr („Okno projektu makra”).
• pasek tytułowy
Pasek u góry okna, w którym jest wyświetlana nazwa okna.
• wstążka (Ribbon
Pasek narzędzi, a począwszy od wersji MS Access 2007 wstążka (Ribbon) zawierający zestaw przycisków, menu lub inne formanty, które można kliknąć, aby wykonać często używane polecenia menu. Można wyróżnić następujące typy pasków narzędzi: pasek menu, pasek narzędzi, menu podręczne (menu podręczne, menu rozwijane, podmenu).
• okno nawigacji
Dawniej okno bazy danych. Począwszy od wersji MS Access 2007 zastąpione zostało okienkiem nawigacji Okno, które pojawia się po otwarciu bazy danych programu Microsoft Access 2007+ z lewej strony okna roboczego Microsoft Access. Zawiera Tabele, Kwerendy, Formularze, Raporty, Makra i Moduły.