К статье
Практический материал

Разработка и Конфигурация · 10 мин

1С: как программно закрыть текущую форму

Как программно закрыть текущую форму в 1С: метод Закрыть(), параметры, закрытие без вопросов, из модуля объекта и общего модуля. Примеры кода и типичные ошибки.

Закрытие формы из кода — одна из самых частых задач при разработке на платформе 1С. Форму нужно закрыть после успешного сохранения данных, при отмене операции, по таймеру или после выбора значения в форме подбора. Во всех этих случаях используется метод Закрыть(), доступный в модуле формы, но у него есть нюансы: поведение при модифицированности данных, отличия для обычных и управляемых форм, закрытие «чужой» формы извне.

Базовый вызов выглядит просто: в модуле формы достаточно написать Закрыть(); — и текущая форма будет закрыта. Однако если данные формы были изменены и не записаны, платформа по умолчанию задаст пользователю вопрос о сохранении. Это штатное поведение, и его нужно учитывать, чтобы форма не «зависала» вопросом в неподходящий момент бизнес-логики.

Ниже разобраны основные сценарии: простое закрытие, закрытие без вопросов, закрытие с возвратом значения в форму-владельца, закрытие из общего модуля и типичные ошибки, из-за которых форма не закрывается или закрывается не та.

Простое закрытие текущей формы методом Закрыть()

Метод Закрыть() доступен только в контексте формы — то есть в её модуле или через объект формы. Самый частый сценарий — закрытие по команде кнопки:

&НаКлиенте

Процедура КомандаЗакрыть(Команда)

Закрыть();

КонецПроцедуры

Если форма открыта модально (в режиме блокировки окна владельца) или как обычное окно, метод отработает одинаково — форма будет закрыта, а открывший её код продолжит выполнение (для модального открытия — после возврата из ОткрытьФормуМодально или после обработки оповещения).

Важно понимать: Закрыть() — это клиентский вызов. В серверной процедуре формы (&НаСервере) напрямую закрыть форму нельзя, потому что на сервере нет интерфейсного контекста. Если логика проверки выполняется на сервере, верните признак на клиент и закройте форму уже там:

&НаКлиенте

Процедура ЗаписатьИЗакрыть(Команда)

Если ЗаписатьНаСервере() Тогда

Закрыть();

КонецЕсли;

КонецПроцедуры

Как закрыть форму без вопроса о сохранении данных

Если пользователь изменил данные в форме, при вызове Закрыть() платформа покажет диалог «Данные были изменены. Сохранить изменения?». В ряде сценариев это нежелательно: например, кнопка «Отмена» должна просто закрывать форму, а автоматическое закрытие после успешной записи не должно задавать лишних вопросов.

Чтобы подавить вопрос, перед закрытием сбросьте признак модифицированности:

&НаКлиенте

Процедура Отмена(Команда)

Модифицированность = Ложь;

Закрыть();

КонецПроцедуры

Установка Модифицированность = Ложь сообщает платформе, что несохранённых изменений нет, и форма закрывается молча. Используйте этот приём осознанно: если пользователь реально ввёл данные и нажал «Отмену» по ошибке, изменения будут потеряны без предупреждения.

Альтернативный вариант — обработчик ПередЗакрытием, в котором можно управлять поведением через параметры Отказ и ЗавершениеРаботы. Там же можно задать свой вопрос пользователю через ПоказатьВопрос, если стандартный диалог не подходит по тексту или набору кнопок.

Закрытие формы с возвратом значения в вызывающую форму

Формы выбора и подбора обычно должны вернуть результат туда, откуда их открыли. Для этого метод Закрыть() принимает необязательный параметр — возвращаемое значение:

&НаКлиенте

Процедура Выбрать(Команда)

Закрыть(Элементы.Список.ТекущиеДанные.Ссылка);

КонецПроцедуры

В модуле формы платформа также предоставляет функцию ЗакрытьФорму в некоторых контекстах, однако основной и документированный способ — именно Закрыть(Значение). Возвращённое значение попадает в обработчик ОбработкаВыбора формы-владельца (для открытия через ОткрытьФорму с указанием владельца) либо в описание оповещения, переданное при открытии:

&НаКлиенте

Процедура ВыбратьКонтрагента(Команда)

Оповещение = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", , ЭтотОбъект, , , , Оповещение);

КонецПроцедуры

&НаКлиенте

Процедура ПослеВыбораКонтрагента(Результат, ДопПараметры) Экспорт

Если Результат <> Неопределено Тогда

Объект.Контрагент = Результат;

КонецЕсли;

КонецПроцедуры

Если форма закрывается крестиком или клавишей Esc без явного вызова Закрыть(Значение), в оповещение придёт Неопределено (или значение, заданное в параметре ЗначениеЗакрытия формы). Поэтому в обработчике результата всегда проверяйте его на Неопределено.

Закрытие формы из другого места: общий модуль и внешний код

Иногда закрыть форму нужно не из её собственного модуля, а извне — например, из общего клиентского модуля по таймеру или при получении оповещения. Для этого сначала нужно получить ссылку на объект формы. Если форма открывалась программно, сохраните её при открытии:

&НаКлиенте

Процедура ОткрытьОбработку(Команда)

ФормаОбработки = ОткрытьФорму("Обработка.МояОбработка.Форма");

КонецПроцедуры

Далее из любого клиентского контекста, где доступна переменная ФормаОбработки, можно вызвать ФормаОбработки.Закрыть(). Если форма уже закрыта пользователем, повторный вызов безопасен — исключения не возникнет, но полагаться на это в логике не стоит; лучше проверять ФормаОбработки.Открыта():

Если ФормаОбработки <> Неопределено И ФормаОбработки.Открыта() Тогда

ФормаОбработки.Закрыть();

КонецЕсли;

Закрытие по оповещению

Универсальный механизм — оповещения. Открытая форма подписывается на событие через ОбработкаОповещения, а инициатор рассылает его через Оповестить(). В обработчике форма решает, закрываться ли ей:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ЗакрытьФормуПодбора" Тогда

Закрыть();

КонецЕсли;

КонецПроцедуры

Порядок действий
  1. 1
    Определите, где нужно закрыть форму: в её модуле или извне
  2. 2
    В модуле формы вызовите Закрыть() в клиентской процедуре
  3. 3
    Если нужен возврат значения — передайте его параметром: Закрыть(Результат)
  4. 4
    Если вопрос о сохранении не нужен — установите Модифицированность = Ложь до вызова
  5. 5
    Проверьте: форма закрылась, владелец получил результат, лишних диалогов нет

Закрытие формы в обычном приложении и тонкости управляемых форм

В обычных формах (толстый клиент, режим обычного приложения) метод Закрыть() также доступен и работает аналогично. Дополнительно там часто использовалась конструкция ЭтаФорма.Закрыть() и проверка ЭтаФорма.Открыта(). В управляемых формах обращение к форме из её модуля идёт напрямую, а ЭтаФорма применяется при передаче формы как параметра.

Для управляемых форм есть особенность с обработчиком ПередЗакрытием: если в нём установить Отказ = Истина, закрытие будет отменено — в том числе инициированное программно. Это частая причина ситуации «вызываю Закрыть(), а форма не закрывается». Проверьте, нет ли в модуле формы или в расширении обработчика, блокирующего закрытие.

Ещё одна тонкость — параметр ЗавершениеРаботы в ПередЗакрытием. При завершении работы программы нельзя показывать модальные вопросы: они будут проигнорированы или вызовут ошибку. Проверяйте этот параметр, если в обработчике есть диалоги с пользователем.

Типичные ошибки
01
Вызов Закрыть() в серверной процедуре — метод недоступен на сервере, получите ошибку
02
Форма не закрывается из-за Отказ = Истина в обработчике ПередЗакрытие — проверьте модуль формы и расширения
03
Закрытие без сброса Модифицированности — пользователь получает неожиданный вопрос о сохранении
04
Отсутствие проверки Результат <> Неопределено в оповещении — при закрытии крестиком в реквизит попадает пустое значение
05
Попытка закрыть уже закрытую форму без проверки Открыта() — логика ветвится по неверному пути

Проверка результата и отладка

После внедрения закрытия проверьте три вещи. Первое — форма действительно закрывается во всех сценариях: по кнопке, по Esc, по крестику, при завершении работы. Второе — вызывающая форма корректно получает результат, если он предусмотрен. Третье — при отмене не остаётся «висящих» блокировок данных: если форма редактировала объект, записанный в базу, убедитесь, что он не остался заблокированным.

Для отладки удобно поставить точку останова в ПередЗакрытием и ПриЗакрытии — так видно, в каком порядке и с какими параметрами срабатывают события. Если закрытие инициируется оповещением, проверьте, что имя события в Оповестить() и в ОбработкаОповещения совпадает посимвольно — опечатка в строке не даёт ошибку, событие просто не приходит.

Контрольные точки

Как проверить результат

Закрытие по кнопке
Норма

Форма закрывается, лишних диалогов нет

Тревожный признак

Появляется вопрос о сохранении там, где его не должно быть

Возврат значения
Норма

В оповещение приходит ожидаемое значение

Тревожный признак

Приходит Неопределено при явном выборе значения

Закрытие крестиком
Норма

Владелец корректно обрабатывает Неопределено

Тревожный признак

Ошибка или очистка реквизита при отмене выбора

Частые вопросы о закрытии форм в 1С

Как закрыть форму, если Закрыть() не срабатывает?

Чаще всего мешает обработчик ПередЗакрытием с установкой Отказ = Истина — проверьте модуль формы и подключённые расширения. Также убедитесь, что вызов выполняется в клиентском контексте, а не на сервере.

Можно ли закрыть все открытые формы разом?

Штатного метода «закрыть всё» нет. Нужно хранить ссылки на открытые формы (например, в параметре сеанса клиентского общего модуля) и закрывать каждую через Закрыть() с проверкой Открыта(). Либо рассылать оповещение, на которое формы реагируют самозакрытием.

Как закрыть форму автоматически через заданное время?

Используйте ПодключитьОбработчикОжидания("ИмяПроцедуры", Интервал, Истина) в модуле формы. В указанной процедуре вызовите Закрыть(). Не забудьте отключить обработчик при ручном закрытии через ОтключитьОбработчикОжидания.

Чем Закрыть() отличается от УстановитьВидимость(Ложь)?

Установка видимости лишь скрывает элементы, форма продолжает существовать и занимать ресурсы. Закрыть() полностью уничтожает форму и освобождает контекст. Для завершения работы с формой всегда используйте Закрыть().

Как запретить пользователю закрывать форму крестиком?

Полностью убрать крестик нельзя, но можно перехватить закрытие в обработчике ПередЗакрытием и установить Отказ = Истина при неподходящих условиях. Это стандартный способ удержать форму открытой до завершения обязательных действий.

Возвращает ли Закрыть() значение при открытии через ОткрытьФормуМодально?

Да. При модальном открытии значение, переданное в Закрыть(Значение), станет результатом вызова ОткрытьФормуМодально в вызывающем коде. Учтите, что модальный режим в новых разработках не рекомендуется — предпочтителен механизм описаний оповещений.

Итог

Что важно запомнить

Текущая форма закрывается методом Закрыть() на клиенте; параметр метода возвращает значение в открывшую форму. Чтобы избежать вопроса о сохранении, сбросьте Модифицированность. Если форма не закрывается — ищите Отказ = Истина в ПередЗакрытием.