Разработка и Конфигурация · 13 мин
Как программно добавить отбор в динамический список в 1С
Как программно добавить отбор в динамический список 1С: примеры кода, работа с элементами отбора, условное оформление, типичные ошибки и проверка результата.
Динамический список в управляемых формах 1С отображает данные на основе запроса, и часто возникает задача ограничить этот набор программно — например, показать документы только текущего пользователя, товары конкретной группы или записи за выбранный период. Для этого используется коллекция Список.Отбор.Элементы, куда добавляются элементы отбора с нужным видом сравнения и значением.
Работа с отбором выполняется на сервере или «без вызова сервера» в зависимости от контекста, а код обычно размещается в обработчиках ПриСозданииНаСервере, в команде формы или при изменении реквизита-фильтра. Важно понимать разницу между элементами отбора динамического списка и пользовательскими настройками: первые жёстко фиксируются кодом, вторые доступны пользователю для изменения.
Ниже разобраны основные приёмы: добавление простого отбора, группировка условий по «И/ИЛИ», работа с параметрами запроса, отключение и очистка отборов, а также типичные ошибки, из-за которых фильтр «не срабатывает» или падает с ошибкой.
Базовый способ: добавление одного элемента отбора
Минимальный код добавления отбора выглядит так: обращаемся к реквизиту формы типа «ДинамическийСписок», получаем его отбор и добавляем новый элемент. Поле, по которому фильтруем, задаётся через Новый ПолеКомпоновкиДанных("ИмяПоля") — имя должно точно совпадать с полем запроса динамического списка.
&НаСервере
Процедура УстановитьОтборПоОрганизации(Организация)
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Организация;
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецПроцедуры
Свойство РежимОтображения = Недоступный скрывает отбор от пользователя: он не сможет случайно отключить его через «Ещё → Настроить список». Если фильтр должен быть видимым, но защищённым от редактирования, используют режим Обычный, а полностью пользовательский отбор добавляют уже не в Список.Отбор, а в пользовательские настройки.
Типичное место вызова — обработчик ПриСозданииНаСервере, когда отбор нужен сразу при открытии формы. Если условие зависит от выбора пользователя (например, поле «Период» на форме), код выносится в отдельную процедуру и вызывается из обработчика ПриИзменении соответствующего реквизита.
Виды сравнения и типы значений
От выбора вида сравнения зависит, как платформа построит условие в итоговом запросе. Наиболее используемые варианты: Равно, НеРавно, ВСписке, ВИерархии, Содержит, БольшеИлиРавно, Заполнено. Для ВСписке правое значение должно быть списком значений или массивом, для Содержит — строкой.
| Вид сравнения | Тип правого значения | Типичный сценарий |
|---|---|---|
| Равно | Ссылка, число, дата, строка | Фильтр по конкретному документу, контрагенту, организации |
| ВСписке | СписокЗначений или массив | Несколько складов, статусов, видов документов |
| ВИерархии | Ссылка на группу | Товары выбранной группы номенклатуры со всеми подгруппами |
| Содержит | Строка | Поиск по подстроке в наименовании |
| БольшеИлиРавно / Меньше | Дата, число | Документы за период, суммы сверх порога |
| Заполнено / НеЗаполнено | Не требуется | Только записи с указанным ответственным |
Частая причина «молчащего» отбора — несовпадение типов. Если поле в запросе имеет составной тип (например, «Хозрасчётный» или документ нескольких видов), а в правое значение передана ссылка несовместимого типа, условие может отработать без ошибки, но не вернуть ни одной строки. Перед отладкой полезно проверить тип поля в схеме запроса динамического списка.
Группы условий: И, ИЛИ и НЕ
Когда одного условия недостаточно, элементы объединяются в группы. Группа создаётся добавлением элемента типа ГруппаЭлементовОтбораКомпоновкиДанных с указанием ТипГруппы: ГруппаИ, ГруппаИли или ГруппаНе. Дочерние условия добавляются уже в коллекцию Элементы самой группы, а не списка.
&НаСервере
Процедура УстановитьСложныйОтбор()
ГруппаИли = Список.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИли.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
ГруппаИли.Использование = Истина;
Условие1 = ГруппаИли.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Условие1.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Статус");
Условие1.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Условие1.ПравоеЗначение = Перечисления.СтатусыЗаказов.Новый;
Условие1.Использование = Истина;
Условие2 = ГруппаИли.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Условие2.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Статус");
Условие2.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Условие2.ПравоеЗначение = Перечисления.СтатусыЗаказов.ВРаботе;
Условие2.Использование = Истина;
КонецПроцедуры
Элементы, добавленные на верхний уровень Список.Отбор.Элементы, по умолчанию объединяются по «И». Поэтому комбинация «условие А И (условие Б ИЛИ условие В)» реализуется так: условие А добавляется в корень, а Б и В — внутрь вложенной группы «ИЛИ». Вложенность групп не ограничена, но глубокие конструкции сложно отлаживать — в таких случаях часто проще перенести логику в текст запроса динамического списка.
Отбор через параметры запроса динамического списка
Альтернатива элементам отбора — параметры в тексте запроса самого динамического списка. Если запрос содержит конструкцию ГДЕ Документ.Организация = &Организация, значение задаётся через Список.Параметры.УстановитьЗначениеПараметра("Организация", Значение). Такой способ работает быстрее на больших таблицах и не виден пользователю в настройках списка.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.УстановитьЗначениеПараметра("ТекущаяОрганизация", ТекущаяОрганизация());
Список.Параметры.УстановитьЗначениеПараметра("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));
КонецПроцедуры
У параметрического способа есть ограничение: условие жёстко зашито в текст запроса, и отключить его без изменения запроса нельзя. Компромисс — конструкция ГДЕ (&ОтборПоОрганизации = ЛОЖЬ ИЛИ Организация = &Организация), где флаг-параметр включает и выключает фильтрацию. Это удобно, когда один и тот же список должен работать в режимах «все данные» и «только мои».
Сравнение вариантов
Гибко: условия добавляются, отключаются и группируются кодом без изменения запроса. Минус — видны в настройках списка, если не скрыть режимом отображения.
Быстро и надёжно, условие нельзя случайно снять пользователю. Минус — логика фиксируется в тексте запроса, динамическое включение требует флаговых параметров.
Максимальная гибкость для сложной логики и соединений. Минус — теряется часть стандартных возможностей динамического списка, всё поддерживается вручную.
Изменение, отключение и очистка отборов
При повторном вызове процедуры установки отбора элементы накапливаются: каждый вызов Добавить() создаёт новый элемент, и старые условия продолжают действовать. Перед установкой нового значения фильтр нужно очистить или найти существующий элемент и обновить его. Самый простой вариант — полная очистка коллекции, если все отборы управляются кодом.
&НаКлиенте
Процедура ОрганизацияОтборПриИзменении(Элемент)
УстановитьОтборПоОрганизации(ОрганизацияОтбор);
КонецПроцедуры
&НаСервере
Процедура УстановитьОтборПоОрганизации(Организация)
// Удаляем ранее добавленные элементы отбора по этому полю
ПолеОрганизация = Новый ПолеКомпоновкиДанных("Организация");
КоличествоЭлементов = Список.Отбор.Элементы.Количество();
Для Индекс = 1 По КоличествоЭлементов Цикл
ЭлементОтбора = Список.Отбор.Элементы[КоличествоЭлементов - Индекс];
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
И ЭлементОтбора.ЛевоеЗначение = ПолеОрганизация Тогда
Список.Отбор.Элементы.Удалить(ЭлементОтбора);
КонецЕсли;
КонецЦикла;
// Пустое значение — отбор не нужен
Если Не ЗначениеЗаполнено(Организация) Тогда
Возврат;
КонецЕсли;
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = ПолеОрганизация;
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Организация;
ЭлементОтбора.Использование = Истина;
КонецПроцедуры
Обход коллекции выполняется с конца, потому что удаление элемента сдвигает индексы остальных. Альтернатива — присвоить элементу отбора уникальное представление или идентификатор пользовательской настройки при создании и потом искать его по этому признаку. Временно отключить условие без удаления можно, установив Использование = Ложь: элемент сохранится и включится обратно одной строкой.
- 1Определите имя поля запроса динамического списка, по которому нужен фильтр
- 2Выберите способ: элемент отбора или параметр запроса
- 3Напишите процедуру установки отбора с очисткой предыдущих элементов
- 4Вызовите её из ПриСозданииНаСервере или обработчика изменения реквизита
- 5Проверьте список: записи фильтруются, отбор не дублируется при повторном вызове
Проверка результата и типичные ошибки
После установки отбора результат проверяется визуально — список обновляется автоматически, перезапускать форму не нужно. Если данные не изменились, первым делом откройте «Ещё → Настроить список» и посмотрите, появился ли элемент отбора и стоит ли у него флаг использования. Отсутствие элемента означает, что код не выполнился или отбор добавлен в другой реквизит формы.
Ошибка вида «Поле не найдено» при обращении к списку говорит о том, что имя в ПолеКомпоновкиДанных не совпадает с полем запроса — проверьте регистр и псевдонимы. Если отбор добавлен, но строк больше или меньше ожидаемого, проверьте вид сравнения: например, ВИерархии для поля, не являющегося иерархическим справочником, или Содержит с учётом регистра в разных СУБД.
Ещё одна ловушка — пользовательские настройки. Если форма сохраняет настройки списка, при следующем открытии пользовательский отбор может перекрыть программный или наоборот. Для отборов, которые должны действовать всегда, используйте РежимОтображения = Недоступный и устанавливайте их при каждом создании формы, а не полагайтесь на сохранённое состояние.
Как проверить результат
Элемент присутствует, флаг использования установлен, значение корректное
Элемента нет или он выключен — код не выполнился или сработала очистка
Показываются только записи, удовлетворяющие условию
Лишние строки (отбор не применился) или пустой список (условие слишком жёсткое)
Количество элементов отбора не растёт, фильтр обновляется
Элементы дублируются, список постепенно пустеет
FAQ
Можно ли добавить отбор в динамический список на клиенте без вызова сервера?
Да, если код находится в контексте формы и работает с реквизитом списка напрямую — коллекция отборов доступна и на клиенте в тонком клиенте. Директива &НаКлиенте допустима, но на практике установку отборов чаще выносят на сервер или используют &НаКлиентеНаСервереБезКонтекста, чтобы единая процедура вызывалась из любых обработчиков.
Как задать отбор по периоду для списка документов?
У динамического списка документов есть стандартное свойство периода, но программно проще добавить два элемента отбора по полю «Дата»: одно с видом сравнения БольшеИлиРавно и датой начала, второе — МеньшеИлиРавно с концом дня даты окончания. Оба элемента объединяются по «И» автоматически, так как добавляются на верхний уровень.
Почему отбор по полю, которого нет в запросе, вызывает ошибку?
Динамический список строит схему компоновки по своему запросу, и отбирать можно только по полям, доступным в этой схеме. Если нужного поля нет, добавьте его в текст запроса списка (достаточно перечислить в выборке) — после этого оно станет доступно для отбора и сортировки.
Как сделать отбор, который пользователь не сможет отключить?
Установите элементу отбора РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный — он не появится в диалоге настройки списка. Ещё надёжнее перенести условие в текст запроса динамического списка с параметром: пользовательские настройки на такой фильтр не влияют.
Чем отличается Список.Отбор от пользовательских настроек списка?
Список.Отбор — фиксированные условия, задаваемые разработчиком; они применяются всегда и не зависят от сохранённых настроек. Пользовательские настройки хранятся отдельно, могут сохраняться между сеансами и изменяться пользователем. При конфликте оба набора условий применяются вместе через «И», поэтому дублировать один и тот же фильтр в обоих местах не нужно.
Как отладить, какой именно запрос выполняет динамический список с отбором?
Используйте консоль компоновки данных или включите технологический журнал с событием DBMSSQL/DBPOSTGRS, чтобы увидеть итоговый SQL-запрос. Также помогает временно вывести в сообщение представление отбора через строковое представление настроек компоновки — так видно, какие условия реально дошли до СКД.
Что важно запомнить
Отбор добавляется в Список.Отбор.Элементы с указанием поля, вида сравнения и значения, либо через параметры запроса списка для жёстких условий. Перед повторной установкой очищайте старые элементы, проверяйте имена полей и типы значений, а защищённые от пользователя фильтры помечайте режимом отображения «Недоступный».