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

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

Как программно закрыть форму в 1С

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

Закрытие формы — одна из базовых операций при разработке на платформе 1С:Предприятие. Программно закрыть форму можно как из самой формы, так и извне: из другой формы, общего модуля, обработчика ожидания или при наступлении определённого события. Правильный выбор метода зависит от того, где вызывается код, есть ли у формы несохранённые изменения и нужно ли передать результат владельцу.

Основной инструмент — метод Закрыть() управляемой формы. Однако у него есть важные особенности: форма может отказаться закрываться, если в обработчике ПередЗакрытием установлен флаг отказа, а закрытие модифицированной формы без подтверждения приведёт к потере введённых пользователем данных. Поэтому простой вызов метода — только часть решения.

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

Как закрыть форму из самой себя

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

&НаКлиенте

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

Закрыть();

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

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

&НаКлиенте

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

Закрыть(ВыбранноеЗначение);

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

Важно понимать: Закрыть() не гарантирует мгновенное уничтожение формы. Если в обработчике ПередЗакрытием установлено Отказ = Истина (например, при несохранённых изменениях), форма останется открытой. Поэтому код, следующий за вызовом Закрыть(), должен быть готов к тому, что форма ещё существует.

Как закрыть форму из другой формы или внешнего кода

Закрыть форму извне можно, только имея ссылку на объект формы. Платформа не предоставляет глобального метода «закрыть все формы документа», поэтому ссылку нужно получить заранее — в момент открытия или через оповещения.

Типовой подход — сохранить ссылку на открытую форму при её создании и использовать позже:

&НаКлиенте

Процедура ОткрытьНастройки(Команда)

ФормаНастроек = ОткрытьФорму("Обработка.Настройки.Форма.ФормаНастроек", , ЭтотОбъект);

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

&НаКлиенте

Процедура ЗавершитьРаботу(Команда)

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

ФормаНастроек.Закрыть();

КонецЕсли;

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

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

Если ссылки на форму нет, но форма открывалась с уникальным ключом, её можно найти через повторный вызов ОткрытьФорму() с тем же ключом: платформа вернёт уже существующую форму вместо создания новой. Это рабочий способ получить доступ к открытой форме списка или объекта.

Порядок действий
  1. 1
    Получите ссылку на форму при её открытии или через ОткрытьФорму с тем же ключом уникальности
  2. 2
    Проверьте, что ссылка не Неопределено и форма ещё открыта методом Открыта()
  3. 3
    Вызовите у формы метод Закрыть() на клиенте
  4. 4
    Если форма могла быть модифицирована, заранее решите судьбу несохранённых данных
  5. 5
    Проверьте результат: форма исчезла с экрана, событие ПриЗакрытии отработало

Закрытие модифицированной формы без потери данных

Главный риск при программном закрытии — потеря введённых пользователем данных. Если реквизит формы изменён, свойство Модифицированность принимает значение Истина, и при закрытии платформа по умолчанию задаёт вопрос о сохранении. В пакетном сценарии этот вопрос может быть нежелателен.

Есть три корректных варианта поведения. Первый — записать данные перед закрытием:

&НаКлиенте

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

Если Записать() Тогда

Закрыть();

КонецЕсли;

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

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

Третий вариант — показать собственный диалог с выбором действия через ПоказатьВопрос() с описанием оповещения, а затем в зависимости от ответа записать, закрыть без сохранения или отменить закрытие. Это самый безопасный путь, когда решение должен принимать пользователь.

Обработчики ПередЗакрытием и ПриЗакрытии: что в них делать

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

&НаКлиенте

Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)

Если ЗавершениеРаботы И Модифицированность Тогда

Отказ = Истина;

ТекстПредупреждения = "Есть несохранённые изменения";

КонецЕсли;

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

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

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

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

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

Иногда требуется закрыть все открытые окна приложения — например, при смене пользователя или перед массовой обработкой данных. Штатного метода «закрыть всё» нет, но есть метод ЗавершитьРаботуСистемы() для завершения сеанса и возможность перебрать открытые окна через ПолучитьОкна().

&НаКлиенте

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

Окна = ПолучитьОкна();

Для Каждого Окно Из Окна Цикл

Если Окно.ПолучитьСодержимое() <> Неопределено Тогда

Окно.ПолучитьСодержимое().Закрыть();

КонецЕсли;

КонецЦикла;

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

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

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

Сравнение вариантов

Закрыть() из самой формы

Подходит для кнопок и завершения действий внутри формы. Ограничение — только в клиентском контексте самой формы

Закрытие через ссылку на форму

Подходит для управления дочерними формами из владельца. Требует хранить ссылку и проверять Открыта()

Перебор через ПолучитьОкна()

Подходит для массового закрытия. Ограничение — формы с изменениями откажутся закрываться или зададут вопросы

ЗавершитьРаботуСистемы()

Когда нужно закрыть весь сеанс, а не отдельные окна. Не подходит для точечного управления формами

Как проверить, что форма закрылась корректно

После программного закрытия убедитесь, что результат соответствует ожиданиям. Визуально форма должна исчезнуть из интерфейса; программно метод Открыта() у сохранённой ссылки должен вернуть Ложь.

Если форма возвращала значение, проверьте, что обработчик ОбработкаВыбора владельца или описание оповещения получили ожидаемое значение, а не Неопределено. Значение Неопределено при закрытии обычно означает, что пользователь закрыл форму крестиком без выбора.

При отладке полезно временно добавить вывод сообщений в обработчики ПередЗакрытием и ПриЗакрытии: так видно, в какой момент цепочка прерывается. Если форма не закрывается, первое, что нужно проверить, — не устанавливает ли какой-либо код Отказ = Истина.

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

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

Состояние формы после Закрыть()
Норма

Метод Открыта() возвращает Ложь, форма исчезла с экрана

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

Форма осталась открытой — где-то установлен Отказ = Истина

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

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

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

Получено Неопределено — форма закрыта без передачи результата

Несохранённые данные
Норма

Перед закрытием данные записаны или пользователь подтвердил отказ от сохранения

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

Изменения пропали без вопроса — проверка модифицированности отключена

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

Почему форма не закрывается после вызова Закрыть()?

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

Можно ли закрыть форму из серверной процедуры?

Напрямую нет: метод Закрыть() доступен только на клиенте. Из серверной процедуры верните признак необходимости закрытия, а в вызывающем клиентском коде проверьте его и вызовите Закрыть(). Это стандартный шаблон взаимодействия клиента и сервера в управляемых формах.

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

Нужно снять модифицированность до закрытия: для формы объекта — перечитать данные методом Прочитать(), либо в обработчике ПередЗакрытием обработать ситуацию и не устанавливать Отказ. Делайте это осознанно: пользователь потеряет введённые данные без предупреждения.

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

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

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

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

Чем закрытие формы отличается от завершения работы системы?

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

Итог

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

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