Как найти элемент справочника по наименованию, если имя справочника задано строкой?

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

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

Динамическое обращение к менеджеру справочника через квадратные скобки

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

Посмотрим на базовый пример обращения и вызова стандартного метода поиска:


ИмяСправочника = "Контрагенты";
ИскомоеНаименование = "ООО Ромашка";

СсылкаНаОбъект = Справочники[ИмяСправочника].НайтиПоНаименованию(ИскомоеНаименование, Истина);

Такой синтаксис полностью аналогичен прямому обращению через точку, но дает возможность динамически подставлять имя целевого объекта во время выполнения кода.

Безопасная проверка существования объекта метаданных

Проанализируем потенциальную проблему: если строковая переменная с именем справочника получена из внешнего источника (файла Excel, XML, JSON) или введена пользователем в интерфейсе, в ней может оказаться опечатка или имя несуществующего объекта. Прямое обращение Справочники[ИмяСправочника] в этом случае немедленно вызовет исключение времени выполнения.

Чтобы избежать аварийного завершения работы алгоритма, разберем прием предварительной проверки через коллекцию метаданных:


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

Особенности и ограничения метода «НайтиПоНаименованию»

Метод менеджера НайтиПоНаименованию прост в использовании, однако при его применении важно учитывать следующие критические нюансы:

  1. Параметр точного соответствия: Второй параметр метода (ТочноеСоответствие) по умолчанию имеет значение Ложь. Это означает, что платформа ищет элемент по вхождению с начала строки. Например, при попытке найти «Кабель» метод может вернуть «Кабель силовой 3х1.5». Чтобы найти строгое совпадение, всегда явно передавайте вторым параметром Истина.
  2. Помеченные на удаление элементы: Метод возвращает первую найденную ссылку, игнорируя признак пометки на удаление. Если в информационной базе присутствует дубль, помеченный на удаление, метод может вернуть именно его.
  3. Наличие дубликатов: Если в базе существует несколько элементов с идентичным наименованием, метод вернет первый попавшийся объект согласно внутреннему порядку СУБД, никак не предупредив разработчика о наличии неоднозначности.
  4. Иерархия и подчинение: Для иерархических или подчиненных справочников поиск без явного указания третьего (Родитель) или четвертого (Владелец) параметров выполняется по всей таблице без учета структуры.
  5. Ограничение длины строки: Если длина искомой текстовой строки превышает установленную в конфигураторе длину реквизита Наименование, строка поиска автоматически усекается до максимальной длины.

Альтернативный вариант: динамический запрос

Когда требуется обойти ограничения стандартного метода, исключить удаленные объекты или выявить дубликаты, рассмотрим построение динамического запроса. В тексте запроса имя таблицы конкатенируется с переменной имени справочника:


Если Метаданные.Справочники.Найти(ИмяСправочника) <> Неопределено Тогда
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Спр.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник." + ИмяСправочника + " КАК Спр
        |ГДЕ
        |	Спр.Наименование = &Наименование
        |	И НЕ Спр.ПометкаУдаления";
    
    Запрос.УстановитьПараметр("Наименование", ИскомоеНаименование);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        СсылкаНаОбъект = Выборка.Ссылка;
    Иначе
        СсылкаНаОбъект = Справочники[ИмяСправочника].ПустаяСсылка();
    КонецЕсли;
КонецЕсли;

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

Производительность и индексирование реквизита

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

  1. Откроем свойства нужного справочника в дереве метаданных.
  2. Перейдем на вкладку «Данные» и откроем свойства стандартного реквизита Наименование.
  3. Проверим свойство «Индексирование»: если там установлено значение «Не индексировать», СУБД при каждом поиске будет выполнять полное сканирование таблицы. Для справочников с десятками и сотнями тысяч записей обязательно должно быть включено индексирование (значение «Индексировать» или «Индексировать с доп. упорядочиванием»).
← На главную