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

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

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

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

Суть проблемы и анализ ситуации

Рассмотрим типичный сценарий: на форме документа или обработки есть динамический список (например, Заказы) и поле выбора (например, Контрагент). Мы хотим, чтобы при выборе контрагента список заказов автоматически фильтровался по нему. Код в обработчике события ПриИзменении выглядит следующим образом:


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

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

Решение №1: Метод «Удаление и повторная установка»

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

Проанализируем исправленный код:


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

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

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

Решение №2: Использование идентификатора отбора

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

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


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

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

Решение №3: Альтернатива через параметры запроса

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

Разберем пример реализации через параметры:

  1. В тексте запроса динамического списка укажите условие: ГДЕ Контрагент = &ВыбранныйКонтрагент.
  2. В коде формы используйте установку значения параметра:

Список.Параметры.УстановитьЗначениеПараметра("ВыбранныйКонтрагент", Объект.Контрагент);

Этот способ работает максимально быстро, так как 1С не нужно анализировать дерево компоновки данных — значение просто подставляется в SQL-запрос. Однако помните, что в этом случае пользователь не увидит этот отбор в стандартном окне настроек списка.

Важные нюансы работы с режимами отображения

При программной установке отбора критически важно обращать внимание на параметр РежимОтображения. В исходном вопросе использовался РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ.

Рассмотрим особенности режимов:

Итоги и рекомендации

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

Во-первых, если вы используете функции БСП, старайтесь всегда проверять, не остались ли старые настройки в памяти формы. Метод «Удалить и создать» является наиболее универсальным «костылем», который спасает в 99% случаев.

Во-вторых, если ваша версия БСП позволяет, всегда используйте текстовый Идентификатор для программных отборов. Это делает ваш код более предсказуемым и защищает от дублирования строк в настройках отбора.

В-третьих, помните о производительности. Для простых списков отбор через КомпоновкаДанных — это норма. Для огромных таблиц с миллионами записей и сложной иерархией лучше использовать параметры запроса (Список.Параметры).

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

← На главную