При работе с объектом ДеревоЗначений у разработчиков часто возникает необходимость посчитать общую сумму или итог по конкретной числовой колонке. В синтаксис-помощнике данный метод относится не к самому дереву, а к коллекции его строк — КоллекцияСтрокДереваЗначений.
Рассмотрим подробнее, как устроена работа со встроенным методом подсчета итогов, какие нюансы необходимо учитывать при наличии иерархических уровней и почему в некоторых случаях метод возвращает 0 или Неопределено.
Для вычисления суммы по колонке используется метод Итог(), выносимый у коллекции строк дерева (ДеревоЗначений.Строки):
Синтаксис метода:
Итог(<Колонка>, <ВключатьПодчиненные>)
Разберем параметры подробнее:
Строка), ее индекс (тип Число) или объект КолонкаДереваЗначений.Булево) — определяет режим подсчета иерархии:
Ложь (по умолчанию) — суммируются значения только верхнего (корневого) уровня дерева строк.Истина — в итоговую сумму включаются значения абсолютно всех строк всех подчиненных уровней.Выясним причину, почему метод Итог() может возвращать 0 или Неопределено. Метод суммирует только те ячейки, которые имеют тип Число или могут быть к нему преобразованы.
Если колонка создается динамически в коде, ей обязательно необходимо задавать описание типов. Если тип колонки не определен или является составным без указания числа, алгоритм не сможет корректно просуммировать данные.
Пример правильной инициализации колонки с типом Число:
ОписаниеТипаЧисло = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));
ДеревоЗначений.Колонки.Добавить("Сумма", ОписаниеТипаЧисло);
Посмотрим на практический пример создания многоуровневого дерева значений и расчета итоговых показателей с разным значением параметра ВключатьПодчиненные:
ДЗ = Новый ДеревоЗначений;
ДЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(20, 2)));
Для Идн1 = 1 по 3 Цикл
Строка1 = ДЗ.Строки.Добавить();
Строка1.Сумма = Идн1 * 1000;
Для Идн2 = 1 по 3 Цикл
Строка2 = Строка1.Строки.Добавить();
Строка2.Сумма = Идн2 * 100;
Для Идн3 = 1 по 3 Цикл
Строка3 = Строка2.Строки.Добавить();
Строка3.Сумма = Идн3 * 10;
Для Идн4 = 1 по 3 Цикл
Строка4 = Строка3.Строки.Добавить();
Строка4.Сумма = Идн4;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;
// Сумма только по верхнему уровню (Строка1)
ИтогВерхнийУровень = ДЗ.Строки.Итог("Сумма", Ложь);
// Сумма по всем элементам и подчиненным веткам
ИтогВсеУровни = ДЗ.Строки.Итог("Сумма", Истина);
Сообщить("Итог по верхнему уровню = " + ИтогВерхнийУровень); // вернет 6 000
Сообщить("Итог по всем уровням = " + ИтогВсеУровни); // вернет 8 502
Проанализируем две распространенные проблемы при расчете итогов в Дереве Значений:
ВключатьПодчиненные = Истина приведет к математическому удвоению суммы. В таком случае нужно либо вызывать метод с параметром Ложь (суммируя только промежуточные итоги родительских строк первого уровня), либо суммировать только конечные элементы («листья»).ДеревоЗначений недоступен на тонком клиенте. На форме используется реквизит с типом ДанныеФормыДерево, коллекция строк которого не имеет метода Итог(). Попытка вызвать метод на клиенте приведет к ошибке. Для расчета итога необходимо передать данные на сервер, сконвертировать их методом РеквизитФормыВЗначение() в объект ДеревоЗначений и выполнить расчет.