Как разделить период на два подпериода в отчете на СКД

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

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

Способ 1. Использование выражений параметров на вкладке «Параметры» СКД

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

Разберем по шагам, как настроить параметры:

  1. Создадим доступный для пользователя параметр Период с типом СтандартныйПериод.
  2. В запросе схемы зафиксируем четыре внутренних параметра: НачалоПериода1, КонецПериода1, НачалоПериода2 и КонецПериода2. Для них снимем флажок ограничения доступности для пользователя.
  3. В колонке Выражение зададим нужные функции вычисления дат.

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

Посмотрим на пример вычисления параметров, когда интервал делится ровно пополам по количеству дней:

Для параметра НачалоПериода1:

&Период.ДатаНачала

Для параметра КонецПериода1:


КонецПериода(ДобавитьКДате(&Период.ДатаНачала, "День", Цел(РазностьДат(&Период.ДатаНачала, &Период.ДатаОкончания, "День") / 2)), "День")

Для параметра НачалоПериода2:


НачалоПериода(ДобавитьКДате(&НачалоПериода1, "День", Цел(РазностьДат(&Период.ДатаНачала, &Период.ДатаОкончания, "День") / 2) + 1), "День")

Для параметра КонецПериода2:

&Период.ДатаОкончания

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

Способ 2. Вызов экспортной функции общего модуля

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

Посмотрим на пример заполнения колонки Выражение для параметра КонецПериода1:


РаботаСДатамиПереопределяемый.ПолучитьКонецПервогоПериода(&Период.ДатаНачала, &Период.ДатаОкончания)

Важно учитывать, что вызываемый общий модуль должен иметь включенный признак клиент-серверного вызова или контекста исполнения, в котором выполняется компоновка макета.

Способ 3. Программная установка параметров в модуле отчета

Когда требуется выполнить вычисления с использованием встроенного языка BSL, оптимальным решением является обработка события ПриКомпоновкеРезультата в модуле объекта отчета.

Проанализируем порядок действий при программной установке параметров:

  1. Отменяем стандартную обработку формирования отчета, установив СтандартнаяОбработка = Ложь.
  2. Извлекаем значение пользовательского параметра Период из компоновщика настроек.
  3. Рассчитываем нужные даты на встроенном языке BSL.
  4. Записываем полученные значения в структуру ПараметрыДанных.
  5. Запускаем компоновщик макета и выполняем вывод отчета.

Разберем пример BSL-кода в модуле объекта отчета:


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

	// Сборка и вывод отчета
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
	
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
	
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
КонецПроцедуры

Способ 4. Изменение архитектуры отчета без жестких параметров

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

  1. Передавать в запрос один общий период (НачалоПериода и КонецПериода).
  2. В запросе выбирать поле Период с нужной периодичностью (например, Месяц) или добавить вычисляемое поле, определяющее номер подпериода.
  3. В настройках структуры отчета выводить данные в кросс-таблицу, где колонками выступают сгруппированные периоды.

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

← На главную