При работе с деревом значений на управляемых формах начинающие разработчики часто сталкиваются с проблемой получения конкретных данных строки. Обычный подход, работающий в плоских таблицах (обращение по индексу), здесь не применим из-за иерархической структуры. Разберем подробно, как правильно извлекать данные выбранной строки, используя механизмы платформы 1С v8.3.
В обработчике события Выбор (или при анализе текущей строки) платформа возвращает нам параметр ВыбраннаяСтрока. Важно понимать: это не порядковый номер строки в коллекции и не индекс массива. Это уникальный идентификатор строки в рамках текущего сеанса отображения формы.
Если мы попытаемся использовать этот идентификатор как индекс, например ТаблицаДерева.Строки[ВыбраннаяСтрока], система либо вернет ошибку, либо (что еще хуже) выдаст неверную строку. Это происходит потому, что Строки[0] всегда возвращает элемент только верхнего уровня, а идентификатор может принадлежать глубоко вложенному узлу.
Проанализируем основные способы решения этой задачи.
Это классический и самый надежный способ получения данных, когда у вас уже есть идентификатор строки (например, полученный из события Выбор или ПриАктивизацииСтроки). Рассмотрим пример кода в обработчике события выбора:
&НаКлиенте
Процедура ТаблицаДереваВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
// Получаем строку через реквизит формы (коллекцию данных), используя идентификатор
СтрокаДерева = Объект.ДеревоЗначений.НайтиПоИдентификатору(ВыбраннаяСтрока);
Если СтрокаДерева <> Неопределено Тогда
// Теперь мы можем обращаться к колонкам этой строки
Сообщить("Выбранная номенклатура: " + СтрокаДерева.Номенклатура);
// Можем получить родителя, если он есть
Родитель = СтрокаДерева.ПолучитьРодителя();
Если Родитель <> Неопределено Тогда
Сообщить("Родительский узел: " + Родитель.Наименование);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс: метод НайтиПоИдентификатору() нужно вызывать именно у реквизита формы (ваших данных), а не у элемента управления (визуальной таблицы на форме).
Если нам нужно получить данные той строки, на которой в данный момент находится курсор пользователя, метод НайтиПоИдентификатору() может быть избыточен. У элемента формы (таблицы) есть замечательное свойство ТекущиеДанные.
Проанализируем его использование:
&НаКлиенте
Процедура ОбработатьТекущуюСтроку()
// Обращаемся к элементу формы (визуальному объекту)
ДанныеСтроки = Элементы.ТаблицаДерева.ТекущиеДанные;
Если ДанныеСтроки = Неопределено Тогда
Возврат; // Строка не выбрана
КонецЕсли;
// Работаем с данными напрямую
ИмяОбъекта = ДанныеСтроки.Наименование;
КонецПроцедуры
Преимущество этого метода в его простоте и скорости. Нам не нужно знать идентификатор и выполнять поиск по коллекции. Однако помните, что ТекущиеДанные возвращают объект типа ДанныеФормыЭлементДерева.
Разберем важный технический момент. Когда мы работаем с деревом на форме, мы имеем дело не с объектом ДеревоЗначений, а с его экранной проекцией — реквизитом типа ДанныеФормыДерево. Соответственно, строка этого дерева имеет тип ДанныеФормыЭлементДерева.
Посмотрим на ключевые отличия в методах:
Родитель. Чтобы получить вышестоящий узел, необходимо использовать метод ПолучитьРодителя().ПолучитьЭлементы() вместо свойства Строки.В ситуациях, когда в дереве разрешено выделение нескольких строк (РежимВыделенияТаблицы.Множественный), параметр ВыбраннаяСтрока в событии Выбор все равно вернет только один идентификатор (тот, по которому кликнули). Чтобы обработать все выделенные строки, нужно проанализировать коллекцию ВыделенныеСтроки.
Рассмотрим пример обхода всех выделенных пользователем элементов:
&НаКлиенте
Процедура ОбработатьВыделенные()
МассивИдентификаторов = Элементы.ТаблицаДерева.ВыделенныеСтроки;
Для Каждого Идентификатор Из МассивИдентификаторов Цикл
ТекущаяСтрока = Объект.ДеревоЗначений.НайтиПоИдентификатору(Идентификатор);
Если ТекущаяСтрока <> Неопределено Тогда
// Выполняем полезные действия
Сообщить("Обработка строки: " + ТекущаяСтрока.Наименование);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Выясним причины возможных ошибок при программном заполнении дерева. Идентификаторы строк назначаются платформой динамически. Если вы программно очищаете дерево и заполняете его заново, все старые идентификаторы становятся недействительными.
Практический совет: если вам нужно сохранить "связь" с конкретной строкой между обновлениями данных, добавьте в дерево скрытую колонку УникальныйКлюч (например, содержащую ссылку на объект базы данных или сгенерированный GUID). В этом случае для поиска строки лучше использовать перебор или предварительную выгрузку в объект ДеревоЗначений через ДанныеФормыВЗначение(), где доступен метод Найти().
Для эффективной работы с деревом значений на управляемых формах следует придерживаться двух правил:
Элементы.ВашаТаблица.ТекущиеДанные.РеквизитДерево.НайтиПоИдентификатору(Идентификатор).Соблюдение этих простых принципов позволит избежать большинства ошибок, связанных с иерархической структурой данных в 1С.