Как исправить подбор в 1С, когда данные переносятся во все открытые документы

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

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

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

Выясняем причину: почему данные дублируются во все формы?

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

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

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

Способ 1. Классический подбор через «Владельца формы» и ОповеститьОВыборе()

Этот метод основан на жесткой привязке открываемой формы подбора к ее владельцу. В качестве владельца может выступать как сама форма документа, так и конкретный элемент управления (например, табличная часть).

Рассмотрим по шагам, как правильно реализовать этот механизм:

  1. В форме исходного документа: При вызове метода ОткрытьФорму мы обязаны передать владельца третьим параметром. Лучше всего передавать конкретную табличную часть, в которую планируется осуществлять подбор.
  2. В форме подбора: Вместо широковещательного метода Оповестить() мы используем строго направленный метод ОповеститьОВыборе(). Он отправляет данные исключительно владельцу формы.

Давайте посмотрим на практический пример кода.

Код кнопки «Подбор» в форме исходного документа:


&НаКлиенте
Процедура Подбор(Команда)
    
    // Формируем параметры открытия формы выбора
    ПараметрыПодбора = Новый Структура;
    ПараметрыПодбора.Вставить("МножественныйВыбор", Истина);
    ПараметрыПодбора.Вставить("ЗакрыватьПриВыборе", Ложь);
    
    // Открываем форму выбора. 
    // Третьим параметром передаем элемент ТЧ (Элементы.Товары) — он становится Владельцем формы подбора
    ОткрытьФорму("Документ.Расписка.ФормаВыбора", ПараметрыПодбора, Элементы.Товары);
    
КонецПроцедуры

Код кнопки «Перенести в документ» в самой форме подбора:


&НаКлиенте
Процедура Перенести(Команда)
    
    // Передаем массив выбранных элементов строго владельцу формы
    ОповеститьОВыборе(ЭтаФорма.ТЧВыбора);
    
    // Закрываем форму подбора
    Закрыть();
    
КонецПроцедуры

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

Способ 2. Современный асинхронный подход через ОписаниеОповещения

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

Давайте разберем этот процесс по шагам:

  1. В вызывающей форме мы создаем объект ОписаниеОповещения, указывая имя процедуры-обработчика, которая выполнится сразу после закрытия формы подбора.
  2. Передаем этот объект в качестве седьмого параметра метода ОткрытьФорму.
  3. В форме подбора при завершении выбора мы просто вызываем метод Закрыть(), передавая выбранные данные в качестве параметра закрытия.

Реализуем это на практике.

Код в форме исходного документа:


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

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

Код переноса данных в форме подбора:


&НаКлиенте
Процедура ПеренестиИЗакрыть(Команда)
    
    // Закрываем форму и передаем массив выбранных данных напрямую в описание оповещения
    Закрыть(ЭтаФорма.ТЧВыбора);
    
КонецПроцедуры

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

Важность параметра «Уникальность» при открытии формы подбора

Обратите внимание на четвертый параметр метода ОткрытьФорму — Уникальность. Это критически важная настройка при работе с множеством открытых документов.

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

Передавая в качестве параметра уникальности УникальныйИдентификатор текущей формы документа, мы гарантируем, что для каждого открытого документа будет открыто свое собственное, независимое окно подбора.

Резюме

Для того чтобы избежать заполнения всех открытых документов при подборе, следуйте простым правилам:

← На главную