Как реализовать отбор по периоду для произвольного реквизита в форме списка 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача предоставить пользователю возможность фильтровать данные в списке по определенному временному интервалу. Если со стандартным реквизитом Дата проблем обычно не возникает (платформа предоставляет встроенную кнопку «Установить период»), то для дополнительных реквизитов, таких как ДатаПросрочки, ДатаОтгрузки или ДатаРегистрации, требуется ручная настройка. Разберем подробно, как реализовать удобный отбор по периоду, используя различные подходы: от визуального конструирования до программного управления отборами.

Метод 1. Настройка отбора через пользовательские настройки (без программирования)

Самый простой и быстрый способ, который позволяет вывести поле периода прямо в «шапку» формы списка, — это использование механизма пользовательских настроек динамического списка. Рассмотрим этот процесс по шагам:

  1. Откроем конфигуратор и перейдем в форму списка нужного документа или справочника.
  2. Выберем основной реквизит формы — Список (тип ДинамическийСписок).
  3. В окне свойств нажмем на ссылку «Настройка списка».
  4. В открывшемся конструкторе перейдем на вкладку «Отбор».
  5. Найдем в левой колонке наш реквизит ДатаПросрочки и перенесем его в правую колонку.
  6. Теперь самое важное: нажмем кнопку «Свойства пользовательских настроек» (иконка с изображением ключа в нижней части окна).
  7. В появившемся диалоге установим флажок «Включать в пользовательские настройки».
  8. В поле «Режим отображения» выберем значение «Быстрый доступ».

После этих манипуляций в верхней части формы списка появится поле для ввода даты. Однако у этого метода есть нюанс: по умолчанию платформа предложит выбор конкретной даты, а не периода. Чтобы пользователь мог выбирать именно интервал (с... по...), часто требуется программное вмешательство, которое мы рассмотрим ниже.

Метод 2. Использование реквизита типа «СтандартныйПериод»

Проанализируем ситуацию: пользователю удобнее всего работать с единым полем, которое при нажатии открывает стандартный календарь 1С с выбором периодов (вчера, этот квартал, прошлый месяц и т.д.). Для этого мы можем создать на форме вспомогательный реквизит.

Рассмотрим алгоритм реализации:

  1. Создадим в форме новый реквизит (не в динамическом списке, а просто в форме), назовем его ПериодПросрочки.
  2. Установим ему тип данных СтандартныйПериод.
  3. Вытащим этот реквизит на форму, расположив его над списком.
  4. Для этого элемента формы создадим событие ПриИзменении.

Теперь нам необходимо написать код, который будет транслировать выбранный период в отбор динамического списка. Посмотрим на пример реализации в модуле формы:


&НаКлиенте
Процедура ПериодПросрочкиПриИзменении(Элемент)
    
    // Вызываем серверную процедуру для обновления отбора
    УстановитьОтборПоПериодуНаСервере();
    
КонецПроцедуры

&НаСервере
Процедура УстановитьОтборПоПериодуНаСервере()
    
    // Определяем имя поля, по которому будем фильтровать
    ИмяПоляОтбора = "ДатаПросрочки";
    ПолеОтбора = Новый ПолеКомпоновкиДанных(ИмяПоляОтбора);
    
    // Ищем существующий отбор по этому полю в динамическом списке
    ЭлементОтбора = Неопределено;
    Для Каждого Элемент Из Список.Отбор.Элементы Цикл
        Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") 
            И Элемент.ЛевоеЗначение = ПолеОтбора Тогда
            ЭлементОтбора = Элемент;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // Если отбор не найден, создаем новый
    Если ЭлементОтбора = Неопределено Тогда
        ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение = ПолеОтбора;
    КонецЕсли;
    
    // Настраиваем параметры отбора
    ЭлементОтбора.Использование = ЗначениеЗаполнено(ПериодПросрочки.ДатаНачала) 
                                 Или ЗначениеЗаполнено(ПериодПросрочки.ДатаОкончания);
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Интервал;
    
    // Формируем стандартный период для СКД
    ЭлементОтбора.ПравоеЗначение = Новый СтандартныйПериод(ПериодПросрочки.ДатаНачала, ПериодПросрочки.ДатаОкончания);
    
КонецПроцедуры

Выясним причину, почему мы используем именно ВидСравненияКомпоновкиДанных.Интервал. Этот вид сравнения идеально подходит для работы с объектом СтандартныйПериод. Платформа сама позаботится о том, чтобы включить в выборку весь день даты окончания (по 23:59:59), что избавляет нас от ручного вызова функции КонецДня().

Метод 3. Использование параметров в запросе динамического списка

Если ваш динамический список построен на основе произвольного запроса, мы можем внедрить фильтрацию непосредственно в текст запроса. Это дает более жесткий контроль над логикой выборки. Рассмотрим подробнее этот вариант.

В тексте запроса динамического списка добавим условие в секцию ГДЕ:


ВЫБРАТЬ
    ДокументТаблица.Ссылка,
    ДокументТаблица.Дата,
    ДокументТаблица.ДатаПросрочки
ИЗ
    Документ.НашДокумент КАК ДокументТаблица
ГДЕ
    (&ИспользоватьОтборПоПериоду = ЛОЖЬ 
    ИЛИ (ДокументТаблица.ДатаПросрочки МЕЖДУ &НачалоПериода И &КонецПериода))

В этом случае при изменении реквизита ПериодПросрочки на форме, нам нужно будет устанавливать параметры запроса:


&НаСервере
Процедура ОбновитьПараметрыСписка()
    
    Начало = ПериодПросрочки.ДатаНачала;
    // Важно: для корректного попадания документов за последний день используем КонецДня
    Конец = КонецДня(ПериодПросрочки.ДатаОкончания);
    
    Использовать = ЗначениеЗаполнено(Начало) И ЗначениеЗаполнено(Конец);
    
    Список.Параметры.УстановитьЗначениеПараметра("НачалоПериода", Начало);
    Список.Параметры.УстановитьЗначениеПараметра("КонецПериода", Конец);
    Список.Параметры.УстановитьЗначениеПараметра("ИспользоватьОтборПоПериоду", Использовать);
    
КонецПроцедуры

Важные нюансы и оптимизация

Разберем критически важный момент, о котором часто забывают начинающие разработчики. Если в вашей базе данных тысячи или миллионы документов, любой отбор по неиндексированному полю будет приводить к значительным задержкам при открытии и обновлении списка.

Обязательно проверьте индексирование:

  1. Перейдите в конфигураторе к объекту метаданных (например, документ ЗаказПокупателя).
  2. Найдите реквизит ДатаПросрочки.
  3. В свойствах реквизита найдите параметр «Индексировать».
  4. Установите значение «Индексировать» или «Индексировать с дополнительным упорядочиванием» (если планируете сортировать список по этой дате).

Проанализируем также вопрос «границы времени». При использовании простых сравнений >= и <= без учета времени, документы, созданные, например, в 12:00 последнего дня периода, не попадут в фильтр, так как дата без времени воспринимается системой как начало дня (00:00:00). Именно поэтому использование объекта СтандартныйПериод или функции КонецДня() является обязательным стандартом разработки.

Таким образом, мы рассмотрели три основных способа реализации отбора. Для большинства типовых задач наиболее предпочтительным является Метод 2 с использованием реквизита СтандартныйПериод, так как он обеспечивает наиболее привычный и удобный интерфейс для конечного пользователя, сохраняя при этом гибкость программного управления.

← На главную