Разработка и Конфигурация · 11 мин
Как получить элемент справочника в 1С
Как получить элемент справочника в 1С программно: НайтиПоКоду, НайтиПоНаименованию, НайтиПоРеквизиту, ссылки и запросы. Примеры кода и проверка результата.
Получение элемента справочника — одна из самых частых задач при разработке и доработке конфигураций 1С. Обработка проведения документа, загрузка данных из файла, синхронизация с внешней системой — почти везде нужно найти конкретную номенклатуру, контрагента или договор по известному значению и получить ссылку на него или его объект.
В языке 1С для этого существует несколько методов менеджера справочника: НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту(), а также универсальный способ через запрос. Выбор зависит от того, какие данные у вас есть на входе: код, наименование, значение реквизита или уникальный идентификатор.
Важно понимать разницу между ссылкой на элемент и объектом элемента. Ссылка — это лёгкий указатель, достаточный для записи в реквизиты документов и сравнения. Объект — полная копия данных элемента в памяти, нужная только для чтения реквизитов без запроса или для изменения элемента. Неоправданное получение объекта — типичная причина медленной работы обработок.
Что возвращают методы поиска: ссылка или объект
Все методы НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту() возвращают значение типа СправочникСсылка. Это не сами данные элемента, а указатель на него. Ссылку можно сравнивать, записывать в реквизиты, передавать в запросы — и всё это без обращения к данным в базе.
Чтобы прочитать реквизиты элемента через точку (например, Ссылка.Артикул), платформа неявно обращается к базе. Чтобы изменить элемент, нужно явно получить объект: Объект = Ссылка.ПолучитьОбъект(), затем изменить реквизиты и вызвать Объект.Записать(). Для массовых операций получение объекта в цикле — главный источник проблем с производительностью.
Поиск по коду: НайтиПоКоду()
Метод НайтиПоКоду() ищет элемент по значению кода. Это самый быстрый способ, потому что код индексирован. Синтаксис:
НайденнаяСсылка = Справочники.Номенклатура.НайтиПоКоду("000000123");
Если НайденнаяСсылка.Пустая() Тогда
Сообщить("Элемент с таким кодом не найден");
КонецЕсли;
У метода есть необязательные параметры: ПоискПоПолномуКоду (искать по полному коду с учётом префиксов, актуально при обмене между базами) и Родитель (искать только внутри указанной группы). Если коды в справочнике не уникальны в пределах подчинения, передача родителя сузит поиск и исключит ошибочные совпадения.
Обратите внимание на тип кода: если код числовой, передавать нужно число, если строковый — строку с ведущими нулями в том виде, в каком она хранится. Несовпадение типа или формата — частая причина «не находит элемент, хотя он есть».
Поиск по наименованию: НайтиПоНаименованию()
Метод НайтиПоНаименованию() ищет элемент по точному совпадению наименования. По умолчанию поиск идёт без учёта регистра не выполняется — сравнение точное, поэтому «Товар А» и «товар а» считаются разными значениями в зависимости от настроек сортировки базы.
Ссылка = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка", Истина);
Второй параметр — ТочноеСоответствие. Если передать Ложь, поиск выполнится по началу наименования, и метод вернёт первый подходящий элемент. Это удобно для автоподбора, но опасно в интеграциях: при частичном совпадении можно получить не тот элемент.
Поиск по реквизиту: НайтиПоРеквизиту()
Когда код и наименование не подходят, используется НайтиПоРеквизиту(ИмяРеквизита, Значение). Типичный пример — поиск контрагента по ИНН:
Ссылка = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7707083893");
Если Ссылка.Пустая() Тогда
// контрагента с таким ИНН нет — возможно, нужно создать
КонецЕсли;
Метод работает только с реквизитами, для которых в конфигураторе установлено свойство «Индексировать» (или реквизит входит в индекс). Если индекса нет, поиск будет работать, но медленно на больших справочниках — платформа выполнит полное сканирование таблицы. Для часто используемых полей поиска включите индексирование в конфигураторе.
Если реквизит составного типа, значение поиска должно совпадать по типу и значению. Поиск по табличной части этим методом невозможен — только запросом.
Получение элемента по уникальному идентификатору
Если известен GUID элемента (например, он пришёл из внешней системы или из параметра веб-сервиса), ссылку получают так:
УИ = Новый УникальныйИдентификатор("a1b2c3d4-e5f6-7890-abcd-ef1234567890");
Ссылка = Справочники.Номенклатура.ПолучитьСсылку(УИ);
Если Ссылка.ПолучитьОбъект() = Неопределено Тогда
Сообщить("Объект с таким идентификатором отсутствует в базе");
КонецЕсли;
Метод ПолучитьСсылку() формирует ссылку из GUID без проверки её существования. Поэтому проверка обязательна: если объекта нет, ПолучитьОбъект() вернёт Неопределено. Это же поведение используют для поиска «битых ссылок» в базе.
Поиск через запрос: когда методов менеджера недостаточно
Запрос нужен, когда условия поиска сложные: несколько реквизитов одновременно, поиск по табличной части, поиск по подстроке, отбор по пометке удаления. Запрос также эффективнее при массовой обработке — можно одним запросом найти ссылки для тысячи значений.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул = &Артикул
| И НЕ Номенклатура.ПометкаУдаления";
Запрос.УстановитьПараметр("Артикул", "АРТ-1001");
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
НайденнаяСсылка = Выборка.Ссылка;
КонецЕсли;
При массовом поиске поместите входные значения во временную таблицу и соедините её со справочником — это на порядки быстрее, чем вызывать НайтиПоРеквизиту() в цикле. Всегда добавляйте отбор по ПометкаУдаления, если помеченные элементы не должны участвовать в логике.
- 1Соберите входные значения (коды, артикулы, ИНН) в таблицу значений
- 2Поместите её во временную таблицу запроса
- 3Соедините временную таблицу со справочником по полю поиска
- 4Выгрузите результат и обрабатывайте найденные ссылки
- 5Для ненайденных значений предусмотрите журнал ошибок или создание элементов
Проверка результата и типичные сценарии ошибок
Любой поиск должен завершаться проверкой результата. Признак «не найдено» отличается в зависимости от способа: методы менеджера возвращают пустую ссылку (проверка Ссылка.Пустая()), запрос — отсутствие строк в выборке, ПолучитьОбъект() по несуществующей ссылке — Неопределено.
Если поиск «не находит» заведомо существующий элемент, проверьте: тип и формат искомого значения (строка с пробелами, лишние неразрывные пробелы из Excel), область поиска (элемент в другой группе, а передан родитель), пометку удаления и права доступа — при ограничении на уровне записей (RLS) элемент может быть просто недоступен текущему пользователю.
Отдельный случай — дубли. Если метод поиска возвращает «не тот» элемент, вероятно, в базе несколько элементов с одинаковым кодом в разных группах или с одинаковым наименованием. Для таких справочников переходите на поиск по гарантированно уникальному реквизиту или комбинации условий через запрос.
Как проверить результат поиска
Ссылка.Пустая() = Ложь
Пустая ссылка — элемент не найден, проверьте значение и тип
ПолучитьОбъект() вернул объект
Вернул Неопределено — объекта нет в базе
Реквизиты читаются, пометки удаления нет
Элемент помечен на удаление или недоступен из-за RLS
Выбор способа под задачу
Для разовой операции в пользовательском режиме или простой обработки достаточно методов менеджера — код короче и читаемее. Для интеграций и загрузок, где важны скорость и контроль дублей, используйте запросы с временными таблицами. Для сопоставления между базами надёжнее всего уникальный идентификатор или регистр соответствия.
Как выбрать способ поиска
Что важно запомнить
Методы менеджера возвращают ссылку и подходят для точечного поиска; запрос — для сложных условий и массовых операций. Всегда проверяйте результат на пустую ссылку или Неопределено, следите за типом искомого значения и индексированием реквизитов.
Частые вопросы
Чем отличается НайтиПоНаименованию от поиска запросом с условием ПОДОБНО?
НайтиПоНаименованию ищет по точному совпадению или по началу строки и возвращает один элемент. Условие ПОДОБНО в запросе позволяет искать по вхождению подстроки в любом месте наименования и вернуть все подходящие элементы, но работает медленнее и требует аккуратности с дублями.
Как получить элемент справочника в управляемой форме?
На клиенте методы менеджера недоступны. Вызовите серверную процедуру с контекстом «НаСервере» и выполните поиск там, вернув на клиент ссылку. Если элемент уже выбран в поле формы, его значение доступно напрямую как ссылка без поиска.
Почему НайтиПоКоду не находит элемент, который виден в списке?
Чаще всего причины: несовпадение типа кода (число вместо строки), ведущие нули в строковом коде, элемент находится в другой группе при переданном родителе, либо действуют ограничения прав на уровне записей. Проверьте точное значение кода через запрос.
Как найти элемент по значению табличной части?
Методы менеджера этого не умеют. Используйте запрос к табличной части справочника: выберите Ссылка из Справочник.Имя.ИмяТабличнойЧасти с условием по нужному полю. Учтите, что один элемент может вернуться несколько раз при совпадениях в разных строках.
Что быстрее: НайтиПоРеквизиту или запрос?
Для одного элемента по индексированному реквизиту скорость сопоставима. Запрос выигрывает при массовом поиске и сложных условиях, а также позволяет за один вызов получить и ссылку, и нужные реквизиты без дополнительных обращений к базе.
Как безопасно создать элемент, если поиск ничего не нашёл?
Проверьте пустую ссылку, затем создайте объект через Справочники.Имя.СоздатьЭлемент(), заполните реквизиты и вызовите Записать(). Чтобы избежать дублей при параллельной работе, перед созданием повторите поиск внутри транзакции или используйте уникальный индекс по полю поиска.