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