Как правильно установить и изменить отбор в динамическом списке 1С, чтобы он не очищался?

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

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

Выясним причину проблемы: почему список становится пустым?

Рассмотрим ситуацию, описанную в теме. Разработчик использует метод Элементы.Добавить() для коллекции отбора динамического списка каждый раз, когда пользователь меняет значение реквизита на форме. В этом и кроется главная ошибка. Давайте проанализируем, что происходит в системе на логическом уровне:

  1. При открытии формы срабатывает процедура ПриСозданииНаСервере. В коллекцию отбора добавляется первый элемент: Отгружено = Ложь.
  2. Пользователь меняет галочку на форме. Срабатывает событие ПриИзменении, которое снова вызывает код добавления. В коллекции появляется второй элемент: Отгружено = Истина.
  3. Динамический список пытается выполнить запрос к базе данных, применяя оба условия одновременно. Поскольку поле не может быть одновременно и «Истина», и «Ложь», результат запроса всегда будет пустым.

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

Способ №1: Поиск и изменение существующего элемента отбора

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


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

В данном примере мы используем цикл Для Каждого, чтобы просканировать коллекцию Отбор.Элементы. Если поле найдено, мы просто обновляем его ПравоеЗначение. Это исключает дублирование условий и корректно обновляет данные в интерфейсе.

Способ №2: Использование параметров в произвольном запросе

Если ваш динамический список построен на основе произвольного запроса, профессиональнее и эффективнее использовать параметры. Это позволяет системе строить более оптимальный план запроса на уровне СУБД. Проанализируем, как изменить текст запроса динамического списка в конфигураторе:


ВЫБРАТЬ
    ДокументПродажа.Ссылка,
    ДокументПродажа.Дата,
    ДокументПродажа.Номер,
    ДокументПродажа.Отгружено
ИЗ
    Документ.Продажа КАК ДокументПродажа
ГДЕ
    (&ИспользоватьФильтр = ЛОЖЬ ИЛИ ДокументПродажа.Отгружено = &ЗначениеОтгрузки)

Теперь в коде формы нам достаточно просто устанавливать значения этих параметров, не обращаясь к сложной структуре компоновки данных:


&НаСервере
Процедура ОбновитьПараметрыСписка()
    // Устанавливаем параметры напрямую в список
    СписокДокументов.Параметры.УстановитьЗначениеПараметра("ИспользоватьФильтр", ТолькоНеОтгруженные);
    СписокДокументов.Параметры.УстановитьЗначениеПараметра("ЗначениеОтгрузки", Ложь);
КонецПроцедуры

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

Способ №3: Применение функций БСП (Библиотеки стандартных подсистем)

Если вы разрабатываете конфигурацию на базе современных типовых решений (УТ 11, БП 3.0, ERP), то в вашем распоряжении есть готовые инструменты. Разберем использование общего модуля ОбщегоНазначенияКлиентСервер. Это самый лаконичный и правильный с точки зрения стандартов разработки «1С» способ.

Вам не нужно писать циклы поиска. Достаточно одной строки кода:


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

Функция УстановитьЭлементОтбора берет на себя всю рутину по управлению коллекцией элементов компоновки данных, предотвращая появление дублей и ошибок, с которыми столкнулся автор темы.

Дополнительные рекомендации по оптимизации

Чтобы ваш динамический список работал молниеносно даже при миллионах записей, обратим внимание на следующие моменты:

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

Подведем итог: главная проблема при работе с динамическим списком — это бесконтрольное накопление элементов в коллекции Отбор. Используя поиск существующих элементов, параметры запроса или стандартные функции БСП, вы обеспечите стабильную и быструю работу интерфейса вашего приложения.

← На главную