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

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

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

Как выгрузить иерархический справочник 1С в дерево: запрос с итогами по иерархии, обход выборки, выгрузка в дерево значений, файл и Excel.

Иерархический справочник в 1С хранит элементы и группы, связанные через реквизит «Родитель». Когда такой справочник нужно выгрузить — в дерево значений, файл, Excel или другую систему — важно не просто получить список записей, а сохранить структуру вложенности: кто в какой группе лежит и на каком уровне находится.

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

Материал ориентирован на платформу 1С:Предприятие 8.3 и типовые механизмы: запросы с конструкцией «ИТОГИ ПО ... ИЕРАРХИЯ», объект «ДеревоЗначений», стандартные средства выгрузки данных. Код приведён на встроенном языке и легко адаптируется под любой иерархический справочник — «Номенклатура», «Подразделения», «Статьи затрат» и другие.

Как устроена иерархия справочника и что именно нужно выгрузить

В иерархическом справочнике каждый элемент имеет системный реквизит «Родитель» — ссылку на группу (или элемент, если иерархия «элементов», а не «групп и элементов»). Корневые записи имеют пустого родителя. Глубина вложенности не ограничена платформой, поэтому обход должен быть либо рекурсивным, либо построенным на механизме иерархических итогов запроса.

Перед выгрузкой определите, что считать результатом: дерево на форме для пользователя, файл со структурой для внешней системы или плоская таблица с колонкой «Родитель» и «Уровень». От этого зависит инструмент: ДеревоЗначений, запись XML/JSON или табличный документ.

Выгрузка в дерево значений запросом с иерархическими итогами

Самый короткий путь — запрос с конструкцией «ИТОГИ ПО Родитель ИЕРАРХИЯ». Результат такого запроса можно выгрузить напрямую в ДеревоЗначений, и платформа сама построит вложенность строк без единой строки рекурсивного кода.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Код КАК Код,

| Номенклатура.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| НЕ Номенклатура.ПометкаУдаления

|

|УПОРЯДОЧИТЬ ПО

| Наименование

|ИТОГИ ПО

| Номенклатура.Ссылка ИЕРАРХИЯ";

РезультатЗапроса = Запрос.Выполнить();

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

Ключевой момент — параметр ОбходРезультатаЗапроса.ПоГруппировкамСИерархией в методе Выгрузить(). С обычным обходом «ПоГруппировкам» вложенность потеряется или дерево построится некорректно. Колонки дерева создаются автоматически по полям выборки.

Обратите внимание на сортировку: «УПОРЯДОЧИТЬ ПО Наименование» применится внутри каждого уровня, что обычно и требуется. Если нужен порядок «как в справочнике», используйте упорядочивание по иерархии — добавьте УПОРЯДОЧИТЬ ПО Ссылка ИЕРАРХИЯ.

Рекурсивный обход: когда запроса недостаточно

Иерархические итоги не подходят, если нужна нестандартная логика: выгрузить только одну ветку, пронумеровать уровни, вычислить путь вида «Группа/Подгруппа/Элемент» или отфильтровать элементы по условию, зависящему от предков. В этих случаях дерево строят рекурсивным обходом по родителям.

Процедура ДобавитьСтроки(СтрокиДерева, Родитель, Уровень)

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ Ссылка, Наименование

|ИЗ Справочник.Номенклатура

|ГДЕ Родитель = &Родитель И НЕ ПометкаУдаления

|УПОРЯДОЧИТЬ ПО Наименование";

Запрос.УстановитьПараметр("Родитель", Родитель);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Строка = СтрокиДерева.Добавить();

Строка.Ссылка = Выборка.Ссылка;

Строка.Наименование = Выборка.Наименование;

Строка.Уровень = Уровень;

ДобавитьСтроки(Строка.Строки, Выборка.Ссылка, Уровень + 1);

КонецЦикла;

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

Начальный вызов выполняется с пустой ссылкой родителя: ДобавитьСтроки(Дерево.Строки, Справочники.Номенклатура.ПустаяСсылка(), 0). Минус подхода — один запрос на каждый узел, поэтому на больших справочниках (десятки тысяч элементов) он заметно медленнее иерархических итогов. Компромисс — выбрать весь справочник одним запросом в таблицу значений и строить дерево поиском по отбору «Родитель» в памяти.

Вывод дерева на форму

На управляемой форме дерево отображается через реквизит типа «ДеревоЗначений» с элементом формы «Таблица», у которой свойство «Отображение» установлено в «Дерево». Дерево значений — несериализуемый между вызовами тип, поэтому его заполняют при создании формы или в серверной процедуре, а при необходимости хранения между вызовами конвертируют через РеквизитФормыВЗначение / ЗначениеВРеквизитФормы.

Если задача — просто показать пользователю справочник деревом, выгружать ничего не нужно: динамический список формы списка иерархического справочника уже умеет режим «Дерево» (свойство «СпособПросмотра»). Ручная выгрузка в ДеревоЗначений оправдана, когда к дереву нужно добавить вычисляемые колонки, объединить данные нескольких источников или изменить структуру.

Выгрузка дерева в файл: XML, JSON и Excel

Для обмена с внешними системами дерево сериализуют. В XML иерархия естественно ложится на вложенные узлы; в JSON — на вложенные массивы «Дети»/«Children». Обходят дерево рекурсивно по коллекции Строки каждой строки.

Функция СтрокуВСтруктуру(СтрокаДерева)

Результат = Новый Структура;

Результат.Вставить("Код", СтрокаДерева.Код);

Результат.Вставить("Наименование", СтрокаДерева.Наименование);

Результат.Вставить("GUID", XMLСтрока(СтрокаДерева.Ссылка));

Дети = Новый Массив;

Для Каждого ПодСтрока Из СтрокаДерева.Строки Цикл

Дети.Добавить(СтрокуВСтруктуру(ПодСтрока));

КонецЦикла;

Результат.Вставить("Дети", Дети);

Возврат Результат;

КонецФункции

Полученная структура преобразуется в JSON через ЗаписьJSON и ЗаписатьJSON. Для Excel проще не вложенность, а «лесенка»: выводите строки дерева в табличный документ обходом с отступом (пробелами или свойством «Отступ» области ячеек) либо добавьте колонки «Уровень» и «Родитель» — так структуру легко восстановить при загрузке обратно.

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

Порядок выгрузки в дерево значений
  1. 1
    Напишите запрос с «ИТОГИ ПО Ссылка ИЕРАРХИЯ» и нужными полями
  2. 2
    Выполните запрос и вызовите Выгрузить с параметром ПоГруппировкамСИерархией
  3. 3
    Проверьте, что в дереве появились вложенные строки (Строки.Количество() у корневых элементов)
  4. 4
    При необходимости обойдите дерево рекурсивно и сериализуйте в XML/JSON или выведите в табличный документ
  5. 5
    Проверьте результат на контрольной ветке с известной структурой

Проверка результата и типичные ошибки

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

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

Отдельная ловушка — зацикливание. Если данные повреждены и элемент ссылается родителем сам на себя или на своего потомка, рекурсивный обход уйдёт в бесконечный цикл и завершится переполнением стека. В рекурсивных алгоритмах добавляйте защиту: ограничение максимального уровня (например, 50) или соответствие уже посещённых ссылок.

Итог

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

Основной инструмент — запрос с «ИТОГИ ПО Ссылка ИЕРАРХИЯ» и выгрузка результата в ДеревоЗначений с обходом ПоГруппировкамСИерархией. Рекурсия нужна для нестандартной логики, файл получают рекурсивным обходом дерева с записью в XML/JSON, а для Excel сохраняют уровень и родителя в отдельных колонках.

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

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

Добавьте в запрос условие «Ссылка В ИЕРАРХИИ (&Группа)» — отбор вернёт саму группу и всех её потомков на любой глубине. Далее применяйте те же итоги по иерархии или рекурсивный обход, начиная с выбранной группы как корня.

Можно ли выгрузить дерево без программирования?

Частично. Список иерархического справочника можно вывести в табличный документ через «Ещё → Вывести список», но иерархия сохранится только визуально (отступами), без явной связи «родитель–потомок». Для машинно-читаемой структуры без кода не обойтись — нужен отчёт на СКД с иерархической группировкой или обработка.

Как построить дерево отчётом СКД без кода?

В схеме компоновки создайте группировку по полю «Ссылка» и в её свойствах укажите тип группировки «Иерархия». Отчёт сам построит дерево с раскрывающимися уровнями, а результат можно сохранить в табличный документ. Это удобно, когда выгрузка нужна аналитику, а не программисту.

Почему в выгрузке появились строки-дубли с пустыми данными?

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

Как сохранить порядок элементов «как в справочнике»?

Используйте в запросе «УПОРЯДОЧИТЬ ПО Ссылка ИЕРАРХИЯ» — записи будут следовать в порядке внутренней нумерации с учётом вложенности. Если нужен пользовательский порядок (например, реквизит «ПорядокСортировки»), упорядочивайте по нему — сортировка применится внутри каждого уровня дерева.

Что делать, если глубина дерева очень большая и рекурсия падает?

Замените рекурсию на итеративный обход с явным стеком (таблица или массив «текущих узлов») — он не ограничен глубиной стека вызовов. Либо используйте иерархические итоги запроса: там обход выполняет платформа, и ограничение на глубину рекурсии встроенного языка не действует.