Процесс программного закрытия формы в платформе 1С кажется тривиальной задачей, однако на практике разработчики часто сталкиваются с ситуациями, когда команда Закрыть() либо не срабатывает, либо вызывает ошибки выполнения. В этой статье мы подробно разберем причины возникновения таких проблем, проанализируем поведение системы в различных режимах и выработаем надежные алгоритмы управления жизненным циклом формы.
Рассмотрим классическую ошибку начинающих разработчиков, когда форма открывается модально, а сразу за строкой открытия следует команда закрытия. Проанализируем следующий фрагмент кода:
Отправка = ЭтотОбъект.ПолучитьФорму("Форма1", ЭтаФорма);
Отправка.ДопНомера = ФормаДок.ДокументПриема.ТелефонКонтактногоЛица;
Отправка.ОткрытьМодально();
Отправка.Закрыть(); // Этот код не сработает так, как ожидает автор
Разберем, почему данный код не выполняет свою задачу. Когда мы вызываем метод ОткрытьМодально(), выполнение основного кода полностью приостанавливается. Система ждет, пока пользователь совершит какие-либо действия и самостоятельно закроет форму (нажмет кнопку "ОК", "Закрыть" или крестик). Только после того, как форма будет закрыта вручную, управление вернется в следующую строку. Следовательно, вызов Отправка.Закрыть() в этой последовательности бессмысленен, так как форма к этому моменту уже и так закрыта пользователем.
Важное замечание: Если ваша цель — автоматически передать данные и сразу закрыть форму, то использование модального режима здесь избыточно и даже вредно. Более того, современные конфигурации 1С часто работают в режиме "Отказ от модальности", где использование этого метода приведет к ошибке.
Эта ошибка часто возникает при попытке управлять формой, которая еще не была визуализирована или уже была уничтожена платформой. Рассмотрим по шагам, как избежать этой ситуации:
Закрыть() убедитесь, что ссылка на форму (переменная) все еще содержит валидный объект формы.ЭтаФорма.Закрыть() внутри модуля этой же формы.ПриСозданииНаСервере или ПриОткрытии без использования дополнительных условий), так как это может привести к конфликту состояний.В современных версиях платформы (например, 8.3.27 и выше) встречается специфическая проблема: разработчик вызывает серверную процедуру для обработки данных, после чего на клиенте вызывает ЭтаФорма.Закрыть(), но окно остается на экране. Посмотрим на пример кода:
&НаКлиенте
Процедура УстановитьНДС(Команда)
УстановитьНДСНаСервере();
ЭтаФорма.Закрыть();
КонецПроцедуры
Выясним причину, почему форма может игнорировать команду Закрыть(). В 90% случаев это связано со свойством Модифицированность. Если в процедуре УстановитьНДСНаСервере вы изменили реквизиты, связанные с данными формы, платформа устанавливает флаг ЭтаФорма.Модифицированность = Истина. При попытке закрытия система пытается спросить пользователя: "Данные были изменены. Сохранить?". Если по каким-то причинам этот диалог не может быть показан или блокируется, форма просто остается открытой.
Решение: Перед закрытием принудительно сбросьте флаг модифицированности, если сохранение через стандартный механизм формы не требуется:
&НаКлиенте
Процедура УстановитьНДС(Команда)
УстановитьНДСНаСервере();
ЭтаФорма.Модифицированность = Ложь; // Снимаем признак изменений
ЭтаФорма.Закрыть();
КонецПроцедуры
Проанализируем ситуацию, когда форма открывается исключительно для того, чтобы в нее "записался телефон" или "обновился НДС". В среде 1С это считается "плохой практикой" (антипаттерном). Работа через визуальный интерфейс требует значительных ресурсов клиента и сервера.
Рассмотрим правильный алгоритм действий:
Параметры в методе ОткрытьФорму, а не через прямое обращение к реквизитам полученной формы.Разберем, как правильно реализовать интерактивное взаимодействие в современных управляемых приложениях. Вместо метода ОткрытьМодально(), который блокирует поток, используйте метод ОткрытьФорму() с описанием оповещения.
Пример правильной реализации:
&НаКлиенте
Процедура ВыполнитьДействие(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияФормы", ЭтотОбъект);
ПараметрыФормы = Новый Структура("Телефон", КонтактныйТелефон);
ОткрытьФорму("Обработка.ОтправкаСМС.Форма", ПараметрыФормы, ЭтаФорма, , , , Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗакрытияФормы(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
Если РезультатЗакрытия = Истина Тогда
// Обработка успешного завершения
КонецЕсли;
КонецПроцедуры
В этом случае основная форма остается активной, код не "зависает" на строке открытия, а реакция на закрытие дочерней формы происходит в отдельной процедуре-колбэке. Это обеспечивает стабильную работу в веб-клиенте и тонком клиенте.
Для того чтобы формы в ваших решениях закрывались корректно и предсказуемо, следуйте этим правилам:
Закрыть() сразу после ОткрытьМодально() в одном блоке кода.Модифицированность = Ложь перед программным закрытием, если не хотите стандартных вопросов системы о сохранении.Объект.Записать().ПоказатьВопрос, ПоказатьВводЗначения вместо их модальных аналогов.ПередЗакрытием — там может стоять условие Отказ = Истина, которое блокирует программную команду Закрыть().Соблюдение этих принципов позволит создавать надежный интерфейс, который не будет вводить пользователя в заблуждение "зависшими" окнами или непонятными ошибками доступа к объектам.