Часто при разработке отчетов в 1С возникает задача предоставить пользователю возможность самостоятельно выбирать детализацию данных по времени. Например, сегодня ему нужен отчет по месяцам, а завтра — по дням. Создавать для этого несколько разных отчетов, множество вариантов или даже использовать две разных схемы в отчете СКД — не всегда удобно. Разберем, как реализовать такую динамическую группировку в одном отчете на Системе Компоновки Данных (СКД) без создания отдельной формы.
Основная задача — добавить на форму отчета параметр (например, переключатель или список выбора) со значениями "День", "Месяц", "Год" и, в зависимости от выбора, изменять поле группировки в структуре отчета. Для этой задачи есть готовый отчет с возможностью выбора периодичности.
Рассмотрим несколько способов решения этой задачи, от самых простых и современных до более сложных, но гибких.
Этот метод является наиболее элегантным и простым в реализации. Он не требует программного вмешательства в процесс формирования отчета или создания нескольких вариантов. Вся логика закладывается непосредственно в текст запроса СКД.
Разберем по шагам:
Создаем параметр. В схеме компоновки данных на вкладке "Параметры" создадим новый параметр, например, с именем Периодичность. В его свойствах укажем "Тип значения" — "Строка" и настроим список выбора. Для этого в свойстве "Выражение списка значений" можно указать предопределенный список или просто в свойстве "Доступные значения" перечислить строки: "День", "Месяц", "Год". Не забудьте установить флажок "Включать в пользовательские настройки", чтобы параметр появился на форме отчета.
Модифицируем запрос. В тексте запроса нам нужно создать одно вычисляемое поле, которое будет принимать значение нужного периода в зависимости от нашего параметра. Для этого идеально подходит конструкция ВЫБОР ... КОГДА ... КОНЕЦ.
Важный момент: чтобы получить разные периоды (здесь вам может пригодиться шпаргалка по языку запросов), мы используем функцию языка запросов НАЧАЛОПЕРИОДА. Она приводит дату к началу дня, месяца или года — для этого подойдёт вывод финансовых показателей в динамике по периодам.
Посмотрим на пример:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ДЕНЬ) КАК ПериодДень,
НАЧАЛОПЕРИОДА(РегистрОбороты.Период, МЕСЯЦ) КАК ПериодМесяц,
НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ГОД) КАК ПериодГод,
РегистрОбороты.СуммаОборот
ИЗ
РегистрНакопления.МойРегистр.Обороты(, , Авто, ) КАК РегистрОбороты
А теперь добавим условное выражение, чтобы объединить эти поля в одно:
ВЫБРАТЬ
ВЫБОР
КОГДА &Периодичность = "День" ТОГДА НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ДЕНЬ)
КОГДА &Периодичность = "Месяц" ТОГДА НАЧАЛОПЕРИОДА(РеgiстрОбороты.Период, МЕСЯЦ)
КОГДА &Периодичность = "Год" ТОГДА НАЧАЛОПЕРИОДА(РегистрОбороты.Период, ГОД)
КОНЕЦ КАК ВыбранныйПериод,
РегистрОбороты.СуммаОборот
ИЗ
РегистрНакопления.МойРегистр.Обороты(, , Авто, ) КАК РегистрОбороты
Настраиваем группировку. На вкладке "Настройки" СКД создадим группировку. В качестве поля группировки выберем наше новое поле — ВыбранныйПериод. Теперь, когда пользователь будет менять значение параметра Периодичность на форме, СКД автоматически будет подставлять в поле ВыбранныйПериод нужные данные, и группировка будет меняться.
Преимущества: Простота, наглядность, отсутствие лишнего кода и вариантов отчета. Вся логика находится в одном месте — в запросе.
Начиная с платформы 1С:Предприятие 8.3.6, система компоновки данных научилась автоматически "разбирать" поля с типом "Дата" на составляющие. Это самый простой способ, который вообще не требует доработок от программиста.
Если в вашем наборе данных есть поле Период, то в пользовательском режиме при настройке структуры отчета пользователь увидит не только само поле Период, но и его дочерние поля:
Период.ДеньПериод.НеделяПериод.МесяцПериод.ГодПользователю достаточно просто перетащить нужное поле в структуру группировок, чтобы изменить детализацию отчета. Программисту для этого ничего делать не нужно, кроме как убедиться, что в запросе есть поле с типом "Дата".
Преимущества: Не требует никаких усилий со стороны разработчика. Все возможности уже встроены в платформу.
Недостатки: Перекладывает настройку на пользователя, что может быть не всегда удобно, если требуется жестко заданный выбор "День/Месяц/Год".
Это классический подход, который был популярен до появления условных выражений в запросах СКД. Суть его в том, чтобы подготовить несколько полей для группировки, а затем создать несколько вариантов отчета, каждый из которых использует свое поле.
Разберем по шагам:
Добавляем поля в запрос. В тексте запроса создаем три отдельных поля для каждой периодичности (похожий подход демонстрирует пример формирования шапки отчета по неделям, месяцам):
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(ИсточникДанных.Период, ДЕНЬ) КАК ПериодДень,
НАЧАЛОПЕРИОДА(ИсточникДанных.Период, МЕСЯЦ) КАК ПериодМесяц,
НАЧАЛОПЕРИОДА(ИсточникДанных.Период, ГОД) КАК ПериодГод,
ИсточникДанных.СуммаОборот
ИЗ
РегистрНакопления.МойРегистр.Обороты(,,Авто,) КАК ИсточникДанных
Альтернатива: Можно не изменять запрос, а создать эти поля на вкладке "Вычисляемые поля" в СКД. Выражения будут такими же: НачалоПериода(Период, "ДЕНЬ"), НачалоПериода(Период, "МЕСЯЦ") и т.д.
Создаем варианты отчета. На вкладке "Настройки" создаем три варианта отчета. Например:
ПериодДень.ПериодМесяц.ПериодГод.Преимущества: Простое и понятное разделение логики. Не требует сложного кода.
Недостатки: Увеличивается количество вариантов отчета, что может быть избыточным.
Этот метод является самым мощным и гибким (наподобие того, как реализована Пользовательская СКД), но и самым трудоемким — в разработке поможет инструментарий разработчика с консолью запросов и СКД. Он позволяет полностью контролировать процесс формирования отчета и изменять его структуру "на лету" в зависимости от любых условий. Он нужен в тех случаях, когда простой сменой поля группировки не обойтись (например, нужно добавить разные вычисляемые поля, выполнить программное изменение заголовка группировки отчета СКД или условное оформление).
Разберем по шагам:
Создаем параметр. Как и в первом способе, создаем параметр Периодичность со списком выбора "День", "Месяц", "Год".
Пишем код в модуле отчета. Нам понадобится обработчик события ПриКомпоновкеРезультата. В нем мы должны перехватить стандартный процесс формирования отчета, изменить настройки и запустить компоновку вручную.
Посмотрим на примерный код:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отменяем стандартную обработку, чтобы все сделать самим
СтандартнаяОбработка = Ложь;
// Получаем текущие настройки компоновщика
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Получаем значение нашего параметра
ЭлементПараметра = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Периодичность"));
Если ЭлементПараметра = Неопределено Тогда
// Если параметр не найден, ничего не делаем
Возврат;
КонецЕсли;
ЗначениеПериодичности = ЭлементПараметра.Значение;
// Очищаем существующие группировки
Настройки.Структура.Очистить();
// Создаем новую группировку
НоваяГруппировка = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
// Добавляем поле группировки в зависимости от параметра
ПолеГруппировки = НоваяГруппировка.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
Если ЗначениеПериодичности = "День" Тогда
ПолеГруппировки.Поле = Новый ПолеКомпоновкиДанных("ПериодДень");
ИначеЕсли ЗначениеПериодичности = "Месяц" Тогда
ПолеГруппировки.Поле = Новый ПолеКомпоновкиДанных("ПериодМесяц");
ИначеЕсли ЗначениеПериодичности = "Год" Тогда
ПолеГруппировки.Поле = Новый ПолеКомпоновкиДанных("ПериодГод");
КонецЕсли;
// Добавляем выбранные поля (например, ресурсы)
ВыбранноеПоле = НоваяГруппировка.ВыбранныеПоля.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
// Запускаем процесс компоновки с новыми настройками
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки,,ДанныеРасшифровки);
ДокументРезультат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Преимущества: Полный контроль над структурой и настройками отчета.
Недостатки: Высокая сложность, большой объем кода, необходимость вручную управлять всеми этапами компоновки.
Иногда начинающие разработчики пытаются подставить имя периодичности в параметры виртуальной таблицы напрямую через фигурные скобки, как в примере ниже:
...
ИЗ
РегистрНакопления.МойРегистр.ОстаткиИОбороты(, , {(&Периодичность)}, , ) КАК ТаблицаРегистра
...
Такой подход не работает. Конструкция {...} в СКД предназначена для условного включения или выключения целых блоков текста запроса, а не для подстановки значений параметров в качестве ключевых слов (День, Месяц, Год). Для динамического выбора периодичности необходимо использовать один из методов, описанных выше.