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

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

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

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

Типичные ошибки при программной установке отбора

Проанализируем распространенные ошибки, которые допускаются при первой попытке установить фильтр:

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

Способ 1. Управление признаком использования существующего элемента отбора

Разберем наиболее архитектурно правильный способ работы с отборами. Вместо постоянного удаления и добавления элементов в коллекцию оптимально найти существующий элемент отбора по имени поля и управлять его свойством Использование.

Посмотрим на пример кода клиентского обработчика события изменения поля ввода:


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

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

Способ 2. Точечное удаление старого элемента перед созданием нового

Если требуется пересоздавать отбор заново, категорически не рекомендуется использовать полный метод Список.Отбор.Элементы.Очистить(), так как он сотрет не только наш отбор, но и все пользовательские фильтры, настроенные через форму «Настроить список» или стандартный поиск. Правильным решением будет удаление только конкретного элемента:


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

Способ 3. Использование стандартных процедур БСП

Если конфигурация разработана с использованием Библиотеки Стандартных Подсистем (БСП), нет необходимости вручную обходить коллекции отборов. Для этого предусмотрена готовая процедура общего модуля ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбора():


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

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

Особенности установки отбора по дате

При установке отбора по полю ДатаВхДокумента важно учитывать состав типа данных. Если реквизит содержит не только дату, но и время, простое условие с видом сравнения Равно найдет только те записи, время которых строго соответствует 00:00:00.

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

  1. Интервал дат: задаем два элемента отбора — со значением ВидСравненияКомпоновкиДанных.БольшеИлиРавно (начало дня) и ВидСравненияКомпоновкиДанных.МеньшеИлиРавно (конец дня).
  2. Реквизит типа СтандартныйПериод: размещаем на форме реквизит с типом СтандартныйПериод, что позволяет пользователю комфортно выбирать произвольные временные интервалы (день, месяц, квартал) с последующей установкой границ периода в отбор списка.

Альтернатива: использование «Быстрого доступа» без написания кода

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

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

← На главную