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