Как программно добавить строку в дерево значений в 1С

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

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

Выясняем причину: разница между Обычными и Управляемыми формами

Главная причина, по которой стандартные методы добавления строк могут «не работать», кроется в архитектурных различиях платформ 1С. Проанализируем, как ведет себя дерево значений в разных интерфейсных подсистемах:

  1. В обычных формах (платформа 1С 8.1 и 8.2) элемент управления на форме напрямую связан с объектом базы данных ДеревоЗначений. Этот объект доступен везде, и работа с ним происходит напрямую как на стороне клиента, так и на сервере.
  2. В управляемых формах (платформа 1С 8.2 и 8.3) действует строгая клиент-серверная архитектура. Объект типа ДеревоЗначений существует только на сервере. На клиенте данные дерева представлены специальным типом-оболочкой — ДанныеФормыДерево, а его строки имеют тип ДанныеФормыЭлементДерева. Попытка вызвать классические серверные методы или создать новый объект дерева на клиенте приведет к ошибке выполнения программы.

Рассмотрим детально, как решать задачу добавления строк в обоих случаях.

Решение для Обычных форм (1С 8.1 / 8.2)

В обычных формах работа со строками дерева предельно проста. Мы обращаемся напрямую к свойству Строки объекта. Разберем по шагам пример добавления корневой строки и подчиненной строки:


// Шаг 1. Добавление новой строки на самый верхний (корневой) уровень дерева
НоваяСтрока = Дерево.Строки.Добавить(); 
НоваяСтрока.Наименование = "Корневой элемент";

// Шаг 2. Добавление подчиненной строки к текущей выделенной строке
ТекущаяСтрока = ЭлементыФормы.ТабличноеПолеДерево.ТекущаяСтрока;
Если ТекущаяСтрока <> Неопределено Тогда
    НоваяПодчиненная = ТекущаяСтрока.Строки.Добавить();
    НоваяПодчиненная.Наименование = "Подчиненный элемент";
КонецЕсли;

В данном сценарии платформа автоматически обновляет отображение дерева на форме сразу после выполнения кода.

Решение для Управляемых форм на Клиенте (1С 8.2 / 8.3)

В управляемом интерфейсе напрямую обратиться к свойству Строки на клиенте нельзя. Вместо этого у объекта типа ДанныеФормыДерево используется метод ПолучитьЭлементы(). Рассмотрим примеры работы на клиенте.

Вариант 1. Добавление строки на корневой уровень дерева:


// "ИмяРеквизитаДерева" — это имя реквизита вашей управляемой формы с типом ДанныеФормыДерево
НоваяСтрока = ИмяРеквизитаДерева.ПолучитьЭлементы().Добавить();
НоваяСтрока.ИмяКолонки = "Значение корневого уровня";

Вариант 2. Добавление подчиненной строки (внутрь выделенной пользователем строки):

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


// Получаем уникальный идентификатор текущей строки в таблице формы
ТекущаяСтрокаID = Элементы.ИмяТаблицыФормы.ТекущаяСтрока;

Если ТекущаяСтрокаID <> Неопределено Тогда
    // Находим элемент коллекции данных по полученному идентификатору
    РодительскийЭлемент = ИмяРеквизитаДерева.НайтиПоИдентификатору(ТекущаяСтрокаID);
    
    // Добавляем подчиненную строку в коллекцию родителя
    НоваяПодчиненнаяСтрока = РодительскийЭлемент.ПолучитьЭлементы().Добавить();
    НоваяПодчиненнаяСтрока.ИмяКолонки = "Значение подчиненного уровня";
КонецЕсли;

Переопределение стандартного добавления (событие ПередДобавлением)

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

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


&НаКлиенте
Процедура ТаблицаДереваПередДобавлением(Элемент, Отказ, Копирование, Родитель, Группа, Параметр)
    
    // 1. Отменяем стандартный алгоритм добавления строки платформой
    Отказ = Истина; 
    
    // 2. Программно добавляем новую строку на самый верхний уровень дерева
    НоваяСтрока = ИмяРеквизитаДерева.ПолучитьЭлементы().Добавить();
    НоваяСтрока.ИмяКолонки = "Новая корневая строка";
    
    // 3. Устанавливаем фокус на добавленную строку для удобства редактирования пользователем
    Элементы.ТаблицаДерева.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
    
КонецПроцедуры

Добавление строк в серверном контексте

Когда требуется заполнить дерево большим объемом данных (например, результатами сложного запроса), всю работу следует переносить на сервер. В управляемом приложении на сервере мы можем использовать два принципиально разных подхода.

Подход А: Прямая работа с ДанныеФормыДерево на сервере

Этот способ удобен, когда структура дерева уже создана на форме и нам нужно просто быстро добавить несколько строк. На сервере объект ДанныеФормыДерево сохраняет свои свойства, поэтому код аналогичен клиентскому:


&НаСервере
Процедура ДобавитьСтрокуНаСервере()
    // Добавляем строку напрямую в реквизит формы на сервере
    НоваяСтрока = ИмяРеквизитаДерева.ПолучитьЭлементы().Добавить();
    НоваяСтрока.ИмяКолонки = "Данные, заполненные на сервере";
КонецПроцедуры

Подход Б: Конвертация данных формы в объект ДеревоЗначений и обратно

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


&НаСервере
Процедура ЗаполнитьДеревоСПреобразованием()
    // 1. Конвертируем реквизит формы типа ДанныеФормыДерево в стандартный объект ДеревоЗначений
    ДеревоОбъект = РеквизитФормыВЗначение("ИмяРеквизитаДерева");
    
    // 2. Теперь мы можем работать с ним, используя классические методы дерева значений
    НоваяСтрока = ДеревоОбъект.Строки.Добавить();
    НоваяСтрока.ИмяКолонки = "Данные";
    
    // Добавляем дочерний элемент стандартным серверным методом
    Подчиненная = НоваяСтрока.Строки.Добавить();
    Подчиненная.ИмяКолонки = "Подчиненные данные";
    
    // 3. Выгружаем измененный объект обратно в реквизит формы для визуализации на клиенте
    ЗначениеВРеквизитФормы(ДеревоОбъект, "ИмяРеквизитаДерева");
КонецПроцедуры

Альтернативный метод: использование функции Вставить()

Помимо стандартного метода Добавить(), который всегда помещает новую строку в самый конец текущего уровня иерархии, разработчики могут использовать метод Вставить(). Он позволяет добавить строку в строго определенное место по индексу (нумерация индексов всегда начинается с 0).

Рассмотрим пример, когда необходимо добавить элемент в самое начало списка на верхнем уровне:


// Вставляем новую строку в начало коллекции (индекс 0)
НоваяСтрока = ИмяРеквизитаДерева.ПолучитьЭлементы().Вставить(0);
НоваяСтрока.ИмяКолонки = "Я буду первой строкой в списке!";

Использование этого метода позволяет гибко управлять сортировкой и позиционированием элементов дерева в процессе интерактивной работы пользователя.

← На главную