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