Как ограничить выбор номенклатуры конкретной группой и всеми её подгруппами в 1С

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

При разработке в среде 1С часто возникает задача сузить круг доступных для выбора элементов справочника. Например, в документе ДефектныйТранспорт логично разрешить выбор только той номенклатуры, которая относится к категории техники. Однако стандартные механизмы отбора иногда вызывают трудности у начинающих разработчиков, особенно когда нужно включить не только саму группу, но и все вложенные в неё подпапки. В этой статье мы подробно разберем, как правильно реализовать такой отбор, избежав распространенных ошибок.

Почему стандартный отбор через структуру не подходит

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


ЗначениеОтбора = Новый Структура("Родитель", "Дефектная техника");
ПараметрыВыбора = Новый Структура("Отбор", ЗначениеОтбора);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыВыбора);

Выясним причины, по которым данный код работает некорректно:

  1. Несоответствие типов данных: В поле Родитель передается строка "Дефектная техника", в то время как система ожидает Ссылку на элемент справочника. 1С не умеет автоматически сопоставлять текст с объектом базы данных в таких условиях.
  2. Ограничение по иерархии: Отбор по полю Родитель через структуру работает только на строгое равенство. Это значит, что вы увидите элементы, находящиеся непосредственно в этой папке, но не увидите товары из вложенных подгрупп.
  3. Вид сравнения: Стандартный отбор в структуре всегда использует равенство (или "В списке", если передать массив). Для захвата всей иерархии нам необходим вид сравнения ВИерархии.

Способ 1: Программная установка отбора через ФиксированныеНастройки

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

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


&НаКлиенте
Процедура НоменклатураНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // Отменяем стандартное поведение системы, чтобы открыть форму с нашими настройками
    СтандартнаяОбработка = Ложь; 
    
    // Получаем ссылку на группу на сервере
    ГруппаДляОтбора = ПолучитьСсылкуНаГруппуДефектнойТехники();
    
    Если ГруппаДляОтбора.Пустая() Тогда
        Сообщить("Группа 'Дефектная техника' не найдена в справочнике!");
        Возврат;
    КонецЕсли;

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

&НаСервереБезКонтекста
Функция ПолучитьСсылкуНаГруппуДефектнойТехники()
    // В реальных задачах лучше использовать Предопределенные значения или константы
    Возврат Справочники.Номенклатура.НайтиПоНаименованию("Дефектная техника");
КонецФункции

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

Способ 2: Настройка отбора в самой форме выбора

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


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

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

Важные замечания по типам данных и контексту

Разберем типичную ошибку, возникающую при проверке модуля: "Переменная не определена (Справочники)". Посмотрим на причину: объект Справочники (менеджер справочников) доступен только на стороне сервера. Если вы пытаетесь написать Справочники.Номенклатура... внутри процедуры с директивой &НаКлиенте, система выдаст ошибку.

Помните:

Настройка через свойства реквизита (без кода)

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

Если вы добавите в Параметры выбора условие Отбор.Родитель(ГруппаДефектнаяТехника), система применит фильтр. Но, как мы выяснили ранее, стандартный параметр Отбор.Родитель в свойствах работает только для первого уровня вложенности. Для полноценной работы с подгруппами (иерархией) программный метод с использованием ВидСравненияКомпоновкиДанных.ВИерархии является единственным надежным решением.

Рассмотренные подходы позволят вам эффективно управлять формами выбора в 1С, обеспечивая пользователям удобство работы и минимизируя риск ввода некорректных данных в документы.

← На главную