Как правильно реализовать подбор номенклатуры и работу события ОбработкаВыбора() в 1С?

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

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

Разберем механизм взаимодействия форм

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

  1. Назначение владельца: При открытии формы подбора система должна знать, куда возвращать результат. Владельцем может выступать либо сама основная форма, либо конкретный элемент управления (например, табличное поле).
  2. Немодальный режим: Это критически важный момент. Если вы используете метод ОткрытьМодально(), то событие ОбработкаВыбора не вызывается. Вместо этого результат выбора возвращается функцией открытия. Для полноценного подбора, который не блокирует интерфейс и позволяет выбирать несколько позиций, нужно использовать метод Открыть().
  3. Вызов оповещения: В самой форме подбора должен быть вызван метод ОповеститьОВыборе().

Шаг 1: Вызов формы подбора из документа

Проанализируем ситуацию, когда нам нужно открыть форму подбора из командной панели табличной части. Для этого мы должны использовать метод ПолучитьФорму(), передав в него текущую форму в качестве владельца.

Рассмотрим пример кода в модуле формы документа:


Процедура КоманднаяПанельТоварыПодбор(Кнопка)
    // Получаем форму подбора, указывая Владельцем "ЭтаФорма"
    ФормаПодбора = ПолучитьФорму("Справочник.Номенклатура.ФормаВыбора", ЭтаФорма);
    
    // Если нужно, чтобы форма не закрывалась после одного выбора
    ФормаПодбора.ЗакрыватьПриВыборе = Ложь;
    
    // Открываем форму в немодальном режиме
    ФормаПодбора.Открыть();
КонецПроцедуры

Обратите внимание: если вы укажете владельцем не ЭтаФорма, а ЭлементыФормы.Товары (табличное поле), то событие выбора сначала будет искаться в обработчиках этого табличного поля.

Шаг 2: Реализация выбора в форме подбора

Теперь перейдем к коду в форме, которую мы открыли. Допустим, у нас есть табличное поле со списком номенклатуры. Нам нужно перехватить стандартную обработку выбора и передать данные обратно в документ.

Разберем пример кода в форме подбора:


Процедура ТабличноеПолеСписокВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
    // Если пользователь выбрал группу, ничего не делаем или открываем её
    Если ВыбраннаяСтрока.ЭтоГруппа Тогда
        Возврат;
    КонецЕсли;

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

    // Отправляем данные владельцу
    ОповеститьОВыборе(ПараметрыВыбора);
КонецПроцедуры

Использование метода ОповеститьОВыборе() посылает сигнал владельцу формы, и именно в этот момент в основной форме «просыпается» событие ОбработкаВыбора.

Шаг 3: Обработка результата в основном документе

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

Важно убедиться, что процедура ОбработкаВыбора назначена в свойствах формы на вкладке «События».


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

Важный нюанс: Если в ОбработкаВыбора параметр СтандартнаяОбработка установлен в значение Истина, система может попытаться выполнить действие по умолчанию (например, заполнить поле, которое инициировало выбор). Если вы делаете сложный подбор, лучше устанавливать СтандартнаяОбработка = Ложь.

Передача параметров в форму подбора (например, Контрагента)

Часто возникает вопрос: как передать данные из документа в подбор, чтобы, например, отфильтровать товары по остаткам на определенном складе или по ценам для конкретного контрагента? Выясним, как это сделать наиболее эффективно.

Рассмотрим два способа:

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

Почему модальность — это проблема?

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


Результат = ФормаПодбора.ОткрытьМодально();
Если Результат <> Неопределено Тогда
    // Обрабатываем результат здесь, а не в ОбработкаВыбора
КонецЕсли;

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

Итоги

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

← На главную