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