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