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