Почему в СКД не выводятся итоги по группировкам верхнего уровня?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Финансы и профессиональные услуги
← На главную

Часто при работе с Системой Компоновки Данных (СКД) возникает ситуация, когда итоговые суммы корректно отображаются для самых нижних уровней группировки, но для родительских групп и общих итогов ячейки остаются пустыми. Первое, что приходит на ум, — проверить настройки ресурсов в СКД. Однако причина может быть и не в них. Рассмотрим подробно, почему так происходит и как найти источник проблемы, особенно в случаях, когда отчет выводится не стандартным образом, а через программную обработку.

Проанализируем типичный случай: в отчете есть иерархия группировок, например, Организация -> Вид денежных средств -> Банковский счет. Итоги по сумме выводятся для каждого банковского счета, а вот для "Вида денежных средств" и "Организации" — нет. Давайте разберемся в возможных причинах и способах их устранения.

Шаг 1. Стандартная диагностика: проверяем настройки ресурсов в СКД

Прежде чем погружаться в код, всегда стоит начать с базовых проверок в самой схеме компоновки данных. Это наиболее частая причина отсутствия итогов. Откроем схему и перейдем на вкладку "Ресурсы".

  1. Выражение ресурса. Убедимся, что в поле "Выражение" указано именно то поле, которое нужно суммировать (например, СуммаОборот), а не агрегатная функция вроде СУММА(СуммаОборот). СКД сама применяет нужную функцию (Сумма, Количество, Среднее и т.д.) к указанному полю при расчете итогов.

  2. Поле "Рассчитывать по...". Это ключевая настройка для управления итогами. Она указывает СКД, для каких группировок необходимо вычислять данный ресурс.

    • Если поле "Рассчитывать по..." оставить пустым, СКД будет пытаться рассчитать итог для всех вышестоящих группировок. В большинстве случаев это работает корректно.
    • Если итоги нужны только по определенным группировкам, их нужно явно перечислить в этом поле. Например, если нам нужны итоги только по организации, мы указываем группировку "Организация".
    • В нашем случае, когда итоги не выводятся, можно попробовать явно указать все группировки, для которых они нужны: "Организация", "Вид денежных средств", "Тип счета". Если это не помогает, можно попробовать, наоборот, полностью очистить это поле.
  3. Обработка значений NULL. Если в данных могут встречаться неопределенные значения (NULL), это может влиять на расчет итогов. Например, при левом соединении наборов данных числовые поля из правой таблицы могут быть NULL. СКД может по-разному их обрабатывать. Чтобы избежать проблем, рекомендуется оборачивать такие поля в функцию ЕСТЬNULL() прямо в тексте запроса или в вычисляемом поле. Например: ЕСТЬNULL(ТаблицаОстатков.Сумма, 0) КАК Сумма. Это гарантирует, что все строки будут участвовать в расчете.

Если после тщательной проверки этих настроек итоги так и не появились, значит, проблема, скорее всего, находится глубже — на уровне программного кода, который выводит результат СКД.

Шаг 2. Неочевидная причина: ручной вывод данных в ДеревоЗначений

Очень часто СКД используется не для прямого вывода отчета на форму, а как мощный конструктор запросов. Программист получает результат компоновки в виде таблицы или дерева значений, а затем программно обрабатывает эти данные и выводит их в свой элемент управления на форме, например, в ДеревоЗначений. В этом случае ответственность за расчет и отображение итогов полностью ложится на код разработчика, а настройки ресурсов в СКД могут вообще не использоваться. Для изучения примеров программного формирования отчетов можно использовать подборку примеров программной работы с СКД.

В рассматриваемой нами теме автор предоставил фрагмент кода, который подтверждает именно такой сценарий. Давайте его проанализируем.


// ... код после получения данных из СКД ...

//VID( считаем итоги по добавленным колонкам,13.11.202
Для Каждого ПериодКолонка Из ДанныеФормы.КолонкиПериодов Цикл
    найдКолонка = ДанныеФормы.ДеревоСчета.Колонки.Найти(ПериодКолонка.Представление);
    Если найдКолонка = Неопределено Тогда
        //Сообщить("Колонка не найдена!");
    Иначе
        СчитатьСуммы(ДанныеФормы.ДеревоСчета.Строки, ПериодКолонка.Представление);
    КонецЕсли;
КонецЦикла;
//VID)-----------------------------------------------------------------------

Возврат ДанныеФормы;

Процедура СчитатьСуммы(Строки, Колонка)
    Для Каждого СтрокаДерева Из Строки Цикл
        // Если мы в строке, у неё нет итогов, пропустим
        Если СтрокаДерева.Строки.Количество() = 0 Тогда
            Продолжить;
        КонецЕсли;
        
        СчитатьСуммы(СтрокаДерева.Строки,Колонка);
        
        // Для текущей записи вычислим сумму строк колонки
        СтрокаДерева[Колонка] = СтрокаДерева.Строки.Итог(Колонка);
    КонецЦикла;
КонецПроцедуры

Разберем, что здесь происходит:

Этот механизм должен корректно рассчитывать все итоги. Если он не работает, значит, где-то в логике есть ошибка. Проблема уже не в СКД, а в этом конкретном алгоритме.

Шаг 3. План отладки и поиска ошибки в коде

Когда мы поняли, что проблема в коде, а не в настройках, нужно приступить к его отладке. Вот пошаговый план действий.

  1. Найти точку входа. В первую очередь, нужно найти место в коде, где результат работы СКД преобразуется и помещается в ДеревоЗначений на форме. Это поможет понять, в каком виде данные приходят из компоновщика и как строится первоначальная иерархия в дереве.

  2. Поставить точку останова. Установим точку останова внутри процедуры СчитатьСуммы, прямо на строке СтрокаДерева[Колонка] = СтрокаДерева.Строки.Итог(Колонка);.

  3. Запустить отладку. Сформируем отчет и дождемся, когда выполнение остановится на нашей точке. Теперь мы можем проанализировать переменные.

    • Проверить переменную СтрокаДерева. Какая именно строка сейчас обрабатывается? Это строка нижнего уровня или группировка?
    • Проанализировать коллекцию СтрокаДерева.Строки. Есть ли у текущей строки дочерние элементы? Если это группировка, для которой не считается итог, то, возможно, эта коллекция по какой-то причине пуста, хотя должна содержать дочерние строки.
    • Вычислить выражение СтрокаДерева.Строки.Итог(Колонка). Можно сделать это в окне "Вычислить выражение" (Shift+F9). Какое значение возвращает этот метод? Если 0, то либо в дочерних строках нет числовых данных, либо произошла ошибка.
  4. Проверить типы данных. Важный момент: чтобы метод Итог() сработал корректно, колонка в ДеревеЗначений, по которой считается сумма, должна иметь числовой тип. Если при создании колонок дерева ей по ошибке был назначен строковый тип, метод Итог() вернет 0. Убедимся, что тип данных колонки — Число.

  5. Проверить логику условия. В коде есть проверка: Если СтрокаДерева.Строки.Количество() = 0 Тогда Продолжить; КонецЕсли;. Она пропускает строки самого нижнего уровня (детальные записи), что правильно. Но, возможно, из-за ошибки при заполнении дерева у некоторых группировок верхнего уровня коллекция дочерних строк Строки оказывается пустой, и тогда для них расчет итога просто не выполняется.

Итог: Пройдясь по этим шагам с отладчиком, вы с высокой вероятностью обнаружите, почему рекурсивная процедура не отрабатывает для верхних уровней иерархии. Проблема может быть в неверном построении самого дерева, в неправильных типах данных колонок или в логической ошибке внутри самого алгоритма подсчета сумм.

← На главную