При работе с Системой Компоновки Данных (СКД) в 1С мы часто сталкиваемся с необходимостью выводить сложные показатели, которые представляют собой не простые суммы, а проценты или отношения одних величин к другим. Однако прямая сумма таких показателей на более высоких уровнях иерархии отчета часто приводит к некорректным результатам. Представим, что у нас есть отчет, где на нижнем уровне иерархии правильно рассчитывается процент выполнения или эффективности, но при поднятии на уровень выше, простое суммирование этих процентов теряет смысл. Давайте рассмотрим, как решать эту проблему и получать осмысленные вертикальные итоги для процентных показателей и отношений.
Основная сложность при расчете итогов для процентов и отношений заключается в том, что эти показатели являются производными. Например, если у нас есть "ПроцентВыполнения", который рассчитывается как Факт / План * 100, то на уровне детальных записей он может быть 50%, а для другой записи – 70%. Если мы просто просуммируем эти проценты на более высоком уровне, получим 120%, что не является корректным общим процентом выполнения. Общий процент выполнения должен рассчитываться как СУММА(Факт) / СУММА(План) * 100, то есть на основе уже просуммированных исходных данных (Факт и План) по всей группе, а не на основе суммы рассчитанных процентов.
Такая же ситуация возникает и с другими отношениями, например, со средней выработкой на одного сотрудника или любыми показателями вида Ресурс1 / Ресурс2 * Ресурс3. Нам необходимо, чтобы итоговое значение на более высоком уровне иерархии было пересчитано, используя агрегированные значения исходных ресурсов, а не просто суммировало уже рассчитанные на низшем уровне показатели.
ВычислитьВыражениеСГруппировкойМассив()Для решения описанной проблемы в СКД мы можем использовать мощную функцию ВычислитьВыражениеСГруппировкойМассив(). Эта функция позволяет нам получить массив значений, вычисленных по заданному выражению для каждой записи в указанной группировке. После получения этого массива, мы можем применить к нему нужную нам агрегатную функцию (например, внешнюю Сумма()), чтобы получить корректный итог.
Давайте подробнее разберем синтаксис и возможности этой функции:
ВычислитьВыражениеСГруппировкойМассив("Выражение", "ВыраженияПолейГруппировки", "ОтборЗаписей", "ОтборГруппировок")
Выражение: Это строка, содержащая формулу, которую СКД должна вычислить для каждой записи в указанной группировке. Например, "Сумма(СуммаОборот)" или более сложное выражение типа "Сумма(Часов)/Сумма(ЧасыХ)*(Сумма(НачисленоНУ)-ЕСТЬNULL(Сумма(Наличные),0))". Важно понимать, что это выражение будет вычисляться в контексте каждой уникальной комбинации полей группировки, которые мы укажем в следующем параметре.ВыраженияПолейГруппировки: Это строка, содержащая имена полей группировки, перечисленные через запятую, например, "Контрагент, Договор" или "Рабочий". Функция будет вычислять Выражение для каждой уникальной комбинации значений этих полей. Именно это позволяет нам "опуститься" на нужный уровень детализации, выполнить там расчет, а затем собрать результаты.ОтборЗаписей: (Необязательный параметр) Выражение отбора, применяемое к детальным записям до их группировки. Например, "ПометкаУдаления = Ложь". Это позволяет исключить ненужные записи из начального набора данных, по которым будет строиться группировка.ОтборГруппировок: (Необязательный параметр) Выражение отбора, применяемое к уже сгруппированным данным. Например, "Сумма(СуммаОборот) > &Параметр1". Это позволяет отфильтровать группы после того, как по ним были рассчитаны промежуточные итоги.Функция ВычислитьВыражениеСГруппировкойМассив() возвращает массив результатов. Этот массив затем можно передать внешней агрегатной функции (например, Сумма(), Максимум(), Минимум(), Среднее()) для получения итогового значения на текущем уровне иерархии.
Предположим, у нас есть отчет, где нужно рассчитать пользовательское поле, которое является отношением и выглядит примерно так: (Сумма(Часов) / Сумма(ЧасыХ)) * (Сумма(НачисленоНУ) - ЕСТЬНУЛЛ(Сумма(Наличные),0)). На нижнем уровне иерархии этот расчет корректен, но при агрегации нам нужно не суммировать эти проценты, а получить общий итог, который представляет собой сумму результатов по каждому "Рабочему".
Давайте разберем шаги по настройке ресурса в СКД.
Прежде всего, мы должны четко понимать, как рассчитывается наш показатель на самом нижнем уровне иерархии, для каждой отдельной единицы или строки. В нашем случае, это выражение:
Сумма(Часов)/Сумма(ЧасыХ)*(Сумма(НачисленоНУ)-ЕСТЬNULL(Сумма(Наличные),0))
Это выражение включает в себя агрегатные функции (Сумма(), ЕСТЬNULL()), которые будут применяться к данным текущего уровня детализации.
Нам необходимо указать, по каким полям мы хотим получать индивидуальные результаты перед их окончательным суммированием. В обсуждаемой теме таким полем является "Рабочий". Это означает, что для каждого уникального "Рабочего" будет вычислено исходное выражение, а затем эти результаты будут собраны в массив.
ВычислитьВыражениеСГруппировкойМассив()Теперь, когда мы знаем исходное выражение и поле группировки, мы можем построить итоговую формулу для ресурса на вкладке "Ресурсы" СКД. Нам нужно получить массив значений выражения для каждого "Рабочего" и затем просуммировать элементы этого массива.
Финальная формула, которая победила в обсуждаемой теме, выглядит так:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(Часов)/Сумма(ЧасыХ)*(Сумма(НачисленоНУ)-ЕСТЬNULL(Сумма(Наличные),0))", "Рабочий"))
Давайте детально проанализируем эту формулу:
Сумма(): Эта функция суммирует элементы массива, который возвращает ВычислитьВыражениеСГруппировкойМассив(). Таким образом, мы получаем корректный вертикальный итог, который является суммой всех индивидуальных расчетов, выполненных на более низком уровне (для каждого "Рабочего").ВычислитьВыражениеСГруппировкойМассив(...): Это ядро нашего решения. Оно выполняет следующие действия:
"Сумма(Часов)/Сумма(ЧасыХ)*(Сумма(НачисленоНУ)-ЕСТЬNULL(Сумма(Наличные),0))". Это та самая формула расчета, которую мы определили для нижнего уровня иерархии. СКД будет вычислять это выражение для каждой группы, определенной во втором параметре."Рабочий". Здесь мы указываем, что выражение из первого параметра должно быть вычислено для каждого уникального значения поля "Рабочий". Функция вернет массив результатов, где каждый элемент будет представлять собой значение рассчитанного выражения для одного "Рабочего".Таким образом, мы сначала для каждого "Рабочего" вычисляем его индивидуальный показатель (процент или отношение), а затем складываем эти индивидуальные показатели, что и дает нам правильный вертикальный итог, избегая бессмысленного суммирования уже рассчитанных процентов.
Эту формулу необходимо прописать на вкладке "Ресурсы" в СКД, в поле "Выражение" для вашего нового или существующего ресурса. Убедитесь, что тип данных ресурса соответствует ожидаемому результату (например, Число).
Для более гибкого управления отчетами и ресурсами в СКД существуют и другие возможности, которые дополняют наше решение:
Это очень важное свойство ресурса, которое позволяет нам указывать, для каких группировок должен рассчитываться данный ресурс. Например, мы можем создать два ресурса:
ПроцентВыполненияДетально) с простым выражением Факт / План * 100 и свойством "Рассчитывать по..." для всех группировок, кроме "Общий итог".ПроцентВыполненияОбщий) с выражением, использующим ВычислитьВыражениеСГруппировкойМассив() или просто Сумма(Факт) / Сумма(План) * 100 (если это возможно) и свойством "Рассчитывать по..." только для "Общий итог".Такой подход позволяет отображать правильный процент на каждом уровне иерархии, а для общего итога использовать специально пересчитанное значение.
СКД предоставляет широкий набор стандартных агрегатных функций (СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ). Помимо них, существуют и более специфичные функции, такие как Массив(), которая формирует массив значений детальных записей. Ключевое слово Различные можно использовать вместе с Массив() для получения только уникальных значений в массиве.
Кроме того, в поле "Выражение" ресурсов можно прописывать сложные формулы, комбинируя несколько функций, использовать условные операторы ВЫБОР КОГДА, а также обращаться к функциям общих модулей, если это требуется для особо сложных вычислений.
ВычислитьВыражение():
В дополнение к ВычислитьВыражениеСГруппировкойМассив(), существует также функция ВычислитьВыражение(). Она позволяет вычислить выражение в контексте определенной группировки или общего итога. Ее синтаксис включает в себя выражение для расчета, имя группировки и область вычисления ("ОбщийИтог", имя группировки или "Иерархия").
Пример использования: ВычислитьВыражение("Сумма(Ресурс1)", "ОбщийИтог"). Эта функция может быть полезна, когда вам нужно получить значение из общего итога или другой конкретной группировки для использования в расчете на текущем уровне.
Для повышения читаемости и упрощения сложных выражений можно создавать вычисляемые поля на вкладке "Вычисляемые поля" схемы компоновки данных. Это позволяет разбить сложный расчет на несколько более простых шагов, а затем использовать эти промежуточные поля в ресурсах.
Если для расчета итогов требуются данные из нескольких источников, важно правильно настроить связи наборов данных. СКД может объединять данные как на уровне запроса (если связи настроены в источнике данных), так и на уровне схемы компоновки данных. Понимание этого может существенно влиять на корректность и производительность расчетов.
Расчет вертикальных итогов для процентных показателей и отношений в СКД требует внимательного подхода, поскольку прямое суммирование зачастую приводит к бессмысленным результатам. Использование функции ВычислитьВыражениеСГруппировкойМассив() является мощным и гибким решением, позволяющим пересчитывать итоговые значения на основе агрегированных исходных данных, а не уже рассчитанных процентов. Понимание этой функции, а также других возможностей СКД, таких как свойство "Рассчитывать по..." и вычисляемые поля, позволяет нам создавать точные, информативные и удобные для анализа отчеты в 1С.
Всегда помните, что при работе со сложными отчетами важно не только правильно вывести данные, но и обеспечить их корректный анализ на всех уровнях детализации.