Почему не работает программный отбор в динамическом списке 1С и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При программной настройке динамических списков на управляемых формах 1С разработчики часто сталкиваются с ситуацией, когда код добавления отбора выполняется без ошибок, элемент появляется в окне настройки отбора (в режиме «1С:Предприятие»), однако сами данные в списке не фильтруются. Фильтрация начинает работать только после того, как пользователь вручную откроет настройки отбора и нажмет кнопку «ОК».

В этой статье мы разберем причину такого поведения, проанализируем устройство настроек компоновки данных и рассмотрим правильные способы программного наложения отборов.

Выясняем причину проблемы

Начиная с платформы 8.3.5 и обновлений Библиотеки Стандартных Подсистем (БСП), изменился механизм работы с динамическими списками. Динамический список построена на базе системы компоновки данных (СКД) и имеет трехуровневую структуру настроек:

  1. Фиксированные настройки (КомпоновщикНастроек.ФиксированныеНастройки) — жестко заданные настройки, которые пользователь не может изменить в форме.
  2. Основные настройки (КомпоновщикНастроек.Настройки) — базовые настройки списка, определенные разработчиком или системой по умолчанию.
  3. Пользовательские настройки (КомпоновщикНастроек.ПользовательскиеНастройки) — варианты отборов, группировок и сортировок, доступные пользователю прямо на форме (например, элементы быстрых отборов). Пользовательские настройки имеют высший приоритет над основными настройками.

Если программно добавить отбор напрямую в свойство Список.Отбор без учета режимa отображения и синхронизации с пользовательскими настройками, платформа «перекрывает» добавленный отбор ранее сохраненной пользовательской настройкой. В результате отбор числится в структуре, но физически к запросу списка не применяется.

Способ 1. Использование функции БСП

В типовых конфигурациях 1С (УТ 11, БП 3.0, ERP, КА и др.) предусмотрены готовые клиент-серверные процедуры для безопасной работы с отборами динамических списков. Самый простой и надежный вариант — использовать процедуру общего модуля:


ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
    Список,
    "Проведен",
    Истина,
    ВидСравненияКомпоновкиДанных.Равно
);

Эта процедура автоматически определяет, куда именно поместить отбор — в фиксированные настройки или пользовательские, а также корректно связывает идентификаторы настроек.

Способ 2. Самостоятельная реализация алгоритма установки отбора

Если вы работаете в нетиповой конфигурации или старой версии БСП, разберем по шагам, как написать правильную процедуру установки отбора на сервере.

Проанализируем ключевые этапы алгоритма:

  1. Определение целевой коллекции: Если элемент отбора не должен быть доступен пользователю для редактирования (режим Недоступный), мы добавляем его в ФиксированныеНастройки.Отбор. Во всех остальных случаях элемент добавляется в Настройки.Отбор.
  2. Заполнение свойств элемента: Задаем ЛевоеЗначение с помощью объекта ПолеКомпоновкиДанных, устанавливаем ВидСравнения и ПравоеЗначение.
  3. Установка пользовательских настроек: Важно! Свойство ИдентификаторПользовательскойНастройки необходимо заполнять в самом конце, после полного формирования элемента отбора. Если задать его раньше, платформа скопирует не полностью заполненный элемент в пользовательские настройки.

Рассмотрим полный пример кода установки отбора:


Процедура УстановитьЭлементОтбораДинамическогоСписка(ДинамическийСписок, ИмяПоля,
    ПравоеЗначение = Неопределено,
    ВидСравнения = Неопределено,
    Представление = Неопределено,
    Использование = Неопределено,
    РежимОтображения = Неопределено,
    ИдентификаторПользовательскойНастройки = Неопределено) Экспорт
    
    Если РежимОтображения = Неопределено Тогда
        РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
    КонецЕсли;
    
    Если РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный Тогда
        ОтборДинамическогоСписка = ДинамическийСписок.КомпоновщикНастроек.ФиксированныеНастройки.Отбор;
    Иначе
        ОтборДинамическогоСписка = ДинамическийСписок.КомпоновщикНастроек.Настройки.Отбор;
    КонецЕсли;
    
    // Ищем существующий элемент или добавляем новый
    ПолеКомпоновки = Новый ПолеКомпоновкиДанных(ИмяПоля);
    ЭлементОтбора = Неопределено;
    
    Для Каждого Элемент Из ОтборДинамическогоСписка.Элементы Цикл
        Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") 
            И Элемент.ЛевоеЗначение = ПолеКомпоновки Тогда
            ЭлементОтбора = Элемент;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ЭлементОтбора = Неопределено Тогда
        ЭлементОтбора = ОтборДинамическогоСписка.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    КонецЕсли;
    
    ЭлементОтбора.ЛевоеЗначение = ПолеКомпоновки;
    
    Если ВидСравнения <> Неопределено Тогда
        ЭлементОтбора.ВидСравнения = ВидСравнения;
    Иначе
        ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    КонецЕсли;
    
    ЭлементОтбора.ПравоеЗначение = ПравоеЗначение;
    ЭлементОтбора.РежимОтображения = РежимОтображения;
    
    Если Представление <> Неопределено Тогда
        ЭлементОтбора.Представление = Представление;
    КонецЕсли;
    
    Если Использование <> Неопределено Тогда
        ЭлементОтбора.Использование = Использование;
    Иначе
        ЭлементОтбора.Использование = Истина;
    КонецЕсли;
    
    // Установка идентификатора выполняется в самом конце!
    Если ИдентификаторПользовательскойНастройки <> Неопределено Тогда
        ЭлементОтбора.ИдентификаторПользовательскойНастройки = ИдентификаторПользовательскойНастройки;
    ИначеЕсли ЭлементОтбора.РежимОтображения <> РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный Тогда
        ЭлементОтбора.ИдентификаторПользовательскойНастройки = ИмяПоля;
    КонецЕсли;
    
КонецПроцедуры

Особенности работы с типом «Булево» и значениями NULL

Если вы устанавливаете отбор по логическому полю (например, поиск строк, где флаг снят: ПравоеЗначение = Ложь), обратите внимание на запрос самого динамического списка. В случаях, когда таблица содержит левые соединения (LEFT JOIN), значение поля для незаполненных записей может иметь тип NULL.

Отбор с условием Поле = Ложь не вернет записи со значением NULL. Чтобы решить эту проблему, оберните поле в запросе динамического списка функцией ЕСТЬНУЛЛ(Таблица.Поле, ЛОЖЬ).

← На главную