Как обновить сумму в группах дерева значений 1С при изменении цены?

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

При работе с иерархическими структурами в 1С, такими как ДеревоЗначений, часто возникает задача пересчета итоговых показателей (например, цен или сумм) в родительских узлах при изменении значения в дочерней строке. Поскольку уровни вложенности могут быть динамическими, наиболее эффективным и надежным инструментом для решения этой задачи является рекурсия.

Разберем логику рекурсивного пересчета

Суть метода заключается в обходе дерева «в глубину». Мы проходим по всем подчиненным элементам, суммируем их значения и записываем результат в родительскую строку. Рассмотрим два основных подхода к реализации этой задачи.

Решение №1: Использование метода Итог

Если структура вашего дерева позволяет использовать встроенные функции, можно значительно упростить код. Метод Итог() коллекции строк ДеревоЗначений идеально подходит для получения суммы по указанной колонке на текущем уровне.

Разберем пример кода для рекурсивного пересчета:


Процедура РассчитатьСуммуЦенПодчиненныхСтрок(СтрокаРодитель)
    // Вычисляем итог по текущей ветке
    СтрокаРодитель.Цена = СтрокаРодитель.Строки.Итог("Цена", Ложь);
    
    // Рекурсивно переходим к подчиненным строкам
    Для Каждого СтрокаДерева Из СтрокаРодитель.Строки Цикл
        РассчитатьСуммуЦенПодчиненныхСтрок(СтрокаДерева);
    КонецЦикла;
КонецПроцедуры

Этот метод хорош тем, что он автоматически суммирует все дочерние элементы, независимо от того, сколько уровней вложенности содержится в узле.

Решение №2: Накопительный расчет по узлам

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

Посмотрим, как это выглядит на практике:


Процедура РасчитатьСуммыПоУзламДерева(СтрокиДерева) Экспорт
    Для Каждого СтрокаДерева Из СтрокиДерева Цикл
        // Если это группа (есть подчиненные строки), обнуляем сумму
        Если СтрокаДерева.Строки.Количество() > 0 Тогда
            СтрокаДерева.Сумма = 0;
        КонецЕсли;
        
        // Рекурсивный вызов для следующего уровня
        РасчитатьСуммыПоУзламДерева(СтрокаДерева.Строки);
        
        // Суммирование результатов после прохода по подчиненным узлам
        Если СтрокаДерева.Строки.Количество() > 0 Тогда
            Для каждого СтрокаИзСтрок Из СтрокаДерева.Строки Цикл
                СтрокаДерева.Сумма = СтрокаДерева.Сумма + СтрокаИзСтрок.Сумма;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Рекомендации по оптимизации

Чтобы ваша форма работала быстро и интерфейс не «зависал» при вводе данных, рекомендуем придерживаться следующих правил:

  1. Выбор события: Используйте событие ПриИзменении поля формы. Это позволит запускать пересчет сразу после редактирования конкретной ячейки.
  2. Точечный расчет: Если дерево содержит тысячи строк, нет смысла пересчитывать всё дерево целиком. Попробуйте подниматься вверх по иерархии через свойство Родитель, пересчитывая суммы только в ветке, затронутой изменениями.
  3. Обновление интерфейса: После того как серверный код отработал и изменил данные в ДеревеЗначений, не забудьте вызвать метод Элементы.ИмяВашегоДерева.Обновить(). В противном случае пользователь не увидит актуальные изменения на экране.
  4. Работа с массивами: При очень большой вложенности можно использовать вспомогательный массив для хранения итогов по уровням, где индекс массива соответствует уровню вложенности. Это позволяет пройти дерево за один проход, накапливая суммы для вышестоящих узлов.

Применяя данные алгоритмы, вы сможете легко управлять сложными иерархическими структурами в своих разработках. Главное — помнить, что при работе с рекурсией важно следить за корректностью выхода из процедуры, чтобы избежать ошибок переполнения стека в случае циклической ссылочности (чего в стандартных деревьях 1С обычно не бывает, но важно помнить об архитектуре данных).

← На главную