При разработке внешних обработок заполнения для конфигураций на базе БСП (Библиотеки Стандартных Подсистем), таких как "Бухгалтерия предприятия 3.0", разработчики часто сталкиваются с проблемой: механизм Оповестить и ОбработкаОповещения, привычный по обычным формам или встроенным объектам, перестает работать. Пользователь вводит данные в дополнительную форму настроек, нажимает "ОК", но основная форма обработки или форма документа никак на это не реагирует.
Разберем подробно, почему это происходит и как правильно организовать передачу данных между формами внешней обработки в современных управляемых приложениях.
Проанализируем ситуацию, с которой столкнулся автор темы. Использование метода Оповестить является «широковещательным» механизмом. Когда вызывается Оповестить(ИмяСобытия, Параметр, Источник), платформа рассылает это сообщение всем открытым окнам в рамках текущего сеанса. Казалось бы, основная форма должна его поймать, но этого не происходит по нескольким причинам:
ВнешняяОбработка.ИмяФайла_Идентификатор). Если в коде жестко прописано имя источника "ВнешняяОбработка.ЗаполнитьПоЗаявке.Форма.Форма", оно может просто не совпасть с реальным внутренним именем, которое назначила БСП.ВызовКлиентскогоМетода. В этом случае "основная" форма обработки может даже не открываться визуально, а служить лишь контейнером для кода. Если форма не открыта и не активна, её обработчик ОбработкаОповещения не сработает.Рассмотрим самый простой и эффективный способ, предложенный в обсуждении. Вместо того чтобы «кричать» в пустоту через Оповестить, мы можем напрямую обратиться к форме, которая открыла наше окно настроек. Для этого при открытии вспомогательной формы нужно явно указать владельца.
В основной форме обработки (или в методе ВыполнитьКоманду) мы открываем форму настроек следующим образом:
&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
// Указываем ВладельцаФормы. Обычно это форма документа, из которого вызвана обработка.
ПараметрыФормы = Новый Структура("ОбъектыНазначения", ОбъектыНазначенияМассив);
ОткрытьФорму("ВнешняяОбработка.МояОбработка.Форма.ФормаНастроек", ПараметрыФормы, ВладелецФормы);
КонецПроцедуры
Теперь во вспомогательной форме (где пользователь вводит параметры) мы можем напрямую взаимодействовать с данными документа через свойство ВладелецФормы. Посмотрим на пример реализации процедуры заполнения по кнопке:
&НаКлиенте
Процедура ЗаполнитьИЗакрыть(Команда)
// Получаем доступ к форме документа-владельца
ФормаДокумента = ВладелецФормы;
// Мы можем напрямую обращаться к данным объекта на форме владельца
Для Каждого СтрокаТовара Из ФормаДокумента.Объект.Товары Цикл
// Например, меняем дату или цену на основании введенных пользователем данных
СтрокаТовара.ДатаОтгрузки = Объект.ВыбраннаяДата;
КонецЦикла;
// Если нужно вызвать штатные обработчики изменения данных на форме документа
// ФормаДокумента.Элементы.Товары.Обновить();
ЭтаФорма.Закрыть();
КонецПроцедуры
Важный момент: При таком подходе форма настроек фактически сама выполняет работу по заполнению документа, имея прямой доступ к его контексту через ВладелецФормы. Это избавляет нас от необходимости передавать структуры данных «туда-обратно».
Если мы хотим придерживаться более строгого разделения логики (когда форма настроек только собирает данные, а заполняет их основная логика обработки), следует использовать объект ОписаниеОповещения. Это современный стандарт разработки на платформе 8.3.
Разберем этот метод пошагово:
ОписаниеОповещения.ОткрытьФорму.Пример кода в основной части обработки:
&НаКлиенте
Процедура ЗапроситьПараметры()
Оповещение = Новый ОписаниеОповещения("ПослеВводаПараметров", ЭтотОбъект);
ОткрытьФорму("ВнешняяОбработка.ЗаполнитьПоЗаявке.Форма.ФормаНастроек", , ЭтотОбъект, , , , Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаПараметров(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат; // Пользователь просто закрыл форму
КонецЕсли;
// Здесь логика обработки полученных данных (Результат - это структура или значение)
Сообщить("Выбранная дата: " + Результат.ДатаНачала);
КонецПроцедуры
А в форме настроек код будет выглядеть так:
&НаКлиенте
Процедура Перенести(Команда)
СтруктураРезультата = Новый Структура;
СтруктураРезультата.Вставить("ДатаНачала", Объект.ДатаНачала);
// Закрываем форму и передаем данные в ОписаниеОповещения
Закрыть(СтруктураРезультата);
КонецПроцедуры
Проанализируем преимущества использования ОписаниеОповещения и прямого обращения к владельцу:
ОбработкаОповещения бесконечными проверками Если ИмяСобытия = "..." Тогда.Выясним, как упростить процесс разработки подобных механизмов:
1. Проверка владельца: Всегда проверяйте, что именно является владельцем вашей формы. В режиме отладки вычислите значение ВладелецФормы. Если это форма документа, вы увидите тип УправляемаяФорма с объектом нужного метаданного.
2. Использование Временного Хранилища: Если данных для передачи слишком много (например, большая таблица значений), поместите её во временное хранилище на сервере формы настроек, а через Закрыть() или Оповестить() передайте только Адрес этого хранилища. Это значительно ускорит работу клиент-серверного взаимодействия.
Таким образом, для решения проблемы автора достаточно было либо правильно назначить ВладелецФормы при открытии, либо перейти на использование ОписаниеОповещения, что является более современным и «безопасным» способом разработки в среде 1С:Предприятие 8.3.