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

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

При разработке документов часто возникает задача: в определенной колонке табличной части пользователь должен выбирать элементы не из всего справочника целиком, а только из строго заданной папки (группы). Например, в колонке «Обувь» должны быть доступны для выбора только позиции из группы «Обувь» справочника номенклатуры.

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

Почему не работают простые присвоения и стандартные события

Посмотрим на типичные ошибки, с которыми сталкиваются разработчики при попытке решить эту задачу:

  1. Попытка присвоения ссылки на группу в процедуре при открытии: прямое присвоение ссылки колонке (например, Колонка = Справочники.Товары.НайтиПоКоду(...)) не задает фильтрацию для выбора. Колонка таблицы — это объект метаданных или элемент управления, а не поле с отбором.
  2. Использование события ПриНачалеРедактирования или ПередНачаломИзменения: эти события срабатывают при любой активации строки или ячейки, в том числе при простой навигации клавишами со стрелками. Если открывать форму выбора в них, модальное окно будет навязчиво появляться еще до того, как пользователь решит что-то ввести.
  3. Потеря выбранного значения при модальном открытии: метод ОткрытьМодально() возвращает значение, выбранное пользователем. Если вызвать метод без присвоения переменной, форма закроется, а ячейка останется пустой.

Для переопределения стандартного окна подбора в табличном поле 1С предназначено событие НачалоВыбора. Разберем по шагам надежные варианты реализации.

Способ 1. Модальное открытие с ограничением корня через «РодительВерхнегоУровня»

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

В свойствах табличного поля назначим обработчик события НачалоВыбора. Напишем следующий код:


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

Обратите внимание на объект ДанныеСтроки. Он передается платформой в параметры процедуры НачалоВыбора и указывает непосредственно на текущую редактируемую строку, что избавляет от необходимости обращаться к свойствам табличной части через Элемент.ТекущиеДанные.

Способ 2. Немодальный выбор через владельца формы и обработчик «ОбработкаВыбора»

Если в конфигурации не рекомендуется использовать модальные окна, организуем асинхронный возврат значения. Для этого передадим элемент управления (табличное поле) в качестве владельца формы выбора, а результат примем в специализированном событии ОбработкаВыбора.

Разберем реализацию этого способа:


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

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

Способ 3. Установка отбора в списке вместо ограничения иерархии

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

Посмотрим на пример установки отбора:


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

Важные рекомендации и ограничения

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