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