Почему в Дереве значений на форме не отображается четвертый уровень группировки и как это исправить?

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

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

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

Выясняем причину: в коде или в интерфейсе?

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

Для этого выполним пошаговую проверку с помощью встроенного отладчика 1С:

  1. Установим точку останова в коде сразу после строки присвоения данных элементу формы, например, на строке: ЭлементыФормы.Дерево.Значение = ДеревоРезультат;
  2. Запустим отладку и откроем форму. Когда выполнение программы остановится, выделим переменную ДеревоРезультат (или ЭлементыФормы.Дерево.Значение) и нажмем комбинацию клавиш Shift + F9 (Быстрый просмотр).
  3. В открывшемся окне вычислим выражение. Перейдем по ссылке свойства Строки.
  4. Пройдем вглубь по уровням: выберем любую строку первого уровня, зайдем в ее коллекцию Строки, затем перейдем на третий уровень и попробуем найти строки четвертого уровня.

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

Анализ логических ошибок при ручном построении дерева значений

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


СтрокаРодитель2 = СтрокаРодитель1.Строки.Добавить();
НайденныеСтроки_ = Таб.НайтиСтроки(Строка2);

Для каждого Строка3 Из НайденныеСтроки_ Цикл
    НоваяСтрока = СтрокаРодитель2.Строки.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка3);
КонецЦикла;

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

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


СтрокаРодитель2 = СтрокаРодитель1.Строки.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаРодитель2, Строка2); // Заполняем родительскую строку данными!

Во-вторых, критическая ошибка часто кроется в формировании структуры отбора для метода НайтиСтроки(). В коде автора поиск подчиненных строк осуществляется по структуре Строка2, которая содержит только колонки группировки третьего уровня:

НайденныеСтроки_ = Таб.НайтиСтроки(Строка2);

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

Для гарантированно точного поиска структура отбора на каждом последующем уровне вложенности должна быть составной и включать в себя ключевые поля всех предыдущих родительских уровней.

Проверяем дерево с помощью метода ВыбратьСтроку()

Если в процессе стандартной отладки вам неудобно кликать по вложенным коллекциям строк, существует отличный платформенный инструмент быстрого визуального анализа дерева значений. На точке останова в окне вычисления выражений (Shift + F9) введите следующую команду:

ДеревоРезультат.ВыбратьСтроку()

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

Интерфейсные причины: почему табличное поле скрывает уровни?

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

Элегантное решение: уход от вложенных циклов к механизму ИТОГИ в запросах

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

Давайте рассмотрим, как можно изящно и в одну строчку кода построить правильное четырехъярусное дерево значений напрямую из базы данных или из временной таблицы:


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

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

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

// Привязываем готовое дерево к элементу формы
ЭлементыФормы.Дерево.Значение = ДеревоРезультат;
ЭлементыФормы.Дерево.СоздатьКолонки();

Разберем подробнее, почему этот подход решает все проблемы с отображением уровней:

  1. Абсолютная надежность связей: Платформа берет на себя всю математическую и логическую работу по связыванию строк-родителей со строками-потомками. Ошибки адресации, пустые промежуточные строки или дублирование исключены на уровне платформенного ядра.
  2. Высокая производительность: Свертка данных и расчет итогов происходят на уровне СУБД или оптимизированного внутреннего алгоритма платформы, что работает в десятки раз быстрее, чем ручной перебор таблиц в цикле на встроенном языке.
  3. Легкость масштабирования: Если завтра вам потребуется добавить 5-й или 6-й уровень группировки (например, характеристики номенклатуры или документы движения), вам достаточно будет просто дописать одно поле в секцию ИТОГИ ПО вашего запроса. Никаких новых вложенных циклов писать не придется.

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

← На главную