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