Как настроить зависимые отборы между реквизитами в табличной части (Справочник и Перечисление)

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

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

Метод 1. Использование механизма «Связи параметров выбора»

Самый простой и эффективный способ, не требующий написания объемного кода — настройка свойств реквизита непосредственно в объекте метаданных. Рассмотрим ситуацию, когда у нас есть справочник КатегорииЗапросов, в котором имеется реквизит Тип. В нашей внешней обработке или документе в табличной части также присутствуют эти два поля.

Разберем по шагам, как настроить связь:

  1. Откроем свойства реквизита табличной части Категория.
  2. Найдем свойство Связи параметров выбора.
  3. Добавим новую связь: в колонке «Параметр выбора» укажем Отбор.Тип (это стандартный синтаксис отбора по реквизиту справочника), а в колонке «Элемент связи» выберем реквизит нашей табличной части Тип.

Важный нюанс: Если при такой настройке поле Тип не заполнено, платформа по умолчанию может открыть пустой список категорий. Это поведение является штатным, так как система пытается найти категории с пустым типом.

Метод 2. Программное открытие формы с фиксированными настройками

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


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

Этот способ универсален, так как позволяет использовать ВидСравненияКомпоновкиДанных.ВСписке, если категорий много и они подбираются сложным запросом на сервере.

Метод 3. Динамическое управление параметрами выбора «на лету»

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

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


&НаКлиенте
Процедура НастроитьВыборКатегории()
    ТекущаяСтрока = Элементы.Таблица.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;

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

Метод 4. Ограничение выбора для Перечислений

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

Для этого удобно использовать обработчики НачалоВыбора и АвтоПодбор. Разберем алгоритм:

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

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

Дополнительные рекомендации и оптимизация

Проанализируем ситуацию с точки зрения удобства пользователя. Если при выборе Категории однозначно определяется Тип, то пользователю вообще не нужно выбирать тип вручную. Мы можем автоматизировать это в событии ПриИзменении:


&НаКлиенте
Процедура ТаблицаКатегорияПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.Таблица.ТекущиеДанные;
    
    Если ЗначениеЗаполнено(ТекущаяСтрока.Категория) Тогда
        // Автоматически подтягиваем тип из реквизита категории
        ТекущаяСтрока.Тип = ПолучитьЗначениеРеквизитаНаСервере(ТекущаяСтрока.Категория, "Тип");
    КонецЕсли;
КонецПроцедуры

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

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

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

← На главную