Как программно изменить отбор в динамическом списке 1С

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

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

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

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

Для начала проанализируем текст запроса динамического списка. Мы можем добавить условие ГДЕ, которое будет гибко реагировать на наши параметры:


ВЫБРАТЬ
    Долги.ДокументОснование КАК ДокументОснование,
    Долги.Организация КАК Организация,
    Долги.Контрагент КАК Контрагент,
    Долги.Договор КАК Договор,
    Долги.СуммаОстаток КАК СуммаОстаток
ИЗ
    РегистрНакопления.ДолгиПокупателейПоДокументах.Остатки(&Период, 
        Организация = &Организация И Контрагент = &Контрагент) КАК Долги
ГДЕ
    ВЫБОР 
        КОГДА &ОтборПоДоговору ТОГДА Долги.Договор = &Договор 
        ИНАЧЕ ИСТИНА 
    КОНЕЦ

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


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

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

Способ 2: Управление через Компоновщик настроек

Этот метод считается более гибким, так как он не требует изменения текста запроса и позволяет динамически добавлять или удалять поля отбора. Рассмотрим работу с объектом Список.Отбор.

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


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

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

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

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

Разберем по шагам, как это выглядит в коде:


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

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

Сложные условия: Группы И / ИЛИ

Иногда требуется реализовать более сложную логику, например: «Показать документы, где Ответственный равен Текущему Пользователю ИЛИ Сумма документа больше 100 000». В этом случае простым элементом отбора не обойтись. Рассмотрим использование групп.

Проанализируем пример создания группы:


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

Рекомендации по производительности и обновлению

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

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

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

← На главную