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