Почему подбор добавляет товары сразу в несколько открытых документов и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При разработке механизмов подбора номенклатуры в управляемых формах 1С часто возникает ситуация, когда пользователь открывает несколько окон документа, например, ЗаказКлиента, и при выборе товара в одном из них, данные дублируются во все открытые формы. Давайте разберем, почему это происходит и как правильно организовать передачу данных, чтобы изменения затрагивали только нужный документ.

Разбор причин возникновения проблемы

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

Рассмотрим стандартный ошибочный подход:


// В форме подбора происходит глобальное оповещение
СПКПараметров = новый Структура();
СПКПараметров.Вставить("СписокХарактеристик", Список);
Оповестить("ПереносНабораВЗаказКлиента", СПКПараметров);

Так как Оповестить не указывает конкретного получателя, все активные формы, имеющие обработчик этого события, начинают выполнять код переноса данных. Это архитектурная ошибка, которую необходимо устранить.

Решение 1: использование метода Закрыть с ОписаниемОповещения

Это самый современный и правильный способ работы с формами подбора. Вместо того чтобы оповещать весь мир о завершении выбора, мы просто закрываем форму и возвращаем результат непосредственно владельцу.

Шаг 1: При открытии формы подбора мы указываем ОписаниеОповещения, которое жестко привязывает метод обработки к конкретному экземпляру вызывающей формы:


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

Шаг 2: В форме подбора, когда пользователь нажал «Выбрать», мы не вызываем Оповестить(), а просто закрываем форму, передавая результат:


// В форме подбора
РезультатВыбора = ...; // Данные, которые хотим передать
Закрыть(РезультатВыбора);

Шаг 3: В основной форме (Заказе) результат попадет в процедуру, указанную в ОписаниеОповещения:


&НаКлиенте
Процедура ПриЗакрытииФормыВыбораНабора(Результат, ДопПараметры) Экспорт
    Если Результат <> Неопределено Тогда
        // Обработка данных только для текущей формы
        ДобавитьТоварыВТабличнуюЧасть(Результат);
    КонецЕсли;
КонецПроцедуры

Этот подход гарантирует, что данные будут получены только той формой, которая инициировала вызов.

Решение 2: использование метода ОповеститьОВыборе

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

В отличие от Оповестить(), метод ОповеститьОВыборе() отправляет данные только владельцу формы. В форме-владельце (документе) вместо события ОбработкаОповещения необходимо реализовать событие ОбработкаВыбора.

Преимущества этого метода:

  1. Автоматическая фильтрация: система сама понимает, кто является владельцем формы, и не отправляет сообщения в другие документы.
  2. Отсутствие необходимости проверять параметры источника в обработчике.
  3. Стандартное поведение платформы, исключающее «замусоривание» глобального контекста оповещений.

Итоги и рекомендации

При разработке интерфейсов в 1С всегда старайтесь придерживаться принципа инкапсуляции данных. Если вам нужно передать результат выбора из формы А в форму Б:

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

← На главную