Wykorzystanie Menu w programie MSAccess 2003 #2.2

Wstęp

W poprzednim poście skupiłem się na pokazaniu jak zbudować menu bez panelu przełączania, tworząc ze środowiska Accessowego coś na styl MDI. Oczywiście to był tylko wstęp do dalszych rozważań na temat jak to wykorzystać dalej.
Ja najczęściej tworzę tabelę w której odwzorowuje strukturę menu, jak i zapisuje informacje niezbędne do wykonania odpowiedniej akcji po kliknięciu na danym elemencie.

Tworzenie konfiguracji

Dla przypomnienia, struktura przykładowa menu wygląda tak:

 menu1
      |- menu1 opcja1
      |- menu1 opcja2
menu2
      |- menu2 opcja1
      |- menu2 opcja2 

Zróbmy zatem jej odwzorowanie:
1. Stwórzmy tabele Menu o strukturze:

Nazwa Pola

Typ Danych

Opis

ID

Autonumerowanie

Klucz podstawowy
rodzic

Liczba

Identyfikator menu nadrzędnego, dla głównego poziomu wartość ustalamy na 0
nazwa

tekst

Nazwa wyświetlana w menu
akcja

Tekst

Akcja jaka ma się wykonać po kliknięciu
parametry

Tekst

Parametry do wykonania akcji

2. Wypełnijmy tabele danymi:

ID rodzic nazwa akcja parametry
1 0 menu1
2 1 menu1 opcja1 openForm UkryjOdkryj_Paski
3 1 menu1 opcja2 openForm Panel przełączania
4 0 menu2
5 4 menu2 opcja2 openTable Menu
6 4 menu2 opcja2 msg Treść komunikatu

Mając tak przygotowane dane możemy przystąpić do dalszej pracy.

Dynamiczne generowanie menu

W tym miejscu rozbuduje poprzedni przykład o pobranie danych z tabeli i wygenerowanie struktury, celowo pomijam funkcje już wykorzystane:

Public Sub CreateMenu()
    Dim cmdNewMenu As CommandBar
    Dim strMenuName As String
    Dim rootMenu As CommandBarControl
    Dim sql As String
    Dim rMenu As DAO.Recordset

    'usun menu jeśli istnieje
    strMenuName = "MenuAplikacji"
    If fIsCreated(strMenuName) Then
        Application.CommandBars(strMenuName).Delete
    End If
    
    'stwórz nowe menu
    Set cmdNewMenu = Application.CommandBars.Add(strMenuName, msoBarTop, True, False)
    With cmdNewMenu
        .Protection = msoBarNoProtection
        .Visible = True
    End With
    
    'pobierz dane do poziomu 1
    sql = "select id,nazwa from menu where rodzic = 0"
    Set rMenu = CurrentDb.OpenRecordset(sql)
    rMenu.MoveFirst
    Do Until rMenu.EOF
        Set rootMenu = cmdNewMenu.Controls.Add(msoControlPopup)
        rootMenu.Caption = rMenu!nazwa
        'dodaj podmenu
        CreateSubMenu rMenu!id, rootMenu
        rMenu.MoveNext
    Loop
    rMenu.Close
    Set rMenu = Nothing
    Set rootMenu = Nothing
    DodajMenuOkno cmdNewMenu
    Set cmdNewMenu = Nothing
End Sub
Public Sub CreateSubMenu(rodzic As Long, ByRef m As CommandBarControl)
    Dim subMenu As CommandBarControl
    Dim sql As String
    Dim rSubMenu As DAO.Recordset

    'pobierz dane dzieci
    sql = "select id,rodzic,nazwa from menu where rodzic = " & rodzic
    Set rSubMenu = CurrentDb.OpenRecordset(sql)
    rSubMenu.MoveFirst
    Do Until rSubMenu.EOF
        Set subMenu = m.Controls.Add(msoControlButton)
        With subMenu
            .Caption = rSubMenu!nazwa
            .OnAction = "=MnuClick(""" & rSubMenu!id & """)"
        End With

        rSubMenu.MoveNext
    Loop
    rSubMenu.Close
    Set rSubMenu = Nothing
    Set subMenu = Nothing
End Sub

Zasada działania jest następująca:
1. Uruchamiam procedurę CreateMenu
2. Usuwam istniejące menu
3. Tworzę na nowo
4. Pobieram dane najwyższego poziomu (rodzic = 0)
5. Tworzę kolejne pozycje
6. Dla każdej pozycji menu wywołuje funkcje CreateSubMenu, która generuje podmenu

W efekcie otrzymam w pełni funkcjonalne menu

Dodatkowe funkcjonalności

W linijce 35 wywołuje funkcje DodajMenuOkno, zadaniem tej funkcji jest przekopiowanie systemowego menu okno, tak aby dać użytkownikowi możliwość sprawnego nawigowania pomiędzy otwartymi formularzami:

Public Sub DodajMenuOkno(ByRef cb As CommandBar)
    Dim iMB As Integer
    Dim iGW As Integer
    Dim cmenubar As CommandBar
    Dim cwindow As CommandBarControl
    iMB = -1
    iGW = -1
    For Each cmenubar In Application.CommandBars
        If cmenubar.Name = "Menu Bar" Then
            iMB = cmenubar.Index
            Exit For
        End If
    Next
    If iMB <> -1 Then
        For Each cwindow In Application.CommandBars(iMB).Controls
            If cwindow.OLEMenuGroup = msoOLEMenuGroupWindow Then
                iGW = cwindow.Index
                Exit For
            End If
        Next
    End If
    If iGW <> -1 Then Application.CommandBars(iMB).Controls(iGW).Copy cb
End Sub

Działanie:
1. Szukam indeksu dla menu “menu bar”
2. Szukam na nim indeksu menu “okno”
3. Kopiuje do utworzonego menu

Obsługa kliknięć

Jak widać funkcja generująca podmenu (CreateSubMenu) dodaje do zdarzenia odwołanie do funkcji MnuClick.
To główna funkcja odpowiedzialna za całość działania nawigacji.
Jak wynika z danych w tabeli menu możemy rozróżnić 3 akcje:
1.openform – otwarcie formularza
2.openTable – otwarcie tabeli
3.msg – wyświetlenie komunikatu

Dane niezbędne do wykonania tych czynności są w kolumnie parametry i tak np. dla menu o id 3 otworzy się formularz: Panel przełączania
Obsługa w kodzie VBA:

Public Function MnuClick(ByVal id As Long)
    Dim sql As String
    Dim rAkcja As DAO.Recordset

    'pobierz dane o akcji menu
    sql = "select akcja,parametry from menu where id=" & id
    Set rAkcja = CurrentDb.OpenRecordset(sql)
    rAkcja.MoveFirst
    Select Case rAkcja!akcja
        Case "openForm"
            DoCmd.OpenForm rAkcja!parametry
        Case "openTable"
            DoCmd.OpenTable rAkcja!parametry, acViewNormal
        Case "msg"
            MsgBox rAkcja!parametry
    End Select
    rAkcja.Close
    Set rAkcja = Nothing

End Function

Działanie to nic innego jak pobranie danych z tabeli menu i wykonanie zdefiniowanej akcji.

Podsumowanie

Na tym zakończę opis pisania nawigacji w Acc2003, myślę, że to każdemu da pogląd jak to można rozwinąć i wykorzystać. Moim zdaniem najważniejsze zalety to:
1. Jedna funkcja generująca menu
2. Konfiguracja na poziomie tabeli
3. Jedna funkcja odpowiedzialna za działanie nawigacji
4. Ułatwiona nawigacja pomiędzy otwartymi formularzami (menu Okno)

Dla zainteresowanych link do przykładowej bazy.

Uwaga! Aby kod zadziałal musi być dodana referncja do Microsoft Office 11 Library

Leave a Comment

NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

WordPress SEO fine-tune by Meta SEO Pack from Poradnik Webmastera
Skip to toolbar