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