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