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