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