Ещё делая первый свой крупный проект, лет этак шесть назад, я пришел к выводу, что на экране должна находиться только одна форма. Несколько одновременно открытых форм загромождают рабочее поле, возникает возможность случайного переключения между открытыми формами, что может привести к ошибкам. (Правда, иногда наличие нескольких форм на экране оправдано. Например, из большой формы ты можешь вызвать какой-нибудь справочник, чтобы посмотреть нужное значение или откорректировать его.) Использование модальных форм не всегда оправдано. Например, при выводе на экран отчета из модальной формы, эта форма остается на экране поверх отчета. Что не очень-то красиво. Пришлось сесть за разработку интерфейса. После нескольких экспериментов, я пришел к выводу, что при вызове одной формы из другой, надо делать родительскую форму невидимой, а при закрытии - восстанавливать видимость. Единственное условие - передача в дочернюю форму имени родительской формы. Здесь можно использовать три метода. (По крайней мере, я додумался до трех.)
- Использовать глобальную текстовую переменную. В момент открытия формы, считывать из неё имя родительской формы, помещать в локальную переменную, а в глобальную записывать своё имя открываемой формы. При вызове следующей формы, операция повторяется. Таким образом, в глобальной переменной хранится имя текущей активной формы. При закрытии формы сначала в глобальную переменную помещается имя родительской формы из локальной переменной, затем закрывается текущая форма и управление передается родительской форме.
- Передавать имя родительской формы через аргументы команды DoCmd.OpenForm
- Передавать имя родительской формы через тег (Tag) загружаемой формы.
Каждый способ имеет как свои преимущества, так и недостатки. В конце концов, мне надоело выписывать строки кода в каждой форме, по этому я сделал две подпрограммы и вынес их в отдельный модуль.
Вот пример реализации управления видимостью форм при передаче имени по третьему методу.
Подпрограмма открытия формы
Public Sub GotoForm(Name As String, Optional MyForm As Variant, Optional StrWhere As Variant, Optional StrArg As String)
' Параметры подпрограммы GotoForm
' Name as String - имя загружаемой формы
' MyForm as Variant - имя закрываемой формы (опционально)
' StrWhere as Variant - cтроковое выражение, представляющее допустимое
' предложение SQL WHERE без ключевого слова
' WHERE (опционально)
' StrArg as String - аргументы открытия (опционально)
On Error GoTo Err_GotoForm
Dim stDocName As String
Dim stLinkCriteria As String
Dim strHide As String
' определяется имя активной формы
strHide = Screen.ActiveForm.Name
' активная форма делается невидимой
Screen.ActiveForm.Visible = False
' проверяется наличие условий
If Not IsMissing(StrWhere) Then
If Len(StrWhere) > 0 Then
DoCmd.OpenForm Name, acNormal, , StrWhere, , , StrArg
' проверяется наличие закрываемой формы
If Not IsMissing(MyForm) Then
DoCmd.Close acForm, strHide
Else
Screen.ActiveForm.Tag = strHide
End If
Exit Sub
End If
End If
' если нет условий на открытие формы
DoCmd.OpenForm Name, acNormal, , , , , StrArg
' проверяется наличие закрываемой формы
If Not IsMissing(MyForm) Then
DoCmd.Close acForm, strHide
Else
Screen.ActiveForm.Tag = strHide
End If
Exit_GotoForm:
Exit Sub
Err_GotoForm:
MsgBox Err.Description
Resume Exit_GotoForm
End Sub
****************************************************
Функция закрытия формы
Public Function fnCloseForm() As Long
' Данная функция закрывает текущую форму и делает
' видимой родительскую форму
On Error GoTo Err_fnCloseForm
Dim strUnhide As String
Dim Name As String
' определяется имя активной формы
Name = Screen.ActiveForm.Name
' определяется наличие родительской формы
If Nz(Screen.ActiveForm.Tag) = "" Then
DoCmd.Close acForm, Name
Else
strUnhide = Screen.ActiveForm.Tag
DoCmd.Close acForm, Name
DoCmd.SelectObject acForm, strUnhide
End If
' если при выполнении функции не произошло ошибки
fnCloseForm = 0
Exit_fnCloseForm:
Exit Function
Err_fnCloseForm:
' если при выполнении функции произошла ошибка
' MsgBox Err.Description
fnCloseForm = Err.Number
Resume Exit_fnCloseForm
End Function
Эти две подпрограммы надо применять совместно. Код конечно далек от идеала, например подпрограмму GotoForm можно представить в виде:
Public Sub GotoForm(Name As String, Optional MyForm As Variant, Optional StrWhere As String, Optional StrArg As String)
' Параметры подпрограммы GotoForm
' Name as String - имя загружаемой формы
' MyForm as Variant - имя закрываемой формы (опционально)
' StrWhere as String - cтроковое выражение, представляющее допустимое
' предложение SQL WHERE без ключевого слова
' WHERE (опционально)
' StrArg as String - аргументы открытия (опционально)
On Error GoTo Err_GotoForm
Dim stDocName As String
Dim strHide As String
' определяется имя активной формы
strHide = Screen.ActiveForm.Name
' активная форма делается невидимой
Screen.ActiveForm.Visible = False
' открывается новая форма
DoCmd.OpenForm Name, acNormal, , StrWhere, , , StrArg
' проверяется наличие закрываемой формы
If Not IsMissing(MyForm) Then
DoCmd.Close acForm, strHide
Else
Screen.ActiveForm.Tag = strHide
End If
Exit_GotoForm:
Exit Sub
Err_GotoForm:
MsgBox Err.Description
Resume Exit_GotoForm
End Sub
Оба варианта работоспособны, причем второй проще и красивее. Прошу не слишком ругать, я эти подпрограммки сочинил, когда из всей литературу по Access у меня была книга "Access 97 - шаги к эффективной работе" (что-то вроде "Access за 24 часа") и хелп к самому Access 97.
Эти подпрограммы по существу являются "обертками" стандартных команд Access. Их можно изменять и дорабатывать под свой вкус. Но и в таком виде они решают большинство стоящих перед Вами задач. А если надо, то добавьте новые параметры. Скачать пример реализации работы форм Вы можете ниже.