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