Как программно реализовать отбор в динамическом списке во внешней обработке?

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

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

Метод 1. Программное добавление элемента отбора в компоновщик настроек

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

Разберем по шагам логику реализации в модуле формы:

  1. Создадим обработчик события ПриИзменении для нашего реквизита на клиенте.
  2. Вызовем серверную процедуру, так как работа с настройками динамического списка требует серверного контекста.
  3. В серверной процедуре обратимся к свойству Отбор динамического списка.

Проанализируем пример кода, предложенный в ходе обсуждения:


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

КонецПроцедуры

&НаКлиенте
Процедура ДоговорПриИзменении(Элемент)
    ОбновитьОтборНаСервере();
КонецПроцедуры

Важно помнить, что при использовании Список.Отбор.Элементы.Очистить() вы удаляете абсолютно все фильтры, включая те, которые пользователь мог установить вручную через меню "Настроить список". Чтобы этого избежать, рекомендуется искать конкретное поле в цикле и обновлять только его значение, либо использовать идентификаторы пользовательских настроек.

Метод 2. Использование параметров произвольного запроса

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

Представим, что в тексте запроса динамического списка прописано условие:

ГДЕ Договор = &ПараметрДоговор

В этом случае код установки будет выглядеть гораздо лаконичнее:


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

Этот метод работает быстрее и надежнее, так как исключает ошибки, связанные с поиском элементов в коллекции отборов компоновки данных.

Метод 3. Применение фиксированных настроек

Если вы хотите, чтобы установленный программно отбор был "жестким" — то есть пользователь не мог увидеть его в стандартных настройках и, тем более, не мог его отключить или удалить, — следует использовать ФиксированныеНастройки.

Рассмотрим, как прописать это в процедуре ПриСозданииНаСервере или при изменении данных:


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

Этот подход идеален для внешних обработок, которые открываются с контекстом конкретного объекта (например, "Договоры текущего контрагента").

Метод 4. Использование функций БСП

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

В общем модуле ОбщегоНазначенияКлиентСервер существует функция УстановитьЭлементОтбораДинамическогоСписка. Рассмотрим ее применение:


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

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

Типичные ошибки и способы их оптимизации

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

Таким образом, мы рассмотрели четыре основных способа реализации отбора. Выбор конкретного метода зависит от архитектуры вашей задачи: используйте параметры для производительности, фиксированные настройки для безопасности логики и функции БСП для чистоты кода.

← На главную