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