Разработка и Конфигурация · 10 мин
1С: как программно закрыть текущую форму
Как программно закрыть текущую форму в 1С: метод Закрыть(), параметры, закрытие без вопросов, из модуля объекта и общего модуля. Примеры кода и типичные ошибки.
Закрытие формы из кода — одна из самых частых задач при разработке на платформе 1С. Форму нужно закрыть после успешного сохранения данных, при отмене операции, по таймеру или после выбора значения в форме подбора. Во всех этих случаях используется метод Закрыть(), доступный в модуле формы, но у него есть нюансы: поведение при модифицированности данных, отличия для обычных и управляемых форм, закрытие «чужой» формы извне.
Базовый вызов выглядит просто: в модуле формы достаточно написать Закрыть(); — и текущая форма будет закрыта. Однако если данные формы были изменены и не записаны, платформа по умолчанию задаст пользователю вопрос о сохранении. Это штатное поведение, и его нужно учитывать, чтобы форма не «зависала» вопросом в неподходящий момент бизнес-логики.
Ниже разобраны основные сценарии: простое закрытие, закрытие без вопросов, закрытие с возвратом значения в форму-владельца, закрытие из общего модуля и типичные ошибки, из-за которых форма не закрывается или закрывается не та.
Простое закрытие текущей формы методом Закрыть()
Метод Закрыть() доступен только в контексте формы — то есть в её модуле или через объект формы. Самый частый сценарий — закрытие по команде кнопки:
&НаКлиенте
Процедура КомандаЗакрыть(Команда)
Закрыть();
КонецПроцедуры
Если форма открыта модально (в режиме блокировки окна владельца) или как обычное окно, метод отработает одинаково — форма будет закрыта, а открывший её код продолжит выполнение (для модального открытия — после возврата из ОткрытьФормуМодально или после обработки оповещения).
Важно понимать: Закрыть() — это клиентский вызов. В серверной процедуре формы (&НаСервере) напрямую закрыть форму нельзя, потому что на сервере нет интерфейсного контекста. Если логика проверки выполняется на сервере, верните признак на клиент и закройте форму уже там:
&НаКлиенте
Процедура ЗаписатьИЗакрыть(Команда)
Если ЗаписатьНаСервере() Тогда
Закрыть();
КонецЕсли;
КонецПроцедуры
Как закрыть форму без вопроса о сохранении данных
Если пользователь изменил данные в форме, при вызове Закрыть() платформа покажет диалог «Данные были изменены. Сохранить изменения?». В ряде сценариев это нежелательно: например, кнопка «Отмена» должна просто закрывать форму, а автоматическое закрытие после успешной записи не должно задавать лишних вопросов.
Чтобы подавить вопрос, перед закрытием сбросьте признак модифицированности:
&НаКлиенте
Процедура Отмена(Команда)
Модифицированность = Ложь;
Закрыть();
КонецПроцедуры
Установка Модифицированность = Ложь сообщает платформе, что несохранённых изменений нет, и форма закрывается молча. Используйте этот приём осознанно: если пользователь реально ввёл данные и нажал «Отмену» по ошибке, изменения будут потеряны без предупреждения.
Альтернативный вариант — обработчик ПередЗакрытием, в котором можно управлять поведением через параметры Отказ и ЗавершениеРаботы. Там же можно задать свой вопрос пользователю через ПоказатьВопрос, если стандартный диалог не подходит по тексту или набору кнопок.
Закрытие формы с возвратом значения в вызывающую форму
Формы выбора и подбора обычно должны вернуть результат туда, откуда их открыли. Для этого метод Закрыть() принимает необязательный параметр — возвращаемое значение:
&НаКлиенте
Процедура Выбрать(Команда)
Закрыть(Элементы.Список.ТекущиеДанные.Ссылка);
КонецПроцедуры
В модуле формы платформа также предоставляет функцию ЗакрытьФорму в некоторых контекстах, однако основной и документированный способ — именно Закрыть(Значение). Возвращённое значение попадает в обработчик ОбработкаВыбора формы-владельца (для открытия через ОткрытьФорму с указанием владельца) либо в описание оповещения, переданное при открытии:
&НаКлиенте
Процедура ВыбратьКонтрагента(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);
ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", , ЭтотОбъект, , , , Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораКонтрагента(Результат, ДопПараметры) Экспорт
Если Результат <> Неопределено Тогда
Объект.Контрагент = Результат;
КонецЕсли;
КонецПроцедуры
Если форма закрывается крестиком или клавишей Esc без явного вызова Закрыть(Значение), в оповещение придёт Неопределено (или значение, заданное в параметре ЗначениеЗакрытия формы). Поэтому в обработчике результата всегда проверяйте его на Неопределено.
Закрытие формы из другого места: общий модуль и внешний код
Иногда закрыть форму нужно не из её собственного модуля, а извне — например, из общего клиентского модуля по таймеру или при получении оповещения. Для этого сначала нужно получить ссылку на объект формы. Если форма открывалась программно, сохраните её при открытии:
&НаКлиенте
Процедура ОткрытьОбработку(Команда)
ФормаОбработки = ОткрытьФорму("Обработка.МояОбработка.Форма");
КонецПроцедуры
Далее из любого клиентского контекста, где доступна переменная ФормаОбработки, можно вызвать ФормаОбработки.Закрыть(). Если форма уже закрыта пользователем, повторный вызов безопасен — исключения не возникнет, но полагаться на это в логике не стоит; лучше проверять ФормаОбработки.Открыта():
Если ФормаОбработки <> Неопределено И ФормаОбработки.Открыта() Тогда
ФормаОбработки.Закрыть();
КонецЕсли;
Закрытие по оповещению
Универсальный механизм — оповещения. Открытая форма подписывается на событие через ОбработкаОповещения, а инициатор рассылает его через Оповестить(). В обработчике форма решает, закрываться ли ей:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ЗакрытьФормуПодбора" Тогда
Закрыть();
КонецЕсли;
КонецПроцедуры
- 1Определите, где нужно закрыть форму: в её модуле или извне
- 2В модуле формы вызовите Закрыть() в клиентской процедуре
- 3Если нужен возврат значения — передайте его параметром: Закрыть(Результат)
- 4Если вопрос о сохранении не нужен — установите Модифицированность = Ложь до вызова
- 5Проверьте: форма закрылась, владелец получил результат, лишних диалогов нет
Закрытие формы в обычном приложении и тонкости управляемых форм
В обычных формах (толстый клиент, режим обычного приложения) метод Закрыть() также доступен и работает аналогично. Дополнительно там часто использовалась конструкция ЭтаФорма.Закрыть() и проверка ЭтаФорма.Открыта(). В управляемых формах обращение к форме из её модуля идёт напрямую, а ЭтаФорма применяется при передаче формы как параметра.
Для управляемых форм есть особенность с обработчиком ПередЗакрытием: если в нём установить Отказ = Истина, закрытие будет отменено — в том числе инициированное программно. Это частая причина ситуации «вызываю Закрыть(), а форма не закрывается». Проверьте, нет ли в модуле формы или в расширении обработчика, блокирующего закрытие.
Ещё одна тонкость — параметр ЗавершениеРаботы в ПередЗакрытием. При завершении работы программы нельзя показывать модальные вопросы: они будут проигнорированы или вызовут ошибку. Проверяйте этот параметр, если в обработчике есть диалоги с пользователем.
Проверка результата и отладка
После внедрения закрытия проверьте три вещи. Первое — форма действительно закрывается во всех сценариях: по кнопке, по Esc, по крестику, при завершении работы. Второе — вызывающая форма корректно получает результат, если он предусмотрен. Третье — при отмене не остаётся «висящих» блокировок данных: если форма редактировала объект, записанный в базу, убедитесь, что он не остался заблокированным.
Для отладки удобно поставить точку останова в ПередЗакрытием и ПриЗакрытии — так видно, в каком порядке и с какими параметрами срабатывают события. Если закрытие инициируется оповещением, проверьте, что имя события в Оповестить() и в ОбработкаОповещения совпадает посимвольно — опечатка в строке не даёт ошибку, событие просто не приходит.
Как проверить результат
Форма закрывается, лишних диалогов нет
Появляется вопрос о сохранении там, где его не должно быть
В оповещение приходит ожидаемое значение
Приходит Неопределено при явном выборе значения
Владелец корректно обрабатывает Неопределено
Ошибка или очистка реквизита при отмене выбора
Частые вопросы о закрытии форм в 1С
Как закрыть форму, если Закрыть() не срабатывает?
Чаще всего мешает обработчик ПередЗакрытием с установкой Отказ = Истина — проверьте модуль формы и подключённые расширения. Также убедитесь, что вызов выполняется в клиентском контексте, а не на сервере.
Можно ли закрыть все открытые формы разом?
Штатного метода «закрыть всё» нет. Нужно хранить ссылки на открытые формы (например, в параметре сеанса клиентского общего модуля) и закрывать каждую через Закрыть() с проверкой Открыта(). Либо рассылать оповещение, на которое формы реагируют самозакрытием.
Как закрыть форму автоматически через заданное время?
Используйте ПодключитьОбработчикОжидания("ИмяПроцедуры", Интервал, Истина) в модуле формы. В указанной процедуре вызовите Закрыть(). Не забудьте отключить обработчик при ручном закрытии через ОтключитьОбработчикОжидания.
Чем Закрыть() отличается от УстановитьВидимость(Ложь)?
Установка видимости лишь скрывает элементы, форма продолжает существовать и занимать ресурсы. Закрыть() полностью уничтожает форму и освобождает контекст. Для завершения работы с формой всегда используйте Закрыть().
Как запретить пользователю закрывать форму крестиком?
Полностью убрать крестик нельзя, но можно перехватить закрытие в обработчике ПередЗакрытием и установить Отказ = Истина при неподходящих условиях. Это стандартный способ удержать форму открытой до завершения обязательных действий.
Возвращает ли Закрыть() значение при открытии через ОткрытьФормуМодально?
Да. При модальном открытии значение, переданное в Закрыть(Значение), станет результатом вызова ОткрытьФормуМодально в вызывающем коде. Учтите, что модальный режим в новых разработках не рекомендуется — предпочтителен механизм описаний оповещений.
Что важно запомнить
Текущая форма закрывается методом Закрыть() на клиенте; параметр метода возвращает значение в открывшую форму. Чтобы избежать вопроса о сохранении, сбросьте Модифицированность. Если форма не закрывается — ищите Отказ = Истина в ПередЗакрытием.