Как в отчете на СКД 1С динамически изменять группировку по периоду (день, месяц, год)?

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

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

Основная задача — добавить на форму отчета параметр (например, переключатель или список выбора) со значениями "День", "Месяц", "Год" и, в зависимости от выбора, изменять поле группировки в структуре отчета. Для этой задачи есть готовый отчет с возможностью выбора периодичности.

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

Способ 1. Использование условного выражения в запросе (рекомендуемый)

Этот метод является наиболее элегантным и простым в реализации. Он не требует программного вмешательства в процесс формирования отчета или создания нескольких вариантов. Вся логика закладывается непосредственно в текст запроса СКД.

Разберем по шагам:

  1. Создаем параметр. В схеме компоновки данных на вкладке "Параметры" создадим новый параметр, например, с именем Периодичность. В его свойствах укажем "Тип значения" — "Строка" и настроим список выбора. Для этого в свойстве "Выражение списка значений" можно указать предопределенный список или просто в свойстве "Доступные значения" перечислить строки: "День", "Месяц", "Год". Не забудьте установить флажок "Включать в пользовательские настройки", чтобы параметр появился на форме отчета.

  2. Модифицируем запрос. В тексте запроса нам нужно создать одно вычисляемое поле, которое будет принимать значение нужного периода в зависимости от нашего параметра. Для этого идеально подходит конструкция ВЫБОР ... КОГДА ... КОНЕЦ.

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

    Посмотрим на пример:

    
    ВЫБРАТЬ
        НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ДЕНЬ) КАК ПериодДень,
        НАЧАЛОПЕРИОДА(РегистрОбороты.Период, МЕСЯЦ) КАК ПериодМесяц,
        НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ГОД) КАК ПериодГод,
        РегистрОбороты.СуммаОборот
    ИЗ
        РегистрНакопления.МойРегистр.Обороты(, , Авто, ) КАК РегистрОбороты
    

    А теперь добавим условное выражение, чтобы объединить эти поля в одно:

    
    ВЫБРАТЬ
        ВЫБОР
            КОГДА &Периодичность = "День" ТОГДА НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ДЕНЬ)
            КОГДА &Периодичность = "Месяц" ТОГДА НАЧАЛОПЕРИОДА(РеgiстрОбороты.Период, МЕСЯЦ)
            КОГДА &Периодичность = "Год" ТОГДА НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ГОД)
        КОНЕЦ КАК ВыбранныйПериод,
        РегистрОбороты.СуммаОборот
    ИЗ
        РегистрНакопления.МойРегистр.Обороты(, , Авто, ) КАК РегистрОбороты
    
  3. Настраиваем группировку. На вкладке "Настройки" СКД создадим группировку. В качестве поля группировки выберем наше новое поле — ВыбранныйПериод. Теперь, когда пользователь будет менять значение параметра Периодичность на форме, СКД автоматически будет подставлять в поле ВыбранныйПериод нужные данные, и группировка будет меняться.

Преимущества: Простота, наглядность, отсутствие лишнего кода и вариантов отчета. Вся логика находится в одном месте — в запросе.

Способ 2. Использование дочерних полей периода (для платформы 8.3.6 и выше)

Начиная с платформы 1С:Предприятие 8.3.6, система компоновки данных научилась автоматически "разбирать" поля с типом "Дата" на составляющие. Это самый простой способ, который вообще не требует доработок от программиста.

Если в вашем наборе данных есть поле Период, то в пользовательском режиме при настройке структуры отчета пользователь увидит не только само поле Период, но и его дочерние поля:

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

Преимущества: Не требует никаких усилий со стороны разработчика. Все возможности уже встроены в платформу.

Недостатки: Перекладывает настройку на пользователя, что может быть не всегда удобно, если требуется жестко заданный выбор "День/Месяц/Год".

Способ 3. Создание вычисляемых полей и вариантов отчета

Это классический подход, который был популярен до появления условных выражений в запросах СКД. Суть его в том, чтобы подготовить несколько полей для группировки, а затем создать несколько вариантов отчета, каждый из которых использует свое поле.

Разберем по шагам:

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

    
    ВЫБРАТЬ
        НАЧАЛОПЕРИОДА(ИсточникДанных.Период, ДЕНЬ) КАК ПериодДень,
        НАЧАЛОПЕРИОДА(ИсточникДанных.Период, МЕСЯЦ) КАК ПериодМесяц,
        НАЧАЛОПЕРИОДА(ИсточникДанных.Период, ГОД) КАК ПериодГод,
        ИсточникДанных.СуммаОборот
    ИЗ
        РегистрНакопления.МойРегистр.Обороты(,,Авто,) КАК ИсточникДанных
    

    Альтернатива: Можно не изменять запрос, а создать эти поля на вкладке "Вычисляемые поля" в СКД. Выражения будут такими же: НачалоПериода(Период, "ДЕНЬ"), НачалоПериода(Период, "МЕСЯЦ") и т.д.

  2. Создаем варианты отчета. На вкладке "Настройки" создаем три варианта отчета. Например:

    • "Отчет по дням": в структуре этого варианта добавляем группировку по полю ПериодДень.
    • "Отчет по месяцам": группировка по полю ПериодМесяц.
    • "Отчет по годам": группировка по полю ПериодГод.
    Теперь пользователь сможет выбирать нужный вариант из выпадающего списка на форме отчета, и структура будет меняться.

Преимущества: Простое и понятное разделение логики. Не требует сложного кода.

Недостатки: Увеличивается количество вариантов отчета, что может быть избыточным.

Способ 4. Программное изменение структуры отчета (гибкий, но сложный)

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

Разберем по шагам:

  1. Создаем параметр. Как и в первом способе, создаем параметр Периодичность со списком выбора "День", "Месяц", "Год".

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

    Посмотрим на примерный код:

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

Преимущества: Полный контроль над структурой и настройками отчета.

Недостатки: Высокая сложность, большой объем кода, необходимость вручную управлять всеми этапами компоновки.

Что не будет работать: ошибка новичков

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


...
ИЗ
    РегистрНакопления.МойРегистр.ОстаткиИОбороты(, , {(&Периодичность)}, , ) КАК ТаблицаРегистра
...

Такой подход не работает. Конструкция {...} в СКД предназначена для условного включения или выключения целых блоков текста запроса, а не для подстановки значений параметров в качестве ключевых слов (День, Месяц, Год). Для динамического выбора периодичности необходимо использовать один из методов, описанных выше.

← На главную