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