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

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

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

Разберем подробный алгоритм решения этой задачи: как выгрузить данные табличной части в реквизит формы типа ДеревоЗначений, сформировать иерархию с подсчетом итоговых сумм с помощью запроса и организовать обратную запись отредактированных данных в документ.

Архитектура решения: разделение данных и формы

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

Процесс работы строится по следующей схеме:

  1. При открытии формы документа выполняется запрос к табличной части с использованием конструкции ИТОГИ СУММА(...) ПО ... ИЕРАРХИЯ.
  2. Результат запроса обходится с учетом иерархических группировок и загружается в реквизит формы ДЗИтоговыеЗатраты.
  3. Пользователь просматривает и редактирует данные в дереве значений на форме.
  4. При изменении данных в дереве выполняется обратная синхронизация: детальные строки перезаписываются в табличную часть Объект.ТЧИтоговыеЗатраты.

Шаг 1. Формирование дерева значений при открытии формы

Рассмотрим серверную процедуру ПриСозданииНаСервере. В ней мы выполняем запрос к табличной части текущего документа, группируем суммы по видам затрат и заполняем дерево значений формы.

Для конвертации реквизита формы в объект `ДеревоЗначений` и обратно применяются методы РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы().


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ТЧИтоговыеЗатраты.ВидыЗатрат КАК ВидыЗатрат,
        |   ТЧИтоговыеЗатраты.Сумма КАК Сумма
        |ИЗ
        |   Документ.Проекты.ТЧИтоговыеЗатраты КАК ТЧИтоговыеЗатраты
        |ГДЕ
        |   ТЧИтоговыеЗатраты.Ссылка = &ТекДок
        |ИТОГИ
        |   СУММА(Сумма)
        |ПО
        |   ВидыЗатрат ИЕРАРХИЯ";
        
    Запрос.УстановитьПараметр("ТекДок", Объект.Ссылка);
    
    Выборка = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией); 
    
    // Преобразуем реквизит формы в объект ДеревоЗначений для программного заполнения
    ДЗИтоговыеЗатратыРФВЗ = РеквизитФормыВЗначение("ДЗИтоговыеЗатраты");
    ДЗИтоговыеЗатратыРФВЗ.Строки.Очистить();
    
    // Обходим верхний уровень группировки (родительские узлы)
    Пока Выборка.Следующий() Цикл
        
        РодительскаяСтрока = ДЗИтоговыеЗатратыРФВЗ.Строки.Добавить();
        РодительскаяСтрока.ВидыЗатрат = Выборка.ВидыЗатрат;
        РодительскаяСтрока.Сумма = Выборка.Сумма;
        
        // Получаем детальные строки для текущей группы
        ВыборкаНижнийУровень = Выборка.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
        
        Пока ВыборкаНижнийУровень.Следующий() Цикл
            
            ПодчиненнаяСтрока = РодительскаяСтрока.Строки.Добавить();
            ПодчиненнаяСтрока.ВидыЗатрат = ВыборкаНижнийУровень.ВидыЗатрат;
            ПодчиненнаяСтрока.Сумма = ВыборкаНижнийУровень.Сумма;
            
        КонецЦикла;
        
    КонецЦикла;
    
    // Помещаем сформированное дерево обратно в реквизит формы
    ЗначениеВРеквизитФормы(ДЗИтоговыеЗатратыРФВЗ, "ДЗИтоговыеЗатраты");

КонецПроцедуры

На стороне клиента в обработчике ПриОткрытии зададим начальное отображение дерева на форме, чтобы все узлы автоматически разворачивались при открытии:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    Элементы.ДЗИтоговыеЗатраты.НачальноеОтображениеДерева = НачальноеОтображениеДерева.РаскрыватьВсеУровни;

КонецПроцедуры

Шаг 2. Запись изменений из дерева значений в табличную часть документа

Проанализируем процесс сохранения данных. Позиции верхнего уровня в дереве являются виртуальными (суммовыми итогами). В табличную часть документа должны попадать только конечные детальные строки. При изменении данных в дереве на форме запускаем процедуру перезаполнения табличной части объекта.


&НаСервере
Процедура ДЗИтоговыеЗатратыПриИзмененииНаСервере()
    
    ДЗИтоговыеЗатратыРФВЗ = РеквизитФормыВЗначение("ДЗИтоговыеЗатраты");
    
    // Очищаем табличную часть документа перед перезаполнением
    Объект.ТЧИтоговыеЗатраты.Очистить();
    
    // Обходим верхний уровень (группы)
    Для Каждого ГруппаИзДерева Из ДЗИтоговыеЗатратыРФВЗ.Строки Цикл
        
        // Обходим только дочерние детальные строки группы
        Для Каждого СтрокаЭлемента Из ГруппаИзДерева.Строки Цикл
            
            НоваяСтрокаТЧ = Объект.ТЧИтоговыеЗатраты.Добавить();
            НоваяСтрокаТЧ.ВидыЗатрат = СтрокаЭлемента.ВидыЗатрат;
            НоваяСтрокаТЧ.Сумма = СтрокаЭлемента.Сумма;
            
        КонецЦикла;
        
    КонецЦикла;

КонецПроцедуры

&НаКлиенте
Процедура ДЗИтоговыеЗатратыПриИзменении(Элемент)
    
    ДЗИтоговыеЗатратыПриИзмененииНаСервере();

КонецПроцедуры

Шаг 3. Оформление и выделение родительских узлов в дереве

Для более наглядного визуального разделения групп и детальных строк на управляемой форме рекомендуется использовать Условное оформление. Чтобы выделить жирным шрифтом или цветом только родительские узлы (верхний уровень), выполним следующие настройки:

  1. Добавим в реквизит формы ДЗИтоговыеЗатраты дополнительную колонку ЭтоГруппа с типом Булево.
  2. При обходе выборки запроса на сервере для строк верхнего уровня устанавливаем значение РодительскаяСтрока.ЭтоГруппа = Истина, а для подчиненных — ПодчиненнаяСтрока.ЭтоГруппа = Ложь.
  3. В свойствах формы открываем составное свойство УсловноеОформление и создаем новый элемент оформления:
    • Оформление: Шрифт -> Заголовок (или Шрифт с флагом Жирный), Цвет фона.
    • Условие: ДЗИтоговыеЗатраты.ЭтоГруппа Равно Истина.
    • Оформляемые поля: указываем колонки таблицы дерева ДЗИтоговыеЗатраты.

Этот подход позволяет гибко настраивать визуальное отображение группировок без использования устаревших событий вывода строк и с полным соблюдением стандартов разработки под управляемое приложение 1С.

← На главную