При разработке в среде 1С:Предприятие 8 на базе обычных форм программисты часто сталкиваются с задачей: нужно открыть форму (например, типового отчета или документа), дождаться, пока пользователь завершит с ней работу, и после ее закрытия выполнить определенные действия в исходной обработке. Ситуация осложняется, когда код открываемой формы менять нельзя (например, это типовой объект конфигурации на поддержке). Рассмотрим, как решить эту задачу, используя стандартные механизмы платформы.
В управляемых формах (так называемый «Такси» или УФ) для подобных целей существует параметр ОписаниеОповещенияОЗакрытии. В обычных же формах такой механизм отсутствует. Попытки передать в структуру параметров экспортную процедуру, как это пробовал сделать автор темы, не увенчаются успехом: система просто проигнорирует этот параметр, так как механизм обратного вызова (callback) в старом интерфейсе не реализован на уровне ядра.
Разберем два рабочих сценария решения этой проблемы.
Это самый простой и надежный способ «остановить» выполнение кода в основной обработке до момента закрытия вызванного окна. Рассмотрим этот метод на примере кода автора, когда нужно выбрать документ и открыть его форму.
Алгоритм действий:
ОткрытьМодально().Проанализируем пример кода:
Процедура КнопкаВыполнитьНажатие(Кнопка)
// 1. Получаем и настраиваем форму выбора
ФормаВыбора = Документы.РегламентированныйОтчет.ПолучитьФормуВыбора();
ФормаВыбора.ДокументСписок.Отбор.НаименованиеОтчета.ВидСравнения = ВидСравнения.Равно;
ФормаВыбора.ДокументСписок.Отбор.НаименованиеОтчета.Значение = "Декларация по НДС";
ФормаВыбора.ДокументСписок.Отбор.НаименованиеОтчета.Установить();
// 2. Открываем форму выбора модально
ВыбДок = ФормаВыбора.ОткрытьМодально();
Если ЗначениеЗаполнено(ВыбДок) Тогда
// 3. Получаем форму самого документа
ФормаДок = ВыбДок.ПолучитьФорму();
// 4. Открываем форму документа МОДАЛЬНО
// Выполнение кода ПРИОСТАНОВИТСЯ на этой строке
ФормаДок.ОткрытьМодально();
// 5. Этот код выполнится ТОЛЬКО ПОСЛЕ ЗАКРЫТИЯ формы ФормаДок
Сообщить("Форма была закрыта. Выполняем действия по сохранению...");
// Здесь можно вызвать процедуру записи или оповещения
ВыполнитьДействияПослеЗакрытия();
КонецЕсли;
КонецПроцедуры
Преимущества: Простота реализации. Код выполняется последовательно, не нужно использовать дополнительные переменные или таймеры.
Недостатки: Модальный режим блокирует весь интерфейс 1С. Пользователь не сможет переключиться на другое окно программы, пока не закроет форму отчета.
Если блокировка интерфейса недопустима, нам придется использовать «немодальное» открытие в связке с периодической проверкой состояния формы. Для этого мы будем использовать свойство формы Открыта().
Разберем по шагам, как это реализовать:
Открыть().Рассмотрим пример реализации в модуле обработки:
Перем СсылкаНаФормуПодчиненную; // Переменная в начале модуля
Процедура КнопкаВыполнитьНажатие(Кнопка)
// Настройка и получение формы (аналогично предыдущему примеру)
ВыбДок = Документы.РегламентированныйОтчет.НайтиПоНомеру("001");
Если ВыбДок.Пустая() Тогда Возврат; КонецЕсли;
СсылкаНаФормуПодчиненную = ВыбДок.ПолучитьФорму();
СсылкаНаФормуПодчиненную.Открыть();
// Подключаем проверку: процедура "ПроверитьЗакрытиеФормы" будет вызываться каждые 1 сек.
ПодключитьОбработчикОжидания("ПроверитьЗакрытиеФормы", 1);
КонецПроцедуры
Процедура ПроверитьЗакрытиеФормы() Экспорт
// Проверяем состояние формы через свойство Открыта()
Если СсылкаНаФормуПодчиненную = Неопределено Или Не СсылкаНаФормуПодчиненную.Открыта() Тогда
// Если мы здесь, значит форма закрыта пользователем
ОтключитьОбработчикОжидания("ПроверитьЗакрытиеФормы");
Сообщить("Внимание: Подчиненная форма закрыта. Начинаем обработку данных.");
// Очищаем ссылку
СсылкаНаФормуПодчиненную = Неопределено;
// Выполняем нужные действия
ДействияПослеЗакрытия();
КонецЕсли;
КонецПроцедуры
Важный нюанс: Процедура ПроверитьЗакрытиеФормы обязательно должна иметь признак Экспорт, иначе глобальный контекст не сможет ее вызвать по таймеру.
Выясним причину, почему в коде автора возникали сложности. Автор использовал ОткрытьФорму, которая является методом глобального контекста. Для решения нашей задачи гораздо эффективнее использовать ПолучитьФорму.
Когда мы вызываем ПолучитьФорму, мы получаем объект типа Форма, с которым можем работать как с объектом: проверять его свойства (Открыта()), программно менять заголовок или состав кнопок перед открытием. При использовании ОткрытьФорму мы сразу «выбрасываем» окно на экран и теряем гибкий контроль над ним.
Механизм Оповестить() и ОбработкаОповещения часто путают с механизмом возврата результата. Чтобы оповещение сработало, внутри подчиненной формы в событии ПриЗакрытии должен быть написан код:
Оповестить("ЗакрытиеФормыОтчета", Параметры);
Так как в нашем условии мы не можем менять код отчета, этот способ нам не подходит — стандартные формы типовых конфигураций обычно не рассылают произвольных оповещений при своем закрытии.
Для «отлова» закрытия чужой формы в обычных формах 1С 8.3:
Открыта(), если нужно сохранить интерактивность приложения.ПолучитьФорму(), чтобы сохранять ссылку на объект формы в переменной модуля.