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