К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как вывести дерево значений на обычную форму 1С

Разбираем, как вывести дерево значений на обычную форму 1С: добавление реквизита, элемента ДеревоЗначений, заполнение строк, настройка колонок и типичные ошибки.

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

Главная сложность задачи — правильно связать реквизит формы типа «ДеревоЗначений» с визуальным элементом и корректно заполнить строки программно. Если связь настроена неверно, форма открывается пустой или выдаёт ошибку при обращении к строкам дерева.

Ниже разобран полный цикл: создание реквизита, добавление элемента на форму, программное заполнение из запроса и вручную, настройка колонок и обработка событий. Примеры кода применимы к платформе 1С:Предприятие 8.2 и 8.3 в режиме обычного приложения.

Создание реквизита формы типа «ДеревоЗначений»

Первый шаг — добавить в форму реквизит, который будет хранить дерево. Откройте форму в конфигураторе, перейдите на закладку «Реквизиты» (или вызовите окно реквизитов формы через меню «Форма → Реквизиты») и добавьте новый реквизит, например с именем ДеревоНоменклатуры. В поле «Тип» выберите ДеревоЗначений.

После создания реквизита нужно описать его колонки. Это делается программно в событии ПриСозданииНаСервере не существует для обычных форм — используется событие ПриОткрытии() модуля формы. Колонки добавляются методом Колонки.Добавить():

Процедура ПриОткрытии()

ДеревоНоменклатуры.Колонки.Добавить("Наименование");

ДеревоНоменклатуры.Колонки.Добавить("Код");

ДеревоНоменклатуры.Колонки.Добавить("Цена");

КонецПроцедуры

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

Добавление элемента «Дерево значений» на форму

На обычной форме дерево отображается специальным элементом управления. Откройте форму в режиме конструктора, в меню выберите «Форма → Вставить элемент управления» (или используйте панель инструментов) и выберите тип «Дерево значений». Не путайте его с «Табличное поле» — табличное поле тоже может показывать дерево, если связать его с реквизитом типа ДеревоЗначений, но специализированный элемент работает корректнее с иерархией.

В свойствах элемента укажите ключевой параметр — «Данные». В нём выберите созданный реквизит ДеревоНоменклатуры. Именно это свойство связывает визуальный элемент с данными формы. Без этой связи элемент останется пустым независимо от того, как вы заполняете реквизит в коде.

После привязки данных настройте колонки элемента: в свойствах элемента откройте список колонок и добавьте нужные, указав для каждой путь к данным (имя колонки реквизита), заголовок и ширину. Первая колонка обычно содержит наименование — именно в ней отображаются значки разворачивания иерархии.

Порядок добавления элемента
  1. 1
    Откройте форму в конфигураторе и добавьте реквизит типа ДеревоЗначений
  2. 2
    Через «Форма → Вставить элемент управления» добавьте элемент «Дерево значений»
  3. 3
    В свойствах элемента в поле «Данные» выберите реквизит формы
  4. 4
    Настройте колонки элемента: путь к данным, заголовок, ширина
  5. 5
    В событии ПриОткрытии опишите колонки и заполните строки дерева
  6. 6
    Откройте форму в режиме Предприятия и проверьте отображение

Программное заполнение дерева значений

Заполнение вручную через Строки.Добавить()

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

// Корневой уровень

СтрокаГруппа = ДеревоНоменклатуры.Строки.Добавить();

СтрокаГруппа.Наименование = "Электроника";

// Дочерний уровень

СтрокаТовар = СтрокаГруппа.Строки.Добавить();

СтрокаТовар.Наименование = "Телевизор";

СтрокаТовар.Цена = 25000;

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

Заполнение из запроса с иерархией

Типовая задача — вывести иерархический справочник. Для этого запрос выполняется с типом обхода ПоГруппировкамСИерархией, а результат выгружается напрямую в дерево значений методом Выгрузить():

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ИТОГИ ПО

| Ссылка ТОЛЬКО ИЕРАРХИЯ";

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

ДеревоНоменклатуры = Результат.Выгрузить(

ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

Это самый быстрый способ: платформа сама строит вложенность по иерархии ссылок. Обратите внимание — после выгрузки тип реквизита остаётся ДеревоЗначений, а колонки создаются по полям запроса автоматически, поэтому ручное добавление колонок в ПриОткрытии в этом сценарии либо не нужно, либо должно выполняться после выгрузки.

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

Настройка отображения и поведения дерева

После вывода дерева обычно требуется донастроить его поведение. Основные свойства элемента «Дерево значений»:

  • Шапка — показывает или скрывает заголовки колонок;
  • ТолькоПросмотр — запрещает редактирование значений прямо в дереве;
  • ИзменятьСоставСтрок — разрешает или запрещает пользователю добавлять и удалять строки;
  • НачальноеОтображениеДерева — определяет, будут ли узлы развёрнуты при открытии (разворачивать все уровни, верхний уровень или не разворачивать).

Для программного разворачивания всех узлов используется метод элемента формы Развернуть() в цикле по строкам верхнего уровня, либо установка свойства начального отображения. Свёрнутое по умолчанию дерево с большим числом уровней удобнее для пользователя, чем полностью раскрытое.

Если дерево должно реагировать на выбор строки, назначьте обработчик события ПриАктивизацииСтроки элемента формы. В нём доступна текущая строка через ЭлементыФормы.ДеревоНоменклатуры.ТекущаяСтрока, из которой можно читать значения колонок и, например, показывать связанную информацию в соседних полях формы.

Если дерево строится из запроса с итогами по иерархии, в строках-группах поля ресурсов содержат суммы по подчинённым строкам. Это удобно для отчётных форм: можно сразу показать, например, сумму продаж по группе товаров без дополнительных вычислений.
ПЗ
Практическое замечание

Типичные ошибки и способы их устранения

Чаще всего разработчики сталкиваются с тремя проблемами. Первая — пустое дерево на форме при заполненном реквизите. Причина почти всегда в том, что у элемента формы не заполнено свойство «Данные» или указан другой реквизит. Проверьте привязку в палитре свойств.

Вторая ошибка — обращение к колонке, которая не создана. Если в коде написано Строка.Цена = 100, а колонка «Цена» не добавлена ни вручную, ни через выгрузку запроса, возникнет ошибка «Поле объекта не обнаружено». Порядок действий должен быть строгим: сначала колонки, потом строки.

Третья проблема — попытка использовать на обычной форме подход управляемых форм с реквизитом «ДеревоЗначений» и элементом «Дерево» через Элементы.Дерево.Строки. В обычных формах обращение идёт напрямую к реквизиту по имени (ДеревоНоменклатуры.Строки), а к элементу — через ЭлементыФормы. Смешение двух моделей приводит к синтаксическим ошибкам.

Типичные ошибки
01
Не заполнено свойство «Данные» у элемента формы — дерево визуально пустое, хотя реквизит заполнен
02
Добавление строк до создания колонок — ошибка «Поле объекта не обнаружено» при обращении к значениям
03
Использование синтаксиса управляемых форм (Элементы.ИмяДерева) в модуле обычной формы
04
Повторное заполнение дерева без вызова Строки.Очистить() — данные дублируются при каждом обновлении

Проверка результата и ограничения

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

Учитывайте ограничение производительности: дерево с десятками тысяч строк на обычной форме отрисовывается заметно медленнее таблицы. Для больших объёмов лучше показывать только верхние уровни и подгружать вложенные строки при разворачивании узла, либо пересмотреть структуру отображения в пользу табличного поля с группировкой.

Контрольные точки

Как проверить результат

Отображение дерева на форме
Норма

Видны строки, иконки разворачивания, заголовки колонок

Тревожный признак

Пустой элемент — проверьте свойство «Данные»

Работа иерархии
Норма

Узлы разворачиваются, вложенность соответствует источнику

Тревожный признак

Все строки на одном уровне — неверный тип обхода запроса

Повторное открытие формы
Норма

Данные корректны и не задваиваются

Тревожный признак

Дубли строк — нет очистки перед заполнением

Итог

Что важно запомнить

Вывод дерева на обычную форму состоит из четырёх шагов: реквизит типа ДеревоЗначений, элемент формы «Дерево значений» с привязкой через свойство «Данные», создание колонок и заполнение строк вручную или выгрузкой запроса с иерархией. Перед повторным заполнением очищайте строки, а при ошибках в первую очередь проверяйте привязку данных и порядок создания колонок.

Частые вопросы

Чем отличается вывод дерева на обычную и управляемую форму?

На обычной форме используется элемент «Дерево значений» с прямой привязкой к реквизиту через свойство «Данные», а обращение в коде идёт по имени реквизита. На управляемой форме дерево хранится в реквизите формы, данные передаются между клиентом и сервером, а доступ к элементу выполняется через коллекцию Элементы. Синтаксис и событийная модель заметно различаются.

Как развернуть все уровни дерева программно?

Пройдите циклом по строкам верхнего уровня и вызовите для элемента формы метод Развернуть(Строка, Истина) — второй параметр включает разворачивание всех подчинённых уровней. Альтернатива — установить в свойствах элемента начальное отображение дерева в значение «Разворачивать все уровни».

Почему после выгрузки запроса в дерево пропали колонки, добавленные вручную?

Метод Выгрузить() создаёт в дереве значений новый набор колонок по полям запроса. Если вы добавляли колонки до выгрузки, они либо заменяются, либо приводят к несоответствию структуры. Решение — выполнять выгрузку в отдельную переменную, а затем либо присвоить её реквизиту, либо добавлять дополнительные колонки уже после выгрузки.

Как найти строку в дереве по значению?

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

Можно ли редактировать данные прямо в дереве на форме?

Да, если у элемента не установлено свойство ТолькоПросмотр, а у колонок разрешено редактирование. Пользователь сможет менять значения ячеек, а события ПриИзменении и ПередОкончаниемРедактирования позволяют контролировать и проверять ввод. Для отчётных форм редактирование обычно отключают.

Что делать, если дерево с большим числом строк тормозит форму?

Ограничьте первоначальную загрузку верхними уровнями и подгружайте вложенные строки по событию ПередРазворачиванием. Также проверьте, не выполняется ли заполнение дерева в цикле с обращениями к базе данных на каждой итерации — выгрузка одним запросом всегда быстрее построчного чтения.