При разработке на платформе 1С:Предприятие 8.3 часто возникает задача ограничить список документов в журнале или любой другой форме списка по определенному критерию. Это может быть фильтр по подразделению, контрагенту или специфическому статусу. В этой статье мы подробно разберем, как реализовать программную установку отбора, проанализируем различные подходы и выясним, почему иногда установленные пользователем фильтры «не видны» в отладчике.
Прежде чем переходить к коду, давайте разберем, как устроены настройки динамического списка. В основе любого списка (будь то журнал документов или справочник) лежит Система компоновки данных (СКД). Все отборы хранятся в объекте КомпоновщикНастроек, который имеет три ключевых уровня:
Рассмотрим ситуацию, когда нам нужно программно ограничить список документов по конкретному подразделению.
Этот метод считается наиболее надежным, если нам нужно гарантированно скрыть лишние данные от пользователя. Проанализируем пример кода, который добавляет новый элемент отбора в коллекцию фиксированных настроек:
ЭлементОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Подразделение");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Объект.Подразделение;
ЭлементОтбора.Использование = Истина;
В данном примере мы обращаемся к свойству Список (это стандартное имя реквизита формы с типом ДинамическийСписок). Мы создаем новый объект типа ЭлементОтбораКомпоновкиДанных, указываем путь к полю и значение. Обратите внимание, что если поле Подразделение входит в состав граф журнала, мы можем обращаться к нему напрямую по имени.
Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), мы рекомендуем использовать типовые процедуры. Это сокращает объем кода и минимизирует риск ошибок. Рассмотрим использование функции УстановитьЭлементОтбораДинамическогоСписка.
Эта функция полезна тем, что она автоматически проверяет наличие существующего отбора и заменяет его, а не плодит дубликаты. Пример вызова:
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список,
"Подразделение",
Объект.Подразделение,
ВидСравненияКомпоновкиДанных.Равно
);
Этот метод можно вызывать как в процедуре ПриСозданииНаСервере, так и при изменении каких-либо реквизитов на форме, чтобы динамически обновлять список.
Иногда использование стандартного механизма отборов может быть неоптимальным с точки зрения производительности, особенно если динамический список построен на сложном произвольном запросе. В таких случаях эффективнее использовать параметры запроса.
Разберем этот вариант по шагам. Сначала в настройках динамического списка (в конфигураторе) мы модифицируем текст запроса, добавляя условие ГДЕ:
ВЫБРАТЬ
ЖурналДокументов.Ссылка,
ЖурналДокументов.Дата,
ЖурналДокументов.Подразделение
ИЗ
ЖурналДокументов.Продажи КАК ЖурналДокументов
ГДЕ
(&ИспользоватьОтборПоПодразделению = ЛОЖЬ ИЛИ ЖурналДокументов.Подразделение = &Подразделение)
Затем в программном коде мы устанавливаем значения этих параметров:
Список.Параметры.УстановитьЗначениеПараметра("Подразделение", НужноеПодразделение);
Список.Параметры.УстановитьЗначениеПараметра("ИспользоватьОтборПоПодразделению", ЗначениеЗаполнено(НужноеПодразделение));
Этот способ позволяет гибко управлять логикой отбора на уровне SQL-запроса, что часто работает быстрее на больших объемах данных.
Часто программисты сталкиваются с тем, что пользователь установил отбор вручную, но при просмотре объекта Список.КомпоновщикНастроек.Настройки.Отбор в отладчике коллекция элементов пуста. Выясним причину этой ситуации.
Как мы уже упоминали, 1С разделяет настройки на разные уровни. Когда пользователь нажимает кнопку «Найти» или выбирает значение в списке, эти данные попадают в Пользовательские настройки. Чтобы увидеть их в отладчике, необходимо анализировать коллекцию Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.
Каждый элемент в пользовательских настройках имеет свой ИдентификаторПользовательскойНастройки. Если вы хотите программно изменить именно то поле, которое видит и может редактировать пользователь, вам нужно найти элемент именно в этой коллекции, сопоставив его по идентификатору из основной схемы компоновки.
Проанализируем вопрос обращения к полям, которые не выведены в список напрямую. Допустим, вам нужно отобрать документы по реквизиту, который есть в ссылке, но его нет в графах журнала. Вы можете использовать путь к данным вида Ссылка.ВашРеквизит.
Важный нюанс производительности: использование конструкции Ссылка.Подразделение в отборах заставляет систему выполнять неявное соединение (JOIN) таблиц. Если журнал содержит миллионы записей, это может привести к замедлению работы. По возможности старайтесь добавлять необходимые поля в состав граф журнала документов — в этом случае обращение к ним будет происходить напрямую из индексированной таблицы журнала.
Рассмотрим ситуацию, когда нам нужно открыть форму списка уже с предустановленным фильтром из другого места программы. Вместо того чтобы писать сложный код внутри самой открываемой формы, мы можем передать структуру отбора в параметрах открытия:
ПараметрыОтбора = Новый Структура("Подразделение", ВыбранноеПодразделение);
ПараметрыФормы = Новый Структура("Отбор", ПараметрыОтбора);
ОткрытьФорму("ЖурналДокументов.СкладскиеДокументы.ФормаСписка", ПараметрыФормы);
Система 1С самостоятельно проанализирует структуру Отбор и применит ее к динамическому списку при инициализации формы. Это наиболее «чистый» и правильный способ с точки зрения архитектуры платформы.
Мы рассмотрели три основных способа программной установки отбора: через фиксированные настройки, через параметры запроса и с помощью функций БСП. Выбор конкретного метода зависит от ваших задач: если нужно жестко ограничить данные — используйте ФиксированныеНастройки, если важна производительность — Параметры запроса, а для удобства и чистоты кода — типовые методы БСП или параметры открытия формы.