Как получить строку дерева значений по идентификатору в управляемых формах 1С

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

При работе с деревом значений на управляемых формах начинающие разработчики часто сталкиваются с проблемой получения конкретных данных строки. Обычный подход, работающий в плоских таблицах (обращение по индексу), здесь не применим из-за иерархической структуры. Разберем подробно, как правильно извлекать данные выбранной строки, используя механизмы платформы 1С v8.3.

Суть проблемы: Идентификатор vs Индекс

В обработчике события Выбор (или при анализе текущей строки) платформа возвращает нам параметр ВыбраннаяСтрока. Важно понимать: это не порядковый номер строки в коллекции и не индекс массива. Это уникальный идентификатор строки в рамках текущего сеанса отображения формы.

Если мы попытаемся использовать этот идентификатор как индекс, например ТаблицаДерева.Строки[ВыбраннаяСтрока], система либо вернет ошибку, либо (что еще хуже) выдаст неверную строку. Это происходит потому, что Строки[0] всегда возвращает элемент только верхнего уровня, а идентификатор может принадлежать глубоко вложенному узлу.

Проанализируем основные способы решения этой задачи.

Способ 1: Использование метода НайтиПоИдентификатору()

Это классический и самый надежный способ получения данных, когда у вас уже есть идентификатор строки (например, полученный из события Выбор или ПриАктивизацииСтроки). Рассмотрим пример кода в обработчике события выбора:


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

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

Способ 2: Свойство ТекущиеДанные

Если нам нужно получить данные той строки, на которой в данный момент находится курсор пользователя, метод НайтиПоИдентификатору() может быть избыточен. У элемента формы (таблицы) есть замечательное свойство ТекущиеДанные.

Проанализируем его использование:


&НаКлиенте
Процедура ОбработатьТекущуюСтроку()
    
    // Обращаемся к элементу формы (визуальному объекту)
    ДанныеСтроки = Элементы.ТаблицаДерева.ТекущиеДанные;
    
    Если ДанныеСтроки = Неопределено Тогда
        Возврат; // Строка не выбрана
    КонецЕсли;
    
    // Работаем с данными напрямую
    ИмяОбъекта = ДанныеСтроки.Наименование;
    
КонецПроцедуры

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

Различия между ДанныеФормыЭлементДерева и СтрокаДереваЗначений

Разберем важный технический момент. Когда мы работаем с деревом на форме, мы имеем дело не с объектом ДеревоЗначений, а с его экранной проекцией — реквизитом типа ДанныеФормыДерево. Соответственно, строка этого дерева имеет тип ДанныеФормыЭлементДерева.

Посмотрим на ключевые отличия в методах:

  1. У строки дерева на форме нет свойства Родитель. Чтобы получить вышестоящий узел, необходимо использовать метод ПолучитьРодителя().
  2. Для получения подчиненных строк используется метод ПолучитьЭлементы() вместо свойства Строки.
  3. Идентификаторы строк уникальны для всего дерева. Это позволяет избежать путаницы при поиске вложенных элементов.

Множественное выделение строк

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

Рассмотрим пример обхода всех выделенных пользователем элементов:


&НаКлиенте
Процедура ОбработатьВыделенные()
    
    МассивИдентификаторов = Элементы.ТаблицаДерева.ВыделенныеСтроки;
    
    Для Каждого Идентификатор Из МассивИдентификаторов Цикл
        
        ТекущаяСтрока = Объект.ДеревоЗначений.НайтиПоИдентификатору(Идентификатор);
        
        Если ТекущаяСтрока <> Неопределено Тогда
            // Выполняем полезные действия
            Сообщить("Обработка строки: " + ТекущаяСтрока.Наименование);
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Рекомендации по оптимизации

Выясним причины возможных ошибок при программном заполнении дерева. Идентификаторы строк назначаются платформой динамически. Если вы программно очищаете дерево и заполняете его заново, все старые идентификаторы становятся недействительными.

Практический совет: если вам нужно сохранить "связь" с конкретной строкой между обновлениями данных, добавьте в дерево скрытую колонку УникальныйКлюч (например, содержащую ссылку на объект базы данных или сгенерированный GUID). В этом случае для поиска строки лучше использовать перебор или предварительную выгрузку в объект ДеревоЗначений через ДанныеФормыВЗначение(), где доступен метод Найти().

Заключение

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

  1. Если нужно быстро получить данные текущей строки под курсором — используйте Элементы.ВашаТаблица.ТекущиеДанные.
  2. Если у вас есть идентификатор из события — используйте РеквизитДерево.НайтиПоИдентификатору(Идентификатор).

Соблюдение этих простых принципов позволит избежать большинства ошибок, связанных с иерархической структурой данных в 1С.

← На главную