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