Почему не работает Оповестить во внешней обработке заполнения 1С и как это исправить

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке внешних обработок заполнения для конфигураций на базе БСП (Библиотеки Стандартных Подсистем), таких как "Бухгалтерия предприятия 3.0", разработчики часто сталкиваются с проблемой: механизм Оповестить и ОбработкаОповещения, привычный по обычным формам или встроенным объектам, перестает работать. Пользователь вводит данные в дополнительную форму настроек, нажимает "ОК", но основная форма обработки или форма документа никак на это не реагирует.

Разберем подробно, почему это происходит и как правильно организовать передачу данных между формами внешней обработки в современных управляемых приложениях.

Причина проблемы: особенности работы внешних обработок в БСП

Проанализируем ситуацию, с которой столкнулся автор темы. Использование метода Оповестить является «широковещательным» механизмом. Когда вызывается Оповестить(ИмяСобытия, Параметр, Источник), платформа рассылает это сообщение всем открытым окнам в рамках текущего сеанса. Казалось бы, основная форма должна его поймать, но этого не происходит по нескольким причинам:

  1. Динамические имена объектов: В БСП внешние обработки подключаются динамически. Платформа присваивает им временные имена в иерархии метаданных (например, ВнешняяОбработка.ИмяФайла_Идентификатор). Если в коде жестко прописано имя источника "ВнешняяОбработка.ЗаполнитьПоЗаявке.Форма.Форма", оно может просто не совпасть с реальным внутренним именем, которое назначила БСП.
  2. Отсутствие активной формы: Часто внешняя заполнялка работает через механизм ВызовКлиентскогоМетода. В этом случае "основная" форма обработки может даже не открываться визуально, а служить лишь контейнером для кода. Если форма не открыта и не активна, её обработчик ОбработкаОповещения не сработает.
  3. Контекст выполнения: Оповещение работает только на клиенте. Если происходит разрыв контекста или форма была закрыта до момента обработки, данные будут потеряны.

Способ 1: Использование Владельца формы (наиболее надежный)

Рассмотрим самый простой и эффективный способ, предложенный в обсуждении. Вместо того чтобы «кричать» в пустоту через Оповестить, мы можем напрямую обратиться к форме, которая открыла наше окно настроек. Для этого при открытии вспомогательной формы нужно явно указать владельца.

В основной форме обработки (или в методе ВыполнитьКоманду) мы открываем форму настроек следующим образом:


&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    // Указываем ВладельцаФормы. Обычно это форма документа, из которого вызвана обработка.
    ПараметрыФормы = Новый Структура("ОбъектыНазначения", ОбъектыНазначенияМассив);
    ОткрытьФорму("ВнешняяОбработка.МояОбработка.Форма.ФормаНастроек", ПараметрыФормы, ВладелецФормы);
КонецПроцедуры

Теперь во вспомогательной форме (где пользователь вводит параметры) мы можем напрямую взаимодействовать с данными документа через свойство ВладелецФормы. Посмотрим на пример реализации процедуры заполнения по кнопке:


&НаКлиенте
Процедура ЗаполнитьИЗакрыть(Команда)
    
    // Получаем доступ к форме документа-владельца
    ФормаДокумента = ВладелецФормы;
    
    // Мы можем напрямую обращаться к данным объекта на форме владельца
    Для Каждого СтрокаТовара Из ФормаДокумента.Объект.Товары Цикл
        // Например, меняем дату или цену на основании введенных пользователем данных
        СтрокаТовара.ДатаОтгрузки = Объект.ВыбраннаяДата; 
    КонецЦикла;
    
    // Если нужно вызвать штатные обработчики изменения данных на форме документа
    // ФормаДокумента.Элементы.Товары.Обновить();
    
    ЭтаФорма.Закрыть();
КонецПроцедуры

Важный момент: При таком подходе форма настроек фактически сама выполняет работу по заполнению документа, имея прямой доступ к его контексту через ВладелецФормы. Это избавляет нас от необходимости передавать структуры данных «туда-обратно».

Способ 2: Использование ОписанияОповещения (Callback)

Если мы хотим придерживаться более строгого разделения логики (когда форма настроек только собирает данные, а заполняет их основная логика обработки), следует использовать объект ОписаниеОповещения. Это современный стандарт разработки на платформе 8.3.

Разберем этот метод пошагово:

  1. В вызывающей форме создаем объект ОписаниеОповещения.
  2. Передаем его в ОткрытьФорму.
  3. В закрываемой форме возвращаем результат.

Пример кода в основной части обработки:


&НаКлиенте
Процедура ЗапроситьПараметры()
    
    Оповещение = Новый ОписаниеОповещения("ПослеВводаПараметров", ЭтотОбъект);
    ОткрытьФорму("ВнешняяОбработка.ЗаполнитьПоЗаявке.Форма.ФормаНастроек", , ЭтотОбъект, , , , Оповещение);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаПараметров(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = Неопределено Тогда
        Возврат; // Пользователь просто закрыл форму
    КонецЕсли;
    
    // Здесь логика обработки полученных данных (Результат - это структура или значение)
    Сообщить("Выбранная дата: " + Результат.ДатаНачала);
    
КонецПроцедуры

А в форме настроек код будет выглядеть так:


&НаКлиенте
Процедура Перенести(Команда)
    
    СтруктураРезультата = Новый Структура;
    СтруктураРезультата.Вставить("ДатаНачала", Объект.ДатаНачала);
    
    // Закрываем форму и передаем данные в ОписаниеОповещения
    Закрыть(СтруктураРезультата);
    
КонецПроцедуры

Почему это лучше, чем глобальное Оповестить?

Проанализируем преимущества использования ОписаниеОповещения и прямого обращения к владельцу:

Советы по отладке внешних обработок

Выясним, как упростить процесс разработки подобных механизмов:

1. Проверка владельца: Всегда проверяйте, что именно является владельцем вашей формы. В режиме отладки вычислите значение ВладелецФормы. Если это форма документа, вы увидите тип УправляемаяФорма с объектом нужного метаданного.

2. Использование Временного Хранилища: Если данных для передачи слишком много (например, большая таблица значений), поместите её во временное хранилище на сервере формы настроек, а через Закрыть() или Оповестить() передайте только Адрес этого хранилища. Это значительно ускорит работу клиент-серверного взаимодействия.

Таким образом, для решения проблемы автора достаточно было либо правильно назначить ВладелецФормы при открытии, либо перейти на использование ОписаниеОповещения, что является более современным и «безопасным» способом разработки в среде 1С:Предприятие 8.3.

← На главную