При разработке отчетов в Системе компоновки данных (СКД) часто возникает необходимость пропорционально распределить плановые показатели за месяц по неделям в зависимости от количества календарных дней. Например, если в первой неделе месяца всего 4 календарных дня, а во второй — 7, месячный план должен делиться соответственно количеству дней, попавших в конкретную неделю.
Рассмотрим, с какой ошибкой можно столкнуться при использовании дополнительных наборов данных и как правильно реализовать распределение показателей в отчетах 1С.
Разберем типичную ситуацию: для получения количества дней в неделе создается дополнительный набор данных — запрос, в котором генерируется таблица дат периода с номером недели. В основном наборе данных также извлекается номер недели, после чего между наборами настраивается связь.
Однако при попытке сформировать отчет система выдает ошибку вида:
Ошибка компоновки макета / Поле не найдено "ДнейНедели"
Выясним причину этой проблемы. Ошибка возникает из-за особенностей работы языкового процессора СКД с пакетными запросами:
ПОМЕСТИТЬ для создания временной таблицы и при этом отсутствует финальный выбор данных через оператор ВЫБРАТЬ, СКД не может определить доступные поля выборки.Для исправления ошибки достаточно убрать ключевое слово ПОМЕСТИТЬ из запроса набора данных или дописать итоговый выбор из созданной временной таблицы:
// Неправильно для набора данных СКД:
ВЫБРАТЬ
Даты.Дата КАК Дата,
НЕДЕЛЯ(Даты.Дата) КАК НомерНедели
ПОМЕСТИТЬ ВТ_Даты
ИЗ
...
// Правильно:
ВЫБРАТЬ
Даты.Дата КАК Дата,
НЕДЕЛЯ(Даты.Дата) КАК НомерНедели
ИЗ
...
Рассмотрим альтернативный способ решения задачи без генерации таблицы дат и создания дополнительных наборов данных. Вычислить пересечение дней недели и текущего месяца можно непосредственно в основном запросе с помощью функций работы с датами.
Разберем логику по шагам:
Посмотрим на пример реализации выражения на языке запросов 1С:
ВЫБРАТЬ
ПродажиПланы.Период КАК Период,
ПродажиПланы.ПланСумма КАК ПланСумма,
РАЗНОСТЬДАТ(
ВЫБОР
КОГДА НАЧАЛОПЕРИОДА(ПродажиПланы.Период, НЕДЕЛЯ) < НАЧАЛОПЕРИОДА(ПродажиПланы.Период, МЕСЯЦ)
ТОГДА НАЧАЛОПЕРИОДА(ПродажиПланы.Период, МЕСЯЦ)
ИНАЧЕ НАЧАЛОПЕРИОДА(ПродажиПланы.Период, НЕДЕЛЯ)
КОНЕЦ,
ВЫБОР
КОГДА КОНЕЦПЕРИОДА(ПродажиПланы.Период, НЕДЕЛЯ) > КОНЕЦПЕРИОДА(ПродажиПланы.Период, МЕСЯЦ)
ТОГДА КОНЕЦПЕРИОДА(ПродажиПланы.Период, МЕСЯЦ)
ИНАЧЕ КОНЕЦПЕРИОДА(ПродажиПланы.Период, НЕДЕЛЯ)
КОНЕЦ,
ДЕНЬ
) + 1 КАК КоличествоДнейВНеделе
ИЗ
РегистрСведений.ПродажиПланы КАК ПродажиПланы
Если количество дней в неделе уже получено в запросе или через связи наборов данных, распределить плановую сумму по неделям пропорционально дням можно на вкладке Ресурсы в схеме компоновки данных.
Для этого применяется функция ВычислитьВыражение, которая позволяет получить значение ресурса вышестоящей группировки (в данном случае — сумму дней за весь месяц):
Сумма(ПлановаяВеличина) * Сумма(КоличествоДнейВНеделе) / ВычислитьВыражение("Сумма(КоличествоДнейВНеделе)", "ПериодМесяц")
Проанализируем работу данного выражения:
Сумма(ПлановаяВеличина) — плановый показатель за месяц;Сумма(КоличествоДнейВНеделе) — количество дней в текущей неделе месяца;ВычислитьВыражение(..., "ПериодМесяц") — общий суммарный итог дней за весь месяц для расчета доли текущей недели.При пропорциональном делении сумм с округлением до копеек или целых единиц может возникать суммовая погрешность (расхождение итогов на 1–2 копейки). Обратите внимание на следующие нюансы:
ПриКомпоновкеРезультата) или высчитывать плановую величину последней недели месяца как разницу между общим месячным планом и суммой предыдущих недель.