Как ограничить выбор стандартного периода одним месяцем в отчете СКД?

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

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

Способ 1: Использование параметра «Дата» с форматом редактирования

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

Для реализации этого метода выполним следующие шаги в конфигураторе:

  1. Откроем схему компоновки данных и перейдем на закладку Параметры.
  2. Создадим новый параметр, назовем его, например, ВыбранныйМесяц. Установим для него тип Дата.
  3. В колонке Оформление для этого параметра найдем свойство Формат редактирования. Пропишем в нем строку: ДФ='MMMM yyyy'. Это заставит стандартный календарь 1С отображать только список месяцев и лет.
  4. Теперь нам нужно передать границы этого месяца в запрос. Для этого создадим еще два параметра: ДатаНачала и ДатаОкончания.
  5. Для этих параметров установим флаг Ограничение доступности, чтобы пользователь не видел их в настройках.
  6. В поле Выражение для ДатаНачала пропишем: НачалоПериода(&ВыбранныйМесяц, "Месяц").
  7. В поле Выражение для ДатаОкончания пропишем: КонецПериода(&ВыбранныйМесяц, "Месяц").

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

Способ 2: Программная настройка периода через форму отчета

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

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


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

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

В этом примере, даже если пользователь выберет произвольный интервал в диалоге, процедура завершения «подправит» его выбор, установив границы полного месяца, соответствующего дате начала. Далее нам нужно обновить значения в КомпоновщикНастроек:


&НаКлиенте
Процедура ОбновитьПараметрыСКД(Начало, Конец)
    ПараметрДатаНач = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ДатаНачала");
    Если ПараметрДатаНач <> Неопределено Тогда
        ПараметрДатаНач.Значение = Начало;
        ПараметрДатаНач.Использование = Истина;
    КонецЕсли;

    ПараметрДатаКон = Отчет.КомпоновщикНастроек.Настройки.ParemetriДанных.Элементы.Найти("ДатаОкончания");
    Если ПараметрДатаКон <> Неопределено Тогда
        ПараметрДатаКон.Значение = Конец;
        ПараметрДатаКон.Использование = Истина;
    КонецЕсли;
КонецПроцедуры

Способ 3: Использование события ПриКомпоновкеРезультата

Посмотрим на ситуацию с другой стороны. Что если мы не хотим создавать форму отчета, а желаем оставить стандартный интерфейс? В этом случае мы можем использовать модуль объекта отчета и процедуру ПриКомпоновкеРезультата. Этот метод позволяет проверить настройки пользователя непосредственно перед выполнением отчета.

Проанализируем следующий алгоритм действий:

  1. Пользователь нажимает кнопку «Сформировать».
  2. Система вызывает обработчик ПриКомпоновкеРезультата в модуле объекта.
  3. Мы программно считываем выбранный период и, если он больше одного месяца, либо выдаем ошибку, либо автоматически корректируем его.

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

Этот способ хорош тем, что он работает всегда, независимо от того, через какую форму (стандартную или пользовательскую) был вызван отчет. Мы гарантируем целостность данных на уровне бизнес-логики самого отчета.

Способ 4: Ограничение через доступные значения

Если количество периодов, доступных пользователю, невелико (например, только месяцы текущего года), мы можем заполнить список Доступные значения для параметра типа СтандартныйПериод. Это можно сделать в конфигураторе на закладке параметров СКД. Вместо произвольного выбора дат пользователь увидит выпадающий список с заранее подготовленными элементами (Январь 2023, Февраль 2023 и т.д.). Это полностью исключает возможность выбора некорректного периода.

Способ 5: Визуальный «обман» через вычисляемые параметры

Рассмотрим еще один интересный подход. Мы можем оставить стандартный выбор периода для пользователя в интерфейсе, но полностью игнорировать его вторую дату (дату окончания) в самом запросе. В выражениях параметров СКД можно указать, что отчет всегда строится от НачалоПериода(&Период.ДатаНачала, "Месяц") до КонецПериода(&Период.ДатаНачала, "Месяц"). В этом случае, даже если пользователь случайно выберет год, отчет сформируется только за первый месяц этого года, что обеспечит высокую производительность и соблюдение логики «одного месяца».

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

← На главную