К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как выгрузить результат запроса в дерево значений в 1С

Пошаговая инструкция: как выгрузить результат запроса в дерево значений в 1С с помощью метода Выгрузить, группировок ИТОГИ и обхода строк дерева.

Выгрузка результата запроса в дерево значений — стандартный приём в 1С, когда данные нужно представить в иерархическом виде: номенклатура по группам, документы по контрагентам, остатки по складам и товарам. Вместо плоской таблицы вы получаете структуру «родитель — подчинённые строки», которую удобно выводить в форму, отчёт или обрабатывать программно.

Механизм строится на двух элементах: конструкции ИТОГИ ... ПО в тексте запроса и методе Выгрузить(ТипОбходаРезультатаЗапроса.ПоГруппировкамСИерархией). Если в запросе нет итогов или указан неправильный тип обхода, дерево не построится — вы получите либо плоскую таблицу, либо ошибку.

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

Базовый пример: запрос с итогами и выгрузка в дерево

Минимальный рабочий сценарий выглядит так. Запрос выбирает детальные записи и содержит секцию ИТОГИ ПО, где перечислены поля, по которым строится иерархия. Порядок полей в ИТОГИ ПО определяет уровни дерева: первое поле — верхний уровень, последнее — самый глубокий.

bsl
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| Товары.Склад КАК Склад,
| СУММА(Товары.Количество) КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК Товары
|СГРУППИРОВАТЬ ПО
| Товары.Номенклатура,
| Товары.Склад
|ИТОГИ ПО
| Товары.Номенклатура";

РезультатЗапроса = Запрос.Выполнить();
Дерево = РезультатЗапроса.Выгрузить(
 ТипОбходаРезультатаЗапроса.ПоГруппировкамСИерархией);

После выполнения переменная Дерево содержит объект ДеревоЗначений. На верхнем уровне — строки группировки по номенклатуре, внутри каждой — детальные строки по складам. Колонки дерева соответствуют полям выборки запроса.

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

Как устроена секция ИТОГИ ПО и почему без неё дерева не будет

Дерево значений строится только из итоговых записей запроса. Секция ИТОГИ ПО Поле1, Поле2 заставляет платформу сформировать для каждого уникального сочетания значений этих полей отдельную итоговую запись, внутрь которой вкладываются детальные строки.

Допустимы два варианта секции итогов:

  • ИТОГИ ПО Номенклатура — группировка по элементам; если поле ссылочного типа и ссылка — элемент иерархического справочника, иерархия групп справочника сама по себе не разворачивается, группировка идёт только по значению ссылки.
  • ИТОГИ ПО Номенклатура ИЕРАРХИЯ — группировка с разворачиванием иерархии справочника: в дереве появятся родительские группы справочника как промежуточные уровни.

Также доступна конструкция ИТОГИ СУММА(Количество) ПО ОБЩИЕ — она добавляет одну верхнюю строку с общим итогом по всей выборке. Её удобно использовать, когда нужен итог «всего» в корне дерева.

Разница между типами обхода результата запроса

Метод Выгрузить принимает три основных типа обхода, и выбор влияет на итоговую структуру.

Сравнение вариантов

Прямой

Все записи подряд, включая итоговые, в одну плоскую таблицу. Подходит, когда иерархия не нужна.

ПоГруппировкам

Только строки верхнего уровня группировок, без детальных записей внутри. Дерево получается усечённым.

ПоГруппировкамСИерархией

Полное дерево: итоговые строки всех уровней с вложенными детальными записями. Стандартный выбор для выгрузки в дерево значений.

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

Как обойти дерево значений после выгрузки

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

bsl
Процедура ОбойтиДерево(Строки, Уровень = 0)
 Для Каждого Строка Из Строки Цикл
  Сообщить(Строка.Номенклатура);
  ОбойтиДерево(Строка.Строки, Уровень + 1);
 КонецЦикла;
КонецПроцедуры;

ОбойтиДерево(Дерево.Строки);

У каждой строки дерева доступны свойства Родитель и Уровень(), что позволяет определять положение строки в иерархии. Итоговые строки можно отличить от детальных по заполненности полей: в строке группировки поля более глубоких уровней обычно пустые.

Если дерево нужно показать пользователю, его привязывают к элементу формы «Дерево значений» через реквизит формы соответствующего типа. Для управляемых форм данные передаются через РеквизитФормыВЗначение и ЗначениеВРеквизитФормы.

Порядок действий
  1. 1
    Сформируйте запрос с детальными полями и секцией ИТОГИ ПО по нужным измерениям
  2. 2
    Выполните запрос и получите РезультатЗапроса
  3. 3
    Вызовите Выгрузить с типом обхода ПоГруппировкамСИерархией
  4. 4
    Проверьте структуру: у строк верхнего уровня должны быть вложенные Строки
  5. 5
    Обойдите дерево рекурсивно или выведите его в форму

Типичные ошибки и ограничения метода

Типичные ошибки
01
Нет секции ИТОГИ в запросе — выгрузка даёт плоскую структуру без вложенности
02
Тип обхода ПоГруппировкам вместо ПоГруппировкамСИерархией — теряются детальные записи
03
Неверный порядок полей в ИТОГИ ПО — уровни дерева оказываются перепутаны
04
Ожидание иерархии справочника без ключевого слова ИЕРАРХИЯ — группы справочника не появляются как уровни
05
Попытка изменить колонки дерева после выгрузки без учёта типов — колонки дерева создаются по полям запроса, добавлять новые нужно до заполнения или аккуратно после

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

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

Проверка результата и альтернативные подходы

После выгрузки полезно убедиться, что структура соответствует ожиданиям. Быстрая проверка — пройти по дереву в отладчике и посмотреть количество уровней и вложенность строк.

Контрольные точки

Как проверить результат

Вложенность строк
Норма

У строк верхнего уровня коллекция Строки содержит детальные записи

Тревожный признак

У всех строк коллекция Строки пуста — дерево фактически плоское

Количество уровней
Норма

Число уровней совпадает с числом полей в ИТОГИ ПО плюс детальный уровень

Тревожный признак

Уровней меньше ожидаемого — проверьте тип обхода и секцию ИТОГИ

Значения итогов
Норма

В строках группировок ресурсы содержат суммы по вложенным строкам

Тревожный признак

Итоги пустые или равны NULL — проверьте агрегатные функции в запросе

Альтернатива выгрузке — прямой обход результата запроса выборкой: РезультатЗапроса.Выбрать(ТипОбходаРезультатаЗапроса.ПоГруппировкамСИерархией). Этот способ экономит память, так как данные читаются последовательно, но не даёт готовой структуры для формы. Выбор зависит от задачи: для отображения в форме — дерево, для разовой обработки больших объёмов — выборка.

Итог

Что важно запомнить

Дерево значений из запроса строится связкой ИТОГИ ПО в тексте запроса и Выгрузить с типом обхода ПоГруппировкамСИерархией. Обход выполняется рекурсивно через Строки. Для иерархии справочника добавляйте ключевое слово ИЕРАРХИЯ, а на больших данных контролируйте объём выборки.

Частые вопросы

Можно ли выгрузить в дерево значений без секции ИТОГИ?

Нет. Дерево формируется только из итоговых записей запроса. Без ИТОГИ ПО выгрузка даст плоскую структуру, аналогичную таблице значений, независимо от указанного типа обхода.

Чем отличается ИТОГИ ПО от СГРУППИРОВАТЬ ПО?

СГРУППИРОВАТЬ ПО сворачивает детальные записи в агрегированные строки — детали теряются. ИТОГИ ПО сохраняет детальные записи и добавляет над ними итоговые уровни, что и позволяет построить многоуровневое дерево.

Как получить в дереве группы иерархического справочника?

Используйте конструкцию ИТОГИ ПО Поле ИЕРАРХИЯ. Тогда родительские группы справочника станут промежуточными уровнями дерева. Без ключевого слова ИЕРАРХИЯ группировка идёт только по значению ссылки.

Почему в дереве только один уровень, хотя итоги заданы?

Чаще всего указан тип обхода ПоГруппировкам вместо ПоГруппировкамСИерархией. Первый вариант возвращает только строки верхнего уровня группировок без вложенных записей.

Как добавить в дерево колонку, которой нет в запросе?

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

Что выбрать для больших данных: Выгрузить или Выбрать?

Для больших выборок предпочтительнее Выбрать с обходом по группировкам — данные читаются последовательно и не копируются целиком в память. Выгрузить в дерево оправдан, когда структура нужна целиком, например для показа в форме.