При разработке управляемых форм разработчики часто сталкиваются с ситуацией, когда в свойствах таблицы формы переключатель Отображение установлен в значение Дерево, однако данные все равно отображаются обычным плоским списком, а кнопки разворачивания («плюсы») не появляются. Рассмотрим подробно, почему так происходит и как реализовать полноценный иерархический вывод на форме.
Проанализируем техническое устройство платформы 1С. Объект метаданных ТабличнаяЧасть (в составе документа, справочника или обработки) всегда является двумерной таблицей. На управляемой форме реквизит, связанный с табличной частью объекта (например, Объект.ТабличнаяЧасть), имеет тип ДанныеФормыКоллекция.
Эта коллекция физически не поддерживает подчиненность строк и иерархические связи. Даже если в свойствах элемента формы активировать режим отображения дерева, платформа не сможет определить родительские и дочерние элементы, так как структура данных остается плоской (аналог ТаблицаЗначений).
При попытке загрузить результат запроса с итогами или объект ДеревоЗначений напрямую в табличную часть объекта возникнет ошибка несоответствия типов данных.
Выясним, как правильно организовать иерархический вывод. Для отображения дерева на управляемой форме необходимо использовать отдельный реквизит формы, не связанный напрямую с табличной частью объекта метаданных.
Разберем по шагам процесс создания и заполнения дерева:
В редакторе формы перейдем на вкладку Реквизиты (в правой панели) и создадим новый реквизит формы. Укажем для него тип ДеревоЗначений. В контексте формы данный реквизит получит тип ДанныеФормыДерево. Добавим внутрь реквизита необходимые колонки с нужными типами данных.
Перетащим созданный реквизит-дерево в левую панель элементов формы. Платформа автоматически создаст элемент типа ТаблицаФормы. В свойствах созданной таблицы убедимся, что свойство Отображение установлено в значение Дерево или Иерархический список.
Выполним запрос с иерархическими итогами или группировками. Выгрузим результат запроса в дерево значений, после чего свяжем полученные данные с реквизитом формы с помощью функции ЗначениеВРеквизитФормы.
Посмотрим на практический пример кода, выполняемого на сервере:
&НаСервере
Процедура ЗаполнитьДеревоНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| Номенклатура.Родитель КАК Родитель
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ИТОГИ ПО
| Родитель ИЕРАРХИЯ";
РезультатЗапроса = Запрос.Выполнить();
// Выгружаем результат запроса с указанием обхода по группировкам
ДеревоРезультат = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
// Переносим данные из ДереваЗначений в реквизит формы
ЗначениеВРеквизитФормы(ДеревоРезультат, "ДеревоНаФорме");
КонецПроцедуры
При работе с деревьями значений на управляемых формах следует учитывать несколько ключевых правил:
1. Совпадение колонок: Для корректной работы метода ЗначениеВРеквизитФормы имена и типы колонок в исходном ДеревеЗначений должны строго совпадать со составом колонок реквизита формы ДанныеФормыДерево. Если структура колонок формируется динамически, реквизиты формы предварительно необходимо изменять через метод ИзменитьРеквизиты().
2. Сохранение данных обратно в объект: Если иерархические данные требуется сохранять в базe данных (в плоскую табличную часть объекта), перед записью выполняется обратная процедура: данные реквизита формы переводятся в объект вызовом РеквизитФормыВЗначение, после чего дерево рекурсивно обходится и сворачивается в плоскую коллекцию Объект.ТабличнаяЧасть с сохранением ключей связи (например, колонок КлючСтроки и КлючРодителя).