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