При разработке сложных отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда стандартные итоги в кросс-таблицах ведут себя непредсказуемо. Особенно остро проблема проявляется на так называемой «точке пересечения» — в ячейке, где сходятся общий горизонтальный и общий вертикальный итоги. Если в отчете используются вычисляемые поля со сложной логикой ВЫБОР КОГДА, обычное суммирование может выдавать некорректные данные.
В этой статье мы разберем, почему возникают ошибки в итогах, как правильно настроить ресурсы и какие функции СКД помогут получить гарантированно верный результат на пересечении группировок.
Рассмотрим ситуацию, когда в вычисляемом поле прописана сложная логика, как в примере из практики:
(Выбор когда (КатегорияППП = "000" или КатегорияППП = "001")
И (НачислениеУдержание = ПланыВидовРасчета.Начисления.НайтиПоНаименованию("270 Отпуск основной"))
И (МЕСЯЦ(ПериодДействия) > МЕСЯЦ(Период)) Тогда Сумма Иначе 0 Конец)
Когда мы выносим такое поле в ресурсы и указываем функцию Сумма(ИмяПоля), СКД пытается вычислить итог. Проблема заключается в том, что система может применять условие ВЫБОР либо к каждой детальной записи (что правильно), либо к уже агрегированным данным в группировке (что часто приводит к ошибке). На пересечении горизонтального итога (по колонкам) и вертикального (по строкам) контекст вычислений становится «размытым», и система не понимает, нужно ли суммировать результаты условий или применять условие к сумме.
Первое, на что стоит обратить внимание — это колонка «Рассчитывать по...» на закладке «Ресурсы». По умолчанию СКД рассчитывает ресурс по всем доступным группировкам. Однако для корректного пересечения часто требуется задать разные формулы для разных уровней отчета.
Проанализируем шаги по настройке:
БезБ).Сумма(БезБ).НачислениеУдержание и КатегорияППП).Одной из самых распространенных ошибок является написание условий ВЫБОР КОГДА во вкладке «Вычисляемые поля». Опыт показывает, что для корректного расчета итогов логику лучше переносить непосредственно в выражение ресурса.
Выясним причину: когда условие находится в вычисляемом поле, СКД сначала вычисляет его для каждой записи, а потом суммирует. Если же условие находится в ресурсе, мы можем явно указать системе способ агрегации. Вместо использования вычисляемого поля ИтогоБезБ, создадим ресурс напрямую для поля Сумма:
Сумма(Выбор Когда КатегорияППП В ("000", "001", "002") Тогда Сумма Иначе 0 Конец)
Такой подход позволяет СКД более эффективно управлять контекстом расчета в кросс-таблицах, особенно на пересечении группировок.
Если стандартные методы не помогают и итог на пересечении все равно не сходится (например, когда нужно получить «сумму максимумов» или «сумму уникальных значений»), на помощь приходит мощная функция ВычислитьВыражениеСГруппировкойМассив. Она позволяет принудительно вычислить итоги по строкам, собрать их в массив и затем просуммировать этот массив для получения общего итога.
Рассмотрим пример выражения для ресурса в «Общем итоге»:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(Сумма)", "НачислениеУдержание"))
Как это работает:
Сумма(Сумма) для каждой группировки НачислениеУдержание.Сумма(...), стоящая снаружи, складывает элементы этого массива.Это гарантирует, что общий итог будет в точности равен сумме строк, видимых пользователем в отчете, что и требуется для корректного пересечения.
В ходе анализа ситуации мы заметили использование функции НайтиПоНаименованию внутри выражений СКД:
НачислениеУдержание = ПланыВидовРасчета.Начисления.НайтиПоНаименованию("270 Отпуск основной")
Важно: это крайне опасная практика. Во-первых, поиск по наименованию медленный. Во-вторых, если в базе появятся два начисления с похожими именами или имя изменится, отчет перестанет работать.
Посмотрим, как сделать правильно:
СписокОтпусков).Список значений и выберем нужные виды расчетов.
Выбор Когда НачислениеУдержание В (&СписокОтпусков) Тогда Сумма Иначе 0 Конец
Это не только ускорит работу отчета, но и сделает расчет итогов на пересечении более стабильным, так как СКД проще оперировать ссылками, чем результатами строковых функций.
В кросс-таблицах часто возникают «дырки» в данных — ячейки, для которых нет записей. В этих случаях значение ресурса может быть NULL. Если ваша формула итога на пересечении включает арифметические операции между несколькими полями, наличие хотя бы одного NULL может привести к тому, что весь итог станет пустым.
Всегда оборачивайте числовые слагаемые в функцию ЕстьNull:
Сумма(ЕстьNull(Поле1, 0)) + Сумма(ЕстьNull(Поле2, 0))
Для корректного расчета пересечения горизонтальных и вертикальных итогов в СКД необходимо придерживаться комплексного подхода: отказываться от сложной логики в вычисляемых полях в пользу выражений ресурсов, активно использовать настройку «Рассчитывать по...» и, в самых сложных случаях, применять функцию агрегации массивов. Правильная работа с параметрами вместо поиска по наименованию дополнительно защитит ваш отчет от логических ошибок при расчете итоговых показателей.