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