Как программно отключить или удалить элемент отбора в динамическом списке 1С?

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

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

Почему не работает метод Найти() для отбора динамического списка

Рассмотрим, с чем именно связана проблема. Обращаясь к свойству Список.Отбор.Элементы, мы работаем с объектом типа КоллекцияЭлементовОтбораКомпоновкиДанных. Проанализируем синтаксис-помощник: у этой коллекции есть методы Добавить, Вставить, Удалить, Очистить, Количество и Получить, но метода Найти() или НайтиСтроки() у нее нет. Точно так же его нет и у самого свойства Список.Отбор.

Из-за отсутствия встроенной функции поиска получить прямую ссылку на ранее созданный элемент отбора из другой процедуры стандартным методом поиска по значению невозможно. Единственный штатный механизм платформы без использования сторонних библиотек — это обход элементов коллекции в цикле с проверкой свойств каждого элемента.

Способ 1. Поиск и отключение элемента отбора перебором коллекции

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

Посмотрим на пример кода, отключающего отбор по полю Ссылка:


ПолеОтбора = Новый ПолеКомпоновкиДанных("Ссылка");

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

В этом примере мы не удаляем элемент физически, а просто снимаем флаг Использование. Это наиболее предпочтительный и производительный вариант: в дальнейшем, если отбор снова понадобится включить, достаточно будет вернуть свойству значение Истина и при необходимости обновить ПравоеЗначение.

Способ 2. Корректное удаление элемента отбора из коллекции

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

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


ПолеОтбора = Новый ПолеКомпоновкиДанных("Ссылка");

Для Индекс = Список.Отбор.Элементы.Количество() - 1 По 0 Цикл
    Элемент = Список.Отбор.Элементы[Индекс];
    
    Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") 
        И Элемент.ЛевоеЗначение = ПолеОтбора Тогда
        
        Список.Отбор.Элементы.Удалить(Элемент);
    КонецЕсли;
КонецЦикла;

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

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

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

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


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

Если необходимо адресно изменить отбор в конкретной группе или в фиксированных настройках, можно использовать родственную процедуру:


ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбора(
    Список.Отбор, 
    "Ссылка", 
    , 
    , 
    , 
    Ложь
);

Типовые процедуры БСП автоматически обходят коллекцию, проверяют типы элементов и меняют параметры нужного отбора без написания громоздких циклов.

Рекомендации для надежной работы с отборами

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

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