Как сделать отбор при открытии за период с возможностью его изменения пользователем?

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

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

В этой статье мы подробно разберем, почему стандартные механизмы платформы могут вызывать ошибки, проанализируем причины возникновения сбоев и рассмотрим три надежных способа реализации этой задачи.

В чем заключается основная проблема стандартного подхода?

Давайте проанализируем попытку решения, которая часто приводит к ошибкам. Типичный сценарий: разработчик пытается передать структуру отбора через стандартный параметр Отбор при вызове функции ОткрытьФорму. Код выглядит следующим образом:


ЗначениеОтбора = Новый Структура();
ЗначениеОтбора.Вставить("ФильтрПоДатаНач", НачалоГода(Объект.Дата));
ЗначениеОтбора.Вставить("ФильтрПоДатаКон", КонецГода(Объект.Дата));
ПараметрыВыбора = Новый Структура("Отбор", ЗначениеОтбора);
ОткрытьФорму("Документ.лкЗаказНаПроизводство.ФормаВыбора", ПараметрыВыбора);

Такой подход гарантированно вызовет ошибку «Несоответствие типов» по двум ключевым причинам:

  1. Свойство Отбор в параметрах формы ожидает структуру, ключами которой являются реальные реквизиты (колонки) динамического списка. Полей с именами ФильтрПоДатаНач или ФильтрПоДатаКон в стандартной таблице документов не существует — там есть только реквизит Дата.
  2. Стандартный параметр формы Отбор поддерживает сравнение только на строгое равенство («Равно»). Мы не можем передать туда два условия на диапазон («Больше или равно» и «Меньше или равно») для одного и того же поля, так как ключи в структуре не могут дублироваться.

Кроме того, даже если бы этот механизм работал для периодов, платформа автоматически помещает параметры из структуры Отбор в так называемые Фиксированные настройки динамического списка. Особенность фиксированных настроек в том, что пользователь никак не может повлиять на них в интерфейсе — кнопки изменения периода будут заблокированы.

Выяснив причины ограничений стандартного механизма, перейдем к разбору трех рабочих вариантов решения.

Вариант 1. Использование стандартного периода элемента формы (Самый простой способ)

У таблиц на управляемой форме, отображающих динамические списки документов, есть стандартное встроенное свойство Период. Оно имеет тип СтандартныйПериод и напрямую связано с полем выбора периода на форме. Если программно изменить это свойство, отбор применится, но пользователь в любой момент сможет нажать на кнопку выбора периода и изменить даты.

Разберем реализацию этого способа по шагам.

Шаг 1. Передача параметров при открытии формы:

Вместо использования зарезервированного свойства Отбор, мы передадим в форму наши собственные произвольные параметры начала и окончания периода:


ПараметрыФормы = Новый Структура();
ПараметрыФормы.Вставить("ДатаНачала", НачалоГода(Объект.Дата));
ПараметрыФормы.Вставить("ДатаОкончания", КонецГода(Объект.Дата));

ОткрытьФорму("Документ.лкЗаказНаПроизводство.ФормаВыбора", ПараметрыФормы);

Шаг 2. Применение параметров в открываемой форме:

В модуле открываемой формы списка (или выбора) в обработчике события ПриСозданииНаСервере мы перехватываем переданные параметры и устанавливаем период для элемента формы таблицы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("ДатаНачала") И Параметры.Свойство("ДатаОкончания") Тогда
        // Обратите внимание: "Список" — это имя элемента таблицы на вашей форме
        Элементы.Список.Период = Новый СтандартныйПериод(Параметры.ДатаНачала, Параметры.ДатаОкончания);
    КонецЕсли;
    
КонецПроцедуры

При таком подходе форма откроется с заполненным интервалом текущего года, а вверху формы пользователь увидит стандартную надпись с выбранным периодом и сможет легко его перенастроить.

Вариант 2. Добавление условий в «Пользовательские настройки» динамического списка

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

Давайте посмотрим, как программно сконструировать такие элементы отбора.

Передачу параметров при открытии формы оставляем точно такой же, как в Варианте 1. А в модуле открываемой формы в обработчике ПриСозданииНаСервере пишем следующий код:


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

Благодаря установке свойства РежимОтображения в значение БыстрыйДоступ, эти отборы появятся прямо в верхней части формы списка в виде удобных флажков с полями ввода дат. Пользователь сможет легко снять галочки или изменить значения.

Вариант 3. Использование готовых функций БСП (Библиотеки Стандартных Подсистем)

Если вы работаете в современной типовой конфигурации 1С (такой как УТ, ERP, КА, БП или УНФ), в вашей системе гарантированно присутствует БСП. В составе этой библиотеки есть замечательный общий модуль ОбщегоНазначенияКлиентСервер, функции которого позволяют установить отборы буквально в одну строку кода, избегая написания громоздких конструкций компоновки данных.

Рассмотрим, как красиво решить задачу с помощью БСП в обработчике ПриСозданииНаСервере:


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

Этот метод самостоятельно найдет или создаст нужные элементы настройки компоновщика, установит переданные значения границ периода, подпишет их понятным представлением ("Дата начала", "Дата окончания") и выведет их в область быстрого доступа формы динамического списка.

Резюме

Мы подробно разобрали, почему стандартная передача периода через структуру Отбор в параметрах открытия формы не подходит для решения этой задачи. Для реализации динамических, изменяемых пользователем периодов всегда используйте либо работу напрямую со свойством Период таблицы формы, либо добавление элементов в ПользовательскиеНастройки компоновщика динамического списка (вручную или через полезные механизмы БСП).

← На главную