Стандартный вывод результата запроса в дерево значений часто выглядит перегруженным. По умолчанию, когда мы раскрываем уровни иерархии, данные распределяются по тем же колонкам, что и у родительских записей, создавая визуальную «кашу». Пользователи часто ожидают увидеть интерфейс, напоминающий отчеты СКД или структуру папок, где каждый уровень вложенности несет свою смысловую нагрузку и отображается в своем контексте. В этой статье мы разберем, как сделать работу с деревом значений профессиональной и эстетичной.
Рассмотрим стандартную ситуацию: у нас есть дерево с уровнями «Контрагент» -> «Заказ» -> «Номенклатура». Если выводить их просто в соответствующие колонки, то при развороте узла контрагента мы увидим пустые места или повторы в строках заказов. Наша задача — сделать так, чтобы данные нижнего уровня не конфликтовали визуально с данными верхнего, а дерево выглядело аккуратным и структурированным.
Этот способ основан на создании одной универсальной колонки, которая будет отображать основной текст для каждого уровня. Мы проанализируем ситуацию, когда нам нужно вывести разные типы данных в одной визуальной области.
Шаг 1. Подготовка структуры дерева значений.
Для начала создадим дерево значений программно и добавим в него служебные колонки: Уровень (для определения вложенности) и Представление (для вывода текста пользователю).
// Создаем объект ДеревоЗначений
ДеревоДанных = Новый ДеревоЗначений;
ДеревоДанных.Колонки.Добавить("ОбъектСвязи", Новый ОписаниеТипов("СправочникСсылка.Номенклатура", "ДокументСсылка.ЗаказПокупателя"));
ДеревоДанных.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
ДеревоДанных.Колонки.Добавить("Уровень", Новый ОписаниеТипов("Число"));
// Пример заполнения первого уровня (Контрагент)
НоваяСтрока = ДеревоДанных.Строки.Добавить();
НоваяСтрока.Уровень = 1;
НоваяСтрока.Представление = Строка(ВыборкаКонтрагент.Контрагент);
НоваяСтрока.ОбъектСвязи = ВыборкаКонтрагент.Контрагент;
// Пример заполнения второго уровня (Заказ)
ПодчиненнаяСтрока = НоваяСтрока.Строки.Добавить();
ПодчиненнаяСтрока.Уровень = 2;
ПодчиненнаяСтрока.Представление = "Заказ №" + ВыборкаЗаказ.Номер + " от " + Формат(ВыборкаЗаказ.Дата, "ДФ=dd.MM.yyyy");
ПодчиненнаяСтрока.ОбъектСвязи = ВыборкаЗаказ.Ссылка;
Шаг 2. Настройка на форме.
После выгрузки дерева в реквизит формы нам необходимо в элементе формы «Таблица» оставить видимой только колонку Представление. Остальные колонки (например, с суммами или количеством) можно оставить рядом. Таким образом, в основной колонке иерархии пользователь всегда будет видеть только актуальный текст для текущего уровня.
Разберем более продвинутый и удобный для пользователя метод. Он позволяет сохранить интерактивность (двойной клик по значению открывает нужный справочник или документ) и при этом достичь идеального внешнего вида.
Суть метода: Мы создаем отдельные колонки для каждого уровня, объединяем их в группу и управляем их видимостью в зависимости от уровня строки.
Контрагент, Заказ, Номенклатура и обязательную служебную колонку Уровень.Рассмотрим настройки условного оформления подробнее:
Уровень Равно 1, то для колонок Заказ и Номенклатура устанавливаем параметр «Видимость» в значение Ложь.Уровень Равно 2, то для колонок Контрагент и Номенклатура устанавливаем параметр «Видимость» в значение Ложь.Уровень Равно 3, то для колонок Контрагент и Заказ устанавливаем параметр «Видимость» в значение Ложь.Этот подход позволяет пользователю видеть данные именно в той колонке, где они должны быть, не загромождая при этом интерфейс лишними деталями на других уровнях. Для быстрого переноса настроенных правил оформления в программный код можно использовать обработку для декомпиляции условного оформления формы.
Если ваше дерево содержит тысячи записей, форма может открываться медленно. Проанализируем, как ускорить этот процесс с помощью события ПередРасширением.
Выясним причину замедления: 1С пытается отрисовать сразу всю структуру. Чтобы избежать этого, мы можем загружать только первый уровень. Для каждой строки первого уровня добавим пустую «строку-пустышку».
&НаКлиенте
Процедура ДеревоДанныхПередРасширением(Элемент, Строка, Отказ)
ТекущаяСтрока = ДеревоДанных.НайтиПоИдентификатору(Строка);
// Проверяем, загружены ли данные
Если ТекущаяСтрока.ПолучитьЭлементы().Количество() = 1
И ТекущаяСтрока.ПолучитьЭлементы()[0].Представление = "Загрузка..." Тогда
// Удаляем пустышку и вызываем серверную процедуру подгрузки
ТекущаяСтрока.ПолучитьЭлементы().Очистить();
ПодгрузитьПодчиненныеДанныеНаСервере(ТекущаяСтрока.ОбъектСвязи, Строка);
КонецЕсли;
КонецПроцедуры
Такой подход делает интерфейс мгновенным, так как данные запрашиваются из базы только в момент нажатия на «плюсик».
Чтобы дерево выглядело законченным, используем условное оформление для стилизации строк. Рассмотрим несколько правил оформления фона и шрифта:
WebЦвет.СветлоСерый). Это поможет пользователю визуально отделить группы.ПутьКДаннымКартинки таблицы формы укажем числовое поле из дерева. В зависимости от уровня будем присваивать индексы: 0 — для папки контрагента, 1 — для иконки документа, 2 — для иконки товара.Часто в деревьях требуется возможность выбора строк. Реализуем логику, при которой установка флажка у родителя отмечает всех детей. Посмотрим на пример кода в событии ПриИзменении флажка:
&НаСервере
Процедура УстановитьФлажкиРекурсивно(СтрокаДерева, ЗначениеФлага)
Для Каждого ПодчиненнаяСтрока Из СтрокаДерева.ПолучитьЭлементы() Цикл
ПодчиненнаяСтрока.Пометка = ЗначениеФлага;
// Рекурсивный вызов для всех уровней вложенности
УстановитьФлажкиРекурсивно(ПодчиненнаяСтрока, ЗначениеФлага);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ДеревоПометкаПриИзменении(Элемент)
ТекущаяСтрока = Элементы.ДеревоДанных.ТекущиеДанные;
УстановитьФлажкиРекурсивно(ТекущаяСтрока, ТекущаяСтрока.Пометка);
КонецПроцедуры
Резюме: Мы рассмотрели, как превратить стандартное дерево значений в мощный и красивый инструмент. Использование УсловногоОформления вместе с грамотной структурой ДанныеФормыДерево позволяет создавать интерфейсы, которые не уступают по качеству сложным отчетам и обеспечивают высокую скорость работы пользователя.