Wykład 10

Język aplikacji baz danych – Visual Basic

 

Streszczenie

W wykładzie 10 rozpoczyna się nauka programowania aplikacji bazodanowych. Zostają wprowadzone podstawowe pojęcia takie jak procedura, moduł, moduł klasy, zdarzenie i obsługa błędów. Obiekty graficznego interfejsu użytkownika stają się obiektami języka programowania, które mają swoje właściwości w tym metody. Pokazane jest użycie edytora kodu i nawigatorów po dostępnych klasach obiektów. Pokazane jest jak synchronizować ze sobą wyświetlane formularze. Przedstawiona jest lista najważniejszych zdarzeń, które są oprogramowywane przy tworzeniu aplikacji bazodanowej.
 


Procedury

Procedury są podstawą programowania aplikacji bazodanowych MS Access w ramach paradygmatu programowania zdarzeniowego. Oto ich cechy:

Na przykład, na formularzu można umieścić zbiór przycisków, po których naciśnięciu użytkownik uzyskuje:


Visual Basic for Applications
(w skrócie VBA) jest językiem programowania dla aplikacji systemu Microsoft Office będący podzbiorem języka Visual Basic. Oto jego cechy:

Moduł jest zbiorem deklaracji i definicji procedur języka VBA przechowywanych razem jako całość.

Typy zmiennych:

Typy danych dla zmiennych

Access Visual Basic Wartość domyślna
Text String ""
Number Integer, Long, Double, Single 0
Currency Currency 0
Yes/No Boolean False
Date/Time Date 30.12.1899

Specjalny typ danych Visual Basic - Variant - oznacza dowolny typ wartości.

Domyślnie wszystkie argumenty przy wywoływaniu procedury są przekazywane metodą przez referencję. Dzięki temu w kodzie procedury operujemy na rzeczywistej zmiennej, którą przekazujemy jako parametr. 
Alternatywnie można przekazywać argument przy wywoływaniu procedury metodą przez wartość – poprzedzając w deklaracji procedury nazwę parametru słowem kluczowym ByVal. Przy wywołaniu oblicza się wartość argumentu i przekazuje do kodu procedury właśnie tę wartość. Jeśli argumentem jest zmienna, wartość tej zmiennej nie ulega zmianie przy wykonywaniu kodu.

Naukę programowania aplikacji bazodanowej będziemy prowadzić na przykładach.

Przykład 1

Typowym zadaniem programistycznym jest obliczanie pierwiastka kwadratowego z liczby nieujemnej. Oto jego zapis w postaci funkcji Visual Basic.

Function SquareRoot (X As Double) As Double
 Dim Msg As String
 Select Case Sgn(X) ' Oblicz znak argumentu.
     Case 1 ' OK jeśli dodatni.
            SquareRoot = Sqr(X) 
            Exit Function
     Case 0 ' Powiadom użytkownika jeśli 0.
            Msg = "Przekazana wartość to 0."
     Case -1 ' Powiadom użytkownika jeśli mniejsze niz 0.
            Msg = "Niedozwolona liczba."
  End Select
  MsgBox Msg ' Wyświetl komunikat Msg
End Function

W przypadku wywołania funkcji, gdy nie nastąpi przypisanie wartości do nazwy funkcji SquareRoot, system przypisze wartość 0.

Teraz zadanie do rozwiązania dla czytelnika:

Napisz procedurę rozwiązującą równanie kwadratowe o współczynnikach rzeczywistych. Uruchom tę procedurę w MS Access.

Przykład 2

Pokażemy na tym przykładzie deklaracje i definicje modułu. Opcje:

są zwykle domyślnie przyjmowane przez system.

Option Compare Database
Option Explicit
-------
Private licznik As Integer  'Zmienna lokalna
Public pokaż As Integer 'Zmienna globalna
--------
Sub Zeruj() 'Procedura globalna
   licznik = 0
   pokaż = licznik
End Sub
-------
Sub Dodaj() 'Procedura globalna
   licznik = licznik + 1
   pokaż = licznik
   MsgBox licznik, , "LICZNIK"
End Sub


W MS Access jest dost
ęny edytor kodu Visual Basic (Visual Basic Editor) – zawierający środowisko uruchamiania kodu VBA.

? licznik

gdzie licznik jest zmienną, której wartość chcemy wypisać.

Na ogół jednej klasie odpowiada dokładnie jeden obiekt tej klasy (obiekt klasy – class object).

Przykład 3

Sprawdzanie, czy dany formularz jest otwarty w widoku Formularz - rozwiązanie używające standardowej funkcji SysCmd.

Function Otwarty(ByVal Mój As String) As Integer
' SysCmd - czy formularz jest otwarty
   Otwarty = False
   If SysCmd(acSysCmdGetObjectState,acForm,Mój) <> 0 Then
   ' CurrentView - czy jest otwarty w widoku Formularz
      If Forms(Mój).CurrentView <> 0 Then Otwarty = True
   End If
End Function

Zwróćmy uwagę na to, że odróżniamy klasę danego formularza łącznie z arkuszem jego właściwości od konkretnych jego wcieleń widocznych na ekranie, na których możemy wykonywać operacje w kodzie VBA. Wcielenie to nazywamy obiektem danego formularza lub w skrócie po prostu formularzem. Możemy więc powiedzieć, że otwarte formularze są obiektami klas swoich formularzy. Do obiektu formularza o nazwie Pracownicy można się odwoływać w następujący sposób:

Używając dostępu kropkowego możemy odwoływać się do właściwości obiektu formularza a także do jego metod np.

Wykrzyknik ! oznacza wybór elementu z kolekcji. Np.

Reasumując:

Zapis Forms![Pracownicy]![Nazwisko] oznacza także domyślnie wartość pola tekstowego Nazwisko czyli konkretne nazwisko – alternatywnie można używać pełnej notacji:

Forms![Pracownicy]![Nazwisko].Value

Przy wpisywaniu do pola tekstowego lub listowego, bieżącą wartość – jeszcze nie zapisaną do bazy danych – uzyskuje się przy użyciu:

Forms![Pracownicy]![Nazwisko].Text

Przy odczytywaniu wartości atrybutu Text fokus (bieżący kursor) musi znajdować się na danym polu:

[Nazwisko].SetFocus
MsgBox "Nazwisko = "&[Nazwisko].Text

Sprawdzenie czy formularz jest otwarty (w widoku Projekt lub Formularz)  można zrealizować jeszcze w inny sposób – przeglądając kolekcję wszystkich otwartych formularzy i sprawdzając ich nazwy.

 
Function Otwarty1 (ByVal Mój As String) As Integer
' Zwraca True, jeśli podany formularz jest otwarty w widoku projekt lub formularz.
   Dim I As Integer
   Otwarty1 = False
   ' Forms.Count to liczba obiektów w kolekcji Forms
   For I = 0 To Forms.Count - 1
     If Forms(I).Name = Mój Then
              Otwarty1 = True
        Exit For
     End If
   Next I
End Function

Jest możliwość tworzenia instancji klasy formularza w kodzie VBA:

      Dim Kopia As New Form_Osoby

i wykonywanie na niej operacji jak na obiekcie. Instancja ta nie jest widoczna na ekranie.

Przykład 4

Kolejna procedura specyfikuje reakcję na zdarzenie naciśnięcia lewego przycisku myszy (obiekt: przycisk Witaj, zdarzenie: Przy kliknięciu).

Private Sub Witaj_Click()
   [Pole] = "Witaj w klubie VBA"
End Sub

Przykład 5

Zwróćmy uwagę na procedurę, jaką tworzy kreator przycisków w celu zrealizowania zadania otwarcia formularza o nazwie Osoby:

Private Sub Przycisk_Click()
   On Error GoTo Err_Przycisk_Click
   Dim stDocName As String
   Dim stLinkCriteria As String
   stDocName = "Osoby"
   DoCmd.OpenForm stDocName, , , stLinkCriteria
  Exit_Przycisk_Click:
   Exit Sub
  Err_Przycisk_Click:

   MsgBox Err.Description
   Resume Exit_Przycisk_Click
End Sub

W powyższej procedurze można byłoby standardowy tekst błędu Err.Description zastąpić własnym tekstem skierowanym do użytkownika aplikacji:

MsgBox "Błąd aplikacji. Skontaktuj się z administratorem aplikacji"

Teraz zadanie do rozwiązania dla czytelnika:

Korzystając z obsługi błędów napisz funkcję spawdzającą czy formularz o nazwie będącej argumentem procedury jest otwarty (w widoku Projekt lub Formularz).

Synchronizacja dwóch formularzy

Przykład 6

Otwarcie formularza może być bardziej skomplikowane, aby mogło wystarczyć użycie samego kreatora przycisków np. procedura otwierająca formularz Uczestnictwo w projektach w oparciu o wartość znajdującą się w polu Numer będącym częścią podformularza przy czym sam przycisk Projekty znajduje się w głównym formularzu Departament.

Procedura otwiera formularz Uczestnictwo w projektach w celu pokazania uczestnictwa w projektach wybranej aktualnie osoby (w podformularzu):

Private Sub Projekty_Click()
   On Error GoTo Err_Projekty_Click
   Dim stDocName As String
   Dim stLinkCriteria As String
   stDocName = "Uczestnictwo w projektach"
   stLinkCriteria = "Numer=Forms![Departament]![Osoba Subform].Form![Numer]"

   DoCmd.OpenForm stDocName, , , stLinkCriteria
   Forms![Departament].SetFocus
   Forms![Departament]![Osoba Subform].SetFocus

Exit_Projekty_Click:
   Exit Sub
Err_Projekty_Click:
   MsgBox Err.Description
   Resume Exit_Projekty_Click
End Sub

Przykład 7 

Formularz Uczestnictwo w projektach powinien pokazywać dane o aktualnie rozpatrywanym pracowniku z podformularza w formularzu Departament. Uaktualnienie wartości następuje przy pojawieniu się nowego rekordu w podformularzu czyli jako reakcja na zdarzenie Przy bieżącym. Przy czym to uaktualnienie ma sens, tylko wtedy gdy użytkownik wcześniej otworzył formularz Uczestnictwo w projektach naciskając przycisk Projekty. Z kolei naciśnięcie przycisku Projekty ma sens tylko wtedy, gdy pole Numer w podformularzu jest niepuste.

W poniższej procedurze występują dwie nowe właściwości, których wartościami są obiekty:

Private Sub Form_Current()
   On Error GoTo Err_Form_Current

   If IsNull(Me![Numer]) Then
      Me.Parent![Projekty].Enabled = False
   Else
      Me.Parent![Projekty].Enabled = True
      If Otwarty("Uczestnictwo w projektach") Then
          Dim Projekt As String
          Projekt = "[Numer]="& Me![Numer]
          DoCmd.OpenForm "Uczestnictwo w projektach", , , Projekt
          Forms![Departament].SetFocus
          Forms![Departament]![Osoba Subform].SetFocus
      End If
   End If
Exit_Form_Current:
   Exit Sub
Err_Form_Current:
   MsgBox Err.Description
   Resume Exit_Form_Current
End Sub

Uaktualnienie formularza Uczestnictwo w projektach jest konieczne nie tylko wtedy, gdy fokus w podformularzu przejdzie do nowego rekordu, ale również gdy w bieżącym rekordzie zmieni się wartość pola Numer. Realizuje to procedura zdarzenia Po aktualizacji dla pola Numer - jej kod jest analogiczny do procedury zdarzenia Przy bieżącym.

Teraz zadanie do rozwiązania dla czytelnika:

Utwórz dwie tabele Instytucje i Pracownicy połączone związkiem jeden do wiele. Każda instytucja zatrudnia wielu pracowników; każdy pracownik jest zatrudniony w jednej instytucji. Utwórz dwa formularze: „Instytucja”, na którym są wyświetlane dane o instytucjach, oraz „Pracownicy” na którym są wyświetlane dane o pracownikach. Chcemy, aby na życzenie użytkownika poprzez naciśnięcie przycisku „Pracownicy instytucji” na formularzu „Instytucja” otwierał się formularz wyświetlający pracowników danej instytucji. Chcemy aby przy chodzeniu po rekordach formularza „Instytucja” aktualizowały się dane o pracownikach zatrudnionych w danej instytucji – oczywiście o ile wcześniej użytkownik otworzył stowarzyszony formularz „Pracownicy”. Jakie zdarzenia należy oprogramować i jaka jest ich treść?

I jeszcze jedno zadanie do rozwiązania dla czytelnika:

Czy Twoje rozwiązanie umożliwia wprowadzanie pracowników do otwieranego z formularza Instytucje formularza Pracownicy? Jakie zdarzenia dla formularza Pracownicy należy oprogramować i jaka jest ich treść?

Zdarzenia

Rozważymy kolejno zdarzenia dla obiektów interfejsu użytkownika (formularzy, raportów, elementów dialogowych) - które najczęściej są oprogramowywane przy pomocy procedur zdarzeń.

Private Sub Form_Open(Cancel As Integer)
   Dim strPass as String
   strPass = InputBox("Podaj hasło: ")
   If strPass<>"KochamVB" Then
      MsgBox "Niepoprawne
hasło"
      Cancel = True
   End If
End Sub

 

Private Sub Form_Load()
   Dim StrName As String
   MsgBox "Formularz za chwilę pojawi się na ekranie!"
End Sub

 

Private Sub Form_Current()
   Forms!Pracownik.Caption = Me![Nazwisko]
End Sub

 

Private Sub Form_Delete(Cancel As Integer)
   If MsgBox("Czy na pewno usunąć?", vbYesNo) = vbNo Then Cancel = True
End Sub

 

Private Sub cmdClickMe_Click()
   MsgBox "Czego chcesz ode mnie?"
End Sub

 
Private Sub Nazwisko_GotFocus()
   [lblNazwisko].Caption = "Rozpatrywany w tej chwili klient"
End Sub

 

Private Sub txtPass_Exit(Cancel As Integer)
     If Len(txtPass) < 8 Then
        MsgBox "Podaj 8 lub więcej znaków."
        Cancel = True
   End If
End Sub

- bez wstrzymywania wyjścia:

Private Sub txtPass_LostFocus()
   If Len(txtPass) < 8 Then
     MsgBox "Podaj 8 lub więcej znaków."
   End If
End Sub

Teraz zadanie do rozwiązania dla czytelnika:

W tym ćwiczeniu przetestujesz działanie procedur zdarzeń. Zdefiniuj tabelę o dwóch kolumnach: id typu Autonumber (klucz główny) oraz liczba typu Integer. Zbuduj formularz oparty na tej tabeli. Oprogramuj wszystkie zdarzenia tego formularza wpisując jako treść procedury zdarzenia instrukcję MsgBox z argumentem będącym nazwą zdarzenia. Przetestuj korzystanie z formularza (otwieranie, wprowadzanie danych, aktualizację danych, usuwanie danych, przechodzenie po rekordach, zamykanie). Rozpocznij od zdarzeń omówionych na wykładzie. Przetestuj działanie formularza. Potem wprowadzaj procedurę zdarzenia kolejnego zdarzenia testując jego zachowanie. Czy pojawiające się na ekranie napisy o zachodzących zdarzeniach są zgodne z Twoimi oczekiwaniami?

Funkcja DLookUp

Funkcja DLookUp umożliwia sprowadzenie z bazy danych pojedynczej wartości. Np.

=DLookUp("[Nazwa]";"[Departament]";"[Id]=Forms![Osoba]![Id]")

Ten sam efekt można byłoby uzyskać opierając formularz na kwerendzie złączającej zamiast na tabeli.

Za pomocą funkcji DLookUp można do pola formularza wprowadzać wartości obliczane przez kwerendę wybierającą - wystarczy najpierw zdefiniować taką kwerendę np. Zap_max  jako

SELECT IIf(IsNull(Max([Numer])),1,Max([Numer])+1) AS Maks FROM Osoba;

a następnie użyć kwerendy jako źródła dla pola na formularzu:

=DLookUp("[Maks]"; "Zap_max")

Metodę tę można zastosować więc do generowania jednoznacznych numerów dla kluczy.


Podsumowanie

W wykładzie zostały wprowadzone podstawowe pojęcia programowania aplikacji bazodanowych takie jak procedura, moduł, zdarzenie i obsługa błędów. Obiekty graficznego interfejsu użytkownika to obiekty języka programowania, które mają swoje właściwości w tym metody. Czytelnik nauczył się posługiwać edytorem kodu VBA i programować procedury zdarzeń.
 


Słownik

procedura - podstawowa jednostka kodu języka programowania Visual Basic for Applications (VBA). Są dwa rodzaje procedur: podprogramy (Sub) i funkcje (Function).
moduł - zbiór deklaracji i definicji procedur języka VBA przechowywanych razem jako całość. Są dwa rodzaje modułów: moduły klas obiektów i moduły ogólne.
zdarzenie - sytuacja jaka może wystąpić w trakcie realizacji aplikacji, dla której programista może przygotować specjalną obsługę np. w postaci  procedury zdarzenia.
DLookUp - funkcja DLookUp umożliwia sprowadzenie z bazy danych pojedynczej wartości lub wykonanie zapytania zwracającego pojedynczą wartość.
 


Zadania 1,2,3,4



Strona przygotowana przez Lecha Banachowskiego - 10/25/03 .