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