Как преобразовать строку с наименованием в ссылку в 1С без использования НайтиПоНаименованию?

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

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

Использование поискового запроса

Наиболее гибким и правильным с точки зрения архитектуры 1С является использование объекта Запрос. Запрос позволяет не только найти элемент, но и четко контролировать ситуацию, когда в базе данных присутствует несколько элементов с одинаковым наименованием. Рассмотрим ситуацию, когда нам нужно найти ссылку на товар по строковой переменной ИмяТовара.

Проанализируем пример кода для поиска единственного значения:


ТекстЗапроса = 
"ВЫБРАТЬ ПЕРВЫЕ 2
|	Номенклатура.Ссылка КАК Ссылка
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|	Номенклатура.Наименование = &Наименование";

Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Наименование", ИмяТовара);

РезультатЗапроса = Запрос.Выполнить();

Если Не РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Если Выборка.Количество() > 1 Тогда
        Сообщить("Найдено несколько элементов с таким наименованием!");
    КонецЕсли;
    
    Пока Выборка.Следующий() Цикл
        НужнаяСсылка = Выборка.Ссылка;
        Прервать; // Берем только первый найденный
    КонецЦикла;
КонецЕсли;

Использование конструкции ВЫБРАТЬ ПЕРВЫЕ 2 позволяет нам быстро понять, уникально ли наше наименование в системе. Если количество строк в результате равно двум, значит, в справочнике есть дубли, и логику поиска стоит уточнить (например, добавить поиск по родителю или коду).

Массовое преобразование строк в ссылки (Оптимизация)

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

  1. Подготовим массив уникальных строковых наименований, которые нужно сопоставить.
  2. Передадим этот массив в запрос для сопоставления с базой данных за один вызов.
  3. Выгрузим результат в объект Соответствие, где ключом будет наименование, а значением — найденная ссылка.

Рассмотрим реализацию этого подхода:


// Предположим, у нас есть ТаблицаДанных с колонкой "НаименованиеСтрокой"
МассивИмен = ТаблицаДанных.ВыгрузитьКолонку("НаименованиеСтрокой");

// Удалим дубли из массива для ускорения работы запроса
ОбщегоНазначенияКлиентСервер.СвернутьМассив(МассивИмен);

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	Номенклатура.Наименование КАК Наименование,
|	Номенклатура.Ссылка КАК Ссылка
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|	Номенклатура.Наименование В(&МассивИмен)";

Запрос.УстановитьПараметр("МассивИмен", МассивИмен);
ТаблицаСсылок = Запрос.Выполнить().Выгрузить();

// Заполняем соответствие для быстрого поиска в памяти
СоответствиеИмен = Новый Соответствие;
Для Каждого Строка Из ТаблицаСсылок Цикл
    СоответствиеИмен.Вставить(Строка.Наименование, Строка.Ссылка);
КонецЦикла;

// Теперь мы можем мгновенно получить ссылку для каждой строки таблицы
Для Каждого СтрокаТаблицы Из ТаблицаДанных Цикл
    СтрокаТаблицы.Ссылка = СоответствиеИмен[СтрокаТаблицы.НаименованиеСтрокой];
КонецЦикла;

Этот метод в десятки раз быстрее поиска "в лоб", так как минимизирует количество обращений к серверу СУБД. Важный нюанс: для того чтобы такой поиск работал быстро, реквизит Наименование (или любой другой, по которому идет поиск) должен быть проиндексирован в метаданных справочника.

Работа с Уникальным Идентификатором (GUID)

Иногда под "строкой" понимается строковое представление уникального идентификатора (GUID). В этом случае нам вообще не нужно выполнять поиск в базе данных через запросы. Мы можем сконструировать ссылку напрямую. Однако стоит учитывать, что полученная ссылка может быть "битой" (объекта с таким ID может не существовать в базе).

Посмотрим, как это сделать:


СтрокаGUID = "550e8400-e29b-41d4-a716-446655440000";
Попытка
    НовыйИдентификатор = Новый УникальныйИдентификатор(СтрокаGUID);
    СсылкаНаОбъект = Справочники.Номенклатура.ПолучитьСсылку(НовыйИдентификатор);
    
    // Проверим, существует ли такой объект на самом деле
    Если ОбщегоНазначения.СсылкаСуществует(СсылкаНаОбъект) Тогда
        // Работаем со ссылкой
    КонецЕсли;
Исключение
    Сообщить("Некорректный формат GUID");
КонецПопытки;

Поиск предопределенных элементов

Если в строке передается имя предопределенного элемента, заданного в конфигураторе, правильнее и быстрее всего использовать функцию ПредопределенноеЗначение(). Это системный механизм, который не требует написания запросов и работает максимально быстро.

Выясним, как получить ссылку по имени предопределенного узла:

Ссылка = ПредопределенноеЗначение("Справочник.Валюты.Доллар");

Использование Полнотекстового Поиска (ПП)

Если наименование в строке может содержать опечатки или вы знаете только часть названия, можно прибегнуть к механизму полнотекстового поиска. Это позволяет реализовать поиск, похожий на работу поисковых систем в интернете.

Рассмотрим пример использования программного интерфейса ПП:


СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок("Болтик М5", 10);
СписокПоиска.ОбластьПоиска.Добавить(Метаданные.Справочники.Номенклатура);
СписокПоиска.ПерваяЧасть();

Если СписокПоиска.Количество() > 0 Тогда
    Для Каждого Результат Из СписокПоиска Цикл
        НайденнаяСсылка = Результат.Значение;
        // Логика обработки найденного
    КонецЦикла;
КонецЕсли;

Типичные ошибки при поиске по строке

Проанализируем распространенную ошибку, упомянутую в обсуждении. При поиске через запрос крайне не рекомендуется использовать функции обрезки строк или приведения к регистру в условии ГДЕ или СОЕДИНЕНИЕ. Например, конструкция ПОДСТРОКА(Наименование, 1, 40) заставит СУБД игнорировать индексы и выполнять полное сканирование таблицы (Full Scan). Это приведет к значительным тормозам на больших объемах данных.

Основные правила эффективного преобразования:

Выбор конкретного метода зависит от ваших задач: для разового поиска идеально подойдет Запрос, для загрузки из Excel — пакетное сопоставление через Массив и Соответствие, а для системных констант — ПредопределенноеЗначение.

← На главную