В конфигурациях на обычных формах, таких как Управление торговлей 10.3, часто возникает задача ограничить выбор элементов в справочнике. Например, при оформлении документов по списанию брака необходимо, чтобы пользователь мог выбрать контрагента только из определенной группы «БРАК». В этой статье мы подробно разберем несколько способов реализации такого фильтра, проанализируем возможные ошибки и выясним, какой метод наиболее эффективен.
Это классический способ перехвата стандартного действия системы. Суть заключается в том, что мы отменяем стандартное открытие формы выбора и открываем её самостоятельно, предварительно передав нужные параметры отбора. Рассмотрим этот процесс по шагам.
Для начала нам необходимо создать обработчик события НачалоВыбора для поля ввода на форме. В этом обработчике мы напишем код для настройки формы выбора. Разберем пример реализации:
Процедура КонтрагентСписанияНачалоВыбора(Элемент, СтандартнаяОбработка)
// Останавливаем стандартное открытие формы
СтандартнаяОбработка = Ложь;
// Получаем форму выбора справочника Контрагенты
// Передаем Элемент как владельца, чтобы выбранное значение вернулось в это же поле
ФормаВыбора = Справочники.Контрагенты.ПолучитьФормуВыбора(, Элемент);
// Находим нужную группу (родителя)
// Внимание: поиск по наименованию не рекомендуется, лучше использовать код или константу
НужныйРодитель = Справочники.Контрагенты.НайтиПоНаименованию("БРАК СПИСАНИЕ");
Если Не НужныйРодитель.Пустая() Тогда
// Устанавливаем отбор по родителю
// Важно: обращаемся к табличному полю СправочникСписок на форме
ФормаВыбора.Отбор.Родитель.Использование = Истина;
ФормаВыбора.Отбор.Родитель.Значение = НужныйРодитель;
ФормаВыбора.Отбор.Родитель.ВидСравнения = ВидСравнения.Равно;
КонецЕсли;
// Открываем настроенную форму
ФормаВыбора.Открыть();
КонецПроцедуры
Важный нюанс: Если вы столкнулись с ошибкой «Поле объекта не обнаружено (Родитель)», проанализируем ситуацию. В обычных формах структура может отличаться в зависимости от того, как спроектирована форма выбора. Если прямой доступ к ФормаВыбора.Отбор не срабатывает, попробуйте обратиться через элемент управления:
ФормаВыбора.ЭлементыФормы.СправочникСписок.Отбор.Родитель.Установить(НужныйРодитель);
Если нам нужно не просто «показать» элементы определенной группы, но и запретить пользователю выходить за её пределы (например, нажимать кнопку «Вверх» и выбирать других контрагентов), следует использовать свойство РодительВерхнегоУровня. Этот метод делает выбранную папку «корневой» для пользователя в момент выбора.
Рассмотрим, как это реализовать программно:
Процедура КонтрагентСписанияНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ФормаВыбора = Справочники.Контрагенты.ПолучитьФормуВыбора(, Элемент);
НужныйРодитель = Справочники.Контрагенты.НайтиПоНаименованию("БРАК СПИСАНИЕ");
Если Не НужныйРодитель.Пустая() Тогда
// Устанавливаем жесткое ограничение иерархии
ФормаВыбора.ЭлементыФормы.СправочникСписок.РодительВерхнегоУровня = НужныйРодитель;
// Отключаем возможность отключить иерархический просмотр, чтобы пользователь не увидел всё списком
ФормаВыбора.ЭлементыФормы.СправочникСписок.ИзменятьИерархическийПросмотр = Ложь;
ФормаВыбора.ЭлементыФормы.СправочникСписок.ИерархическийПросмотр = Истина;
КонецЕсли;
ФормаВыбора.Открыть();
КонецПроцедуры
Этот способ считается более надежным с точки зрения защиты от ошибок пользователя, так как он физически не сможет увидеть контрагентов из других папок.
Бывают ситуации, когда в целевой папке (например, «БРАК») есть подпапки. Если использовать простой отбор по родителю с видом сравнения Равно, программа покажет только те элементы, которые лежат непосредственно в корне папки. Чтобы увидеть всех контрагентов, включая вложенные папки, проанализируем использование вида сравнения ВИерархии.
ФормаВыбора.Отбор.Ссылка.ВидСравнения = ВидСравнения.ВИерархии;
ФормаВыбора.Отбор.Ссылка.Значение = НужныйРодитель;
ФормаВыбора.Отбор.Ссылка.Использование = Истина;
В данном случае мы фильтруем не поле Родитель, а само поле Ссылка, указывая, что ссылка должна находиться в иерархии выбранной группы.
Если количество контрагентов в группе невелико, можно вообще отказаться от открытия формы выбора справочника и предложить пользователю выпадающий список. Для этого мы предварительно выбираем нужных контрагентов запросом и загружаем их в СписокВыбора элемента формы.
// Пример заполнения списка выбора
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Родитель = &Родитель";
Запрос.УстановитьПараметр("Родитель", Справочники.Контрагенты.НайтиПоНаименованию("БРАК СПИСАНИЕ"));
Результат = Запрос.Выполнить().Выгрузить();
Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(Результат.ВыгрузитьКолонку("Ссылка"));
ЭлементыФормы.КонтрагентСписания.СписокВыбора = Список;
ЭлементыФормы.КонтрагентСписания.РежимВыбораИзСписка = Истина;
Преимущество: Это максимально быстрый способ для пользователя, так как не открывается новое окно.
Недостаток: Если контрагентов в группе сотни, такой список станет неудобным и будет долго подгружаться.
В примерах выше мы использовали метод НайтиПоНаименованию. Проанализируем, почему это считается плохой практикой в профессиональной разработке:
Как делать правильно:
НайтиПоКоду), так как коды меняются крайне редко.Подводя итог, выбор метода зависит от бизнес-задачи. Если нужно строго ограничить область видимости — используйте РодительВерхнегоУровня. Если нужно просто подсказать пользователю нужную папку, но оставить свободу действий — используйте Отбор.Родитель в событии НачалоВыбора.