Как реализовать подбор элементов справочника в список на обычной форме в 1С 8.2 / 8.3?

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

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

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

Выясняем причины: почему не работает событие ОбработкаВыбора?

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


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

Процедура ОбработкаВыбора(ЗначениеВыбора, Источник) 
    Сообщить(ЗначениеВыбора);
КонецПроцедуры

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

Решение проблемы 1: Установка владельца формы

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

Вторым параметром методов получения формы передается владелец. Если мы хотим, чтобы результат вернулся в текущую форму внешней обработки, мы обязаны передать туда контекст ЭтаФорма. Разберем правильный вариант вызова:


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

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

Решение проблемы 2: Физическая привязка обработчика к событию формы

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

Давайте по шагам разберем, как правильно привязать процедуру в конфигураторе:

  1. Откроем форму нашей внешней обработки в режиме конфигуратора.
  2. Перейдем в свойства самой формы (кликнув на пустом месте формы и нажав клавишу F4).
  3. В открывшейся палитре свойств перейдем на вкладку События.
  4. Найдем в списке событие ОбработкаВыбора.
  5. Нажмем на кнопку с лупой или выберем из выпадающего списка уже созданную нами процедуру ОбработкаВыбора.

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

Реализация множественного подбора элементов

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

Рассмотрим пример кода для кнопки открытия формы подбора подразделений:


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

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


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

Использование свойства РежимВыбора для произвольных форм

Иногда требуется открыть не стандартную форму выбора, а обычную форму списка или какую-то кастомную форму справочника. Если вы просто откроете форму списка методом ПолучитьФорму("ФормаСписка"), то при двойном клике система попытается открыть карточку элемента на редактирование, а не выбрать его.

Чтобы любая форма списка вела себя как форма выбора, обязательно устанавливайте свойство РежимВыбора в значение Истина перед открытием:


Форма = Справочники.ПодразделенияОрганизаций.ПолучитьФорму("ФормаСписка", ЭтаФорма);
Форма.РежимВыбора = Истина;
Форма.Открыть();

Программная установка отборов в форме выбора

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

В обычных формах отборы накладываются непосредственно на динамический список формы выбора, который по умолчанию имеет имя СправочникСписок. Посмотрим на пример установки отбора:


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

Альтернативный метод: Использование функции ОткрытьПодбор

В платформе 1С для обычного приложения существует специализированный метод ОткрытьПодбор, который позволяет решить эту задачу лаконичнее. Этот метод автоматически связывает форму выбора с формой-владельцем.

Пример использования данного метода:


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

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


Процедура ОбработкаПодбора(ЗначениеВыбора, Источник)
    // Обрабатываем полученный элемент
    Если СписокПодразделений.НайтиПоЗначению(ЗначениеВыбора) = Неопределено Тогда
        СписокПодразделений.Добавить(ЗначениеВыбора);
    КонецЕсли;
КонецПроцедуры

Коротко о разнице с управляемыми формами

Если в будущем вам потребуется перенести эту логику на управляемые формы (например, при переходе на новые редакции конфигураций), помните следующие ключевые отличия:

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

← На главную