Как реализовать иерархическое отображение товаров в виде дерева значений в 1С

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

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

Различие между Таблицей Значений и Деревом Значений

Первое, что нам необходимо понять: обычная ТаблицаЗначений (на форме это ДанныеФормыКоллекция) принципиально не поддерживает иерархию. Она предназначена для линейных списков. Чтобы реализовать вложенность, необходимо использовать объект ДеревоЗначений (на форме — ДанныеФормыДерево).

Рассмотрим основные отличия:

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

Способ 1: Использование запроса с итогами (Оптимальный)

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

Разберем пример кода на стороне сервера:


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

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

Способ 2: Программное добавление строк (Ручное заполнение)

Если данные поступают не из запроса, а, например, из внешнего файла или API, нам придется формировать дерево вручную. Для этого используется обращение к коллекции элементов каждой строки.

Проанализируем алгоритм добавления уровней:


// Добавляем корневой элемент
НоваяГруппа = ДеревоТовары.ПолучитьЭлементы().Добавить();
НоваяГруппа.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Бытовая техника");

// Добавляем подчиненный элемент в эту группу
ПодчиненнаяСтрока = НоваяГруппа.ПолучитьЭлементы().Добавить();
ПодчиненнаяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Холодильник");
ПодчиненнаяСтрока.Количество = 10;

Этот метод удобен для небольших структур или когда логика вложенности сложнее, чем просто «Родитель — Ссылка» в справочнике.

Настройка элемента формы для отображения дерева

Даже если вы правильно заполнили реквизит ДанныеФормыДерево, на форме «плюсики» могут не появиться. Выясним причину и настроим визуальную часть:

  1. Вынесите реквизит (Дерево) на форму. Автоматически создастся элемент типа «Таблица».
  2. В свойствах этой таблицы проверьте путь к данным.
  3. Главное: Убедитесь, что одна из колонок установлена как «Колонка отображения иерархии». Обычно это первая колонка. В ее свойствах должно быть активно отображение кнопки развертывания.
  4. Если вы хотите, чтобы дерево изначально было развернуто, используйте метод Элементы.ИмяТаблицы.Развернуть(ИдентификаторСтроки, Истина).

Оптимизация: Работа с большими данными

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

Разберем, как это работает по шагам:

  1. При открытии формы загружаются только элементы верхнего уровня (корневые группы).
  2. Для каждой группы программно добавляется пустая «строка-заглушка». Это заставляет систему рисовать «плюсик» рядом с группой.
  3. При нажатии пользователем на «плюсик» срабатывает событие таблицы ПриРазвертывании.
  4. В этом событии мы проверяем, загружены ли реальные данные. Если нет — удаляем заглушку и подтягиваем из базы только тех «детей», которые относятся к данной группе.

Альтернативный вариант: Табличный документ

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

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


ТабДок.НачатьАвтогруппировкуСтрок();
// Вывод родительской строки
ОбластьГруппа = ТабДок.ПолучитьОбласть("Группа");
ТабДок.Вывести(ОбластьГруппа, 1, "Группировка1", Истина);

// Вывод вложенных строк с увеличением уровня
ОбластьСтрока = ТабДок.ПолучитьОбласть("Строка");
Для Каждого Стр Из СписокТоваров Цикл
    ТабДок.Вывести(ОбластьСтрока, 2, "Группировка1", Истина);
КонецЦикла;
ТабДок.ЗакончитьАвтогруппировкуСтрок();

Резюмируем: Для интерактивной работы с данными на форме (редактирование количества, выбор строк) лучше подходит ДеревоЗначений. Для формирования красивых печатных форм с иерархией — ТабличныйДокумент.

Используя данные подходы, вы сможете превратить обычную плоскую таблицу в удобный иерархический инструмент, соответствующий стандартам интерфейса 1С.

← На главную