Использование динамических меню в Access.
Наверняка все знакомы с ситуацией, когда в современных приложениях вид меню меняется в зависимости от, например прав доступа зарегистрировавшегося пользователя, контекста или другой ситуации. Меню в Access можно создавать по старинке на основе макросов или как своя панель инструментов. Далее будем предполагать, что меню создана на основе панели инструментов. Если у Вас меню создано на основе макросов, настоятельно рекомендую переделать. Вы получите ряд возможностей. Такое меню можно перетаскивать мышью в любую часть экрана, для пунктов меню вставлять button image, динамически управлять пунктами меню - гасить или вообще удалять конкретные пункты из программного кода. Что бы использовать возможности по управлению меню подключите библиотеку Microsoft Office 8.0 Object Library в Tools > References. Или 9.0 если установлен Office 2000. В этой библиотеке есть объекты: CommandBar - панель инструментов, CommandBarControl - элемент панели инструментов, может быть или подменю или командой. Соответственно CommandBars - семейство всех панелей инструментов, Controls - позволяет как бы перейти в подменю объекта CommandBarControl. Ниже приведенная функция работает с трехуровневым меню. Координаты конкретного пункта задаются (i, j, k), где i - номер пункта в основном меню, нумерация начинается с единицы, j - в подменю, k - в подменю этого меню. В зависимости от Par = true - включает пункт меню, false - выключает пункт меню. EnVis = true - пункт меню при выключении становится не активным, false - вообще исчезает. Соответственно если какая то ветка имеет только два уровня, то значение k = 0, если один уровень, то j = 0 и k = 0.
Public Function SetMenuUserSecurity(i As Long, j As Long, K As Long, Par As Boolean, EnVis As Boolean)
'устанавливает/гасит (Par) меню с координатами (i,j,k) EnVis - True - Enabled False - Visible
On Error GoTo Err_SetMenuUserSecurity
Dim MyMenu As CommandBar
Dim MyControl1 As CommandBarControl
Dim MyControl2 As CommandBarControl
Dim MyControl3 As CommandBarControl
Set MyMenu = CommandBars("Главное меню Information") 'здесь Вы
должны указать имя вашей панели
инструментов
Set MyControl1 = MyMenu.Controls(i)
If j = 0 Then
If EnVis Then
MyControl1.Enabled = Par
Else
MyControl1.Visible = Par
End If
Exit Function
End If
Set MyControl2 = MyControl1.Controls(j)
If K = 0 Then
If EnVis Then
MyControl2.Enabled = Par
Else
MyControl2.Visible = Par
End If
Exit Function
End If
Set MyControl3 = MyControl2.Controls(K)
If EnVis Then
MyControl3.Enabled = Par
Else
MyControl3.Visible = Par
End If
Exit_SetMenuUserSecurity:
Exit Function
Err_SetMenuUserSecurity:
MsgBox Err.Description
Resume Exit_SetMenuUserSecurity
End Function
Пример части меню:

Примеры вызова:
SetMenuUserSecurity(1,2,3,False,True) результат:

видно, что пункт Хранилище счет-фактур не
активен и пользователь не сможет его
выбрать. Вызов SetMenuUserSecurity(1,2,3,True,True)
востановит исходное состояние.
Вызов SetMenuUserSecurity(1,2,3,False,False) вообще удалит пункт меню, так, что пользователь и не будет догадываться о его наличии:

Кроме использования в каких либо контекстных случаях, эти методы можно применить для создания своеобразной системы разграничения прав доступа. Которая будет очень гибкой - вплоть до конкретного пункта меню. Создайте таблицу UserMenuItems, с полями: IDMenuItem - счетчик - код пункта меню, ItemDescription - название меню словами, ID1, ID2, ID3 - адрес меню. И таблицу UserRight, с полями: EmployerID - код пользователя, IDMenuItem - код пункта меню из таблицы UserMenuItems, Right - право (boolean). Соответственно для любого пользователя можно определить его 'профиль' меню. Данная система может работать на ряду с защитой, организованной стандартным методом на уровне таблиц. В тех случаях когда не возможно все права задать на этом уровне или есть противоречия. Например пользователь имеет право вносить исходные данные в таблицу, но не должен запускать отчет построенный на основе этой таблицы. Понятно, что права можно назначить и на отчет, но я знаю, что обычно мало кто идет дальше прав на уровне таблиц.
Следующая функция, запускаемая при
инициализации программы устанавливает
профиль зарегистрировавшегося
пользователя.
Public Function UserMenuControl()
'устанавливает пользовательский профиль меню, если он есть (или его часть)
On Error GoTo Err_UserMenuControl
Dim MySet As Recordset
Set MySet = InfoDB.OpenRecordset("Select UserRight.EmployerID,UserRight.Right,ID1,ID2,ID3 From (UserRight inner Join UserMenuItems on UserRight.IDMenuItem=UserMenuItems.IDMenuItem) Where EmployerID=" & Str$(GlUserID))
'GlUserID - код
пользователя, соответствует EmployerID из
таблицы UserRight
If Not MySet.EOF Then
MySet.MoveFirst
While Not MySet.EOF
Call SetMenuUserSecurity(MySet!ID1, MySet!ID2, MySet!ID3, MySet!Right,
False)
MySet.MoveNext
Wend
End If
Exit_UserMenuControl:
Exit Function
Err_UserMenuControl:
MsgBox Err.Description
Resume Exit_UserMenuControl
End Function
21.3.2001 Сакович Роман sakovich@oma.by