К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как обратиться к элементу справочника в 1С

Как обратиться к элементу справочника 1С: поиск по коду, наименованию, реквизиту, методы НайтиПоКоду и НайтиПоНаименованию, работа со ссылкой и объектом.

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

Выбор способа зависит от того, что известно об элементе: если у вас есть код — используйте НайтиПоКоду, если наименование — НайтиПоНаименованию, если произвольный реквизит — НайтиПоРеквизиту. Когда элемент нужно не только найти, но и изменить, потребуется получить объект через метод ПолучитьОбъект(), внести изменения и записать.

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

Основные способы обращения к элементу справочника

Доступ к справочнику начинается с менеджера объекта — конструкции вида Справочники.ИмяСправочника. Имя справочника берётся из дерева конфигурации точно так, как оно задано в конфигураторе, с учётом регистра. Например, для справочника «Номенклатура» менеджер выглядит как Справочники.Номенклатура.

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

Поиск элемента по коду

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

НайденныйЭлемент = Справочники.Номенклатура.НайтиПоКоду("000000123");

Если НайденныйЭлемент.Пустая() Тогда

Сообщить("Элемент с таким кодом не найден");

Иначе

Сообщить("Найден: " + НайденныйЭлемент.Наименование);

КонецЕсли;

Обратите внимание на тип кода. Если код справочника числовой, передавайте число; если строковый — строку с учётом ведущих нулей. Несовпадение типа или длины строки — частая причина, когда элемент в базе есть, но поиск возвращает пустую ссылку.

Если справочник иерархический и коды могут повторяться в разных группах (при отключённой серии кодов «в пределах справочника»), метод имеет дополнительные параметры: поиск в пределах родителя и поиск по полному коду. Уточните настройки нумерации в конфигураторе перед тем, как полагаться на уникальность кода.

Поиск по наименованию и по реквизиту

Метод НайтиПоНаименованию() ищет точное совпадение строки. Поиск по части строки этим методом невозможен — для нечёткого поиска нужен запрос с конструкцией ПОДОБНО.

Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");

По умолчанию поиск идёт без учёта регистра в большинстве типовых настроек СУБД, но поведение зависит от параметров базы, поэтому не полагайтесь на это без проверки. Второй параметр метода — признак точного соответствия (по умолчанию Ложь, что допускает поиск по началу строки при определённых настройках), третий — родитель для иерархических справочников.

Когда известен не код и не наименование, а значение произвольного реквизита (ИНН, артикул, штрихкод), применяется НайтиПоРеквизиту():

Контрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7707083893");

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

Чтение реквизитов найденного элемента

Через ссылку доступно чтение любых реквизитов элемента «через точку»: код, наименование, пользовательские реквизиты, пометку удаления. Платформа автоматически выполняет обращение к базе данных и возвращает значение.

Товар = Справочники.Номенклатура.НайтиПоКоду("000000045");

Если Не Товар.Пустая() Тогда

Артикул = Товар.Артикул;

Единица = Товар.ЕдиницаИзмерения;

КонецЕсли;

Каждое обращение через точку к реквизиту ссылки — это отдельный запрос к базе. Если нужно прочитать много реквизитов одного элемента, эффективнее использовать запрос с выборкой полей за один раз либо получить объект. В циклах по тысячам элементов обращения «через точку» заметно замедляют код.

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

Изменение элемента: объект и запись

Ссылку изменить нельзя — она только указывает на элемент. Для правки получают объект методом ПолучитьОбъект(), изменяют реквизиты и вызывают Записать():

ТоварСсылка = Справочники.Номенклатура.НайтиПоКоду("000000045");

Если Не ТоварСсылка.Пустая() Тогда

ТоварОбъект = ТоварСсылка.ПолучитьОбъект();

ТоварОбъект.Артикул = "АРТ-100";

ТоварОбъект.Записать();

КонецЕсли;

Если элемент не найден и вызвать ПолучитьОбъект() у пустой ссылки, платформа вернёт значение Неопределено — попытка обратиться к его реквизитам вызовет ошибку. Поэтому проверка на пустую ссылку обязательна перед получением объекта.

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

Обращение к элементу через запрос

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Артикул КАК Артикул

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Наименование ПОДОБНО &ЧастьИмени";

Запрос.УстановитьПараметр("ЧастьИмени", "%кабель%");

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

Пока Результат.Следующий() Цикл

Сообщить(Результат.Артикул);

КонецЦикла;

Запрос возвращает ссылки и значения полей без загрузки объектов, поэтому работает быстро даже на больших таблицах. Но запрос не подходит для изменения данных — он только читает. Для правки найденных элементов всё равно придётся получать объекты по ссылкам из выборки.

Типовой порядок работы с элементом
  1. 1
    Определите, что известно об элементе: код, наименование, реквизит или условие
  2. 2
    Выберите метод: НайтиПоКоду, НайтиПоНаименованию, НайтиПоРеквизиту или запрос
  3. 3
    Проверьте результат на пустую ссылку через Пустая()
  4. 4
    Прочитайте реквизиты через точку или получите объект для изменения
  5. 5
    После правок вызовите Записать() и убедитесь, что изменения сохранились

Частые ошибки и их последствия

Типичная ошибка — сравнение результата поиска с Неопределено вместо проверки на пустую ссылку. Методы поиска не возвращают Неопределено, поэтому такое условие всегда ложно, и код идёт дальше с несуществующим элементом.

Вторая группа ошибок связана с типами: передача числа вместо строки при поиске по строковому коду, лишние пробелы в наименовании, поиск по реквизиту без учёта регистра. Третья — попытка присвоить значение реквизиту ссылки напрямую (ТоварСсылка.Артикул = "X"), что вызывает ошибку, потому что ссылка доступна только для чтения.

Типичные ошибки
01
Сравнение результата поиска с Неопределено вместо Пустая() — условие никогда не срабатывает, код работает с пустой ссылкой
02
Передача числового кода строкой или без ведущих нулей — элемент не находится, хотя существует
03
Попытка изменить реквизит через ссылку — ошибка исполнения, нужен ПолучитьОбъект()
04
Чтение реквизитов через точку в цикле по тысячам элементов — резкое падение производительности
05
НайтиПоНаименованию без проверки дублей — находится первый попавшийся элемент, а не нужный

Как проверить результат обращения

После поиска убедитесь, что ссылка не пустая, прежде чем обращаться к реквизитам. После записи объекта — что запись прошла без исключений, а реквизиты содержат ожидаемые значения. Если код выполняется в транзакции, помните: до её фиксации изменения не видны другим пользователям и откатятся при ошибке.

Контрольные точки

Как проверить результат

Результат метода поиска
Норма

Ссылка не пустая, реквизиты читаются без ошибок

Тревожный признак

Пустая ссылка — элемент не найден, проверьте тип и значение параметра

Вызов ПолучитьОбъект()
Норма

Возвращён объект, реквизиты доступны для записи

Тревожный признак

Возвращено Неопределено — ссылка была пустой

После Записать()
Норма

Метод выполнен без исключений, изменения видны в базе

Тревожный признак

Исключение — смотрите текст ошибки: заполненность реквизитов, уникальность кода, права доступа

Итог

Что важно запомнить

Обращение к элементу справочника идёт через менеджер Справочники.Имя: НайтиПоКоду, НайтиПоНаименованию или НайтиПоРеквизиту возвращают ссылку. Всегда проверяйте её на пустоту. Для чтения достаточно ссылки, для изменения нужен ПолучитьОбъект() и Записать(), а для массовых операций — запрос.

Частые вопросы

Чем отличается НайтиПоНаименованию от поиска запросом с ПОДОБНО?

НайтиПоНаименованию ищет точное совпадение строки и возвращает один элемент. Запрос с ПОДОБНО позволяет искать по части строки с шаблонами (% и _) и возвращает все подходящие записи. Для поиска «кабель» внутри длинных наименований подходит только запрос.

Что вернёт метод поиска, если подходящих элементов несколько?

Первый найденный элемент по порядку, который определяет СУБД, — заранее предсказать, какой именно, нельзя. Если дубли возможны (например, одинаковые наименования контрагентов), используйте запрос с отбором по дополнительным реквизитам, чтобы однозначно идентифицировать элемент.

Можно ли обратиться к элементу справочника на клиенте в управляемой форме?

Да. В управляемых формах методы поиска доступны в серверных и клиент-серверных процедурах. В тонком клиенте прямой вызов из клиентской процедуры недоступен — оберните поиск в процедуру с директивой &НаСервере или &НаСервереБезКонтекста.

Как получить элемент по уникальному идентификатору?

Используйте метод ПолучитьСсылку с объектом УникальныйИдентификатор: Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаGUID)). Этот способ применяется при обмене данными, когда идентификатор хранится во внешней системе.

Почему НайтиПоРеквизиту работает медленно?

Реквизит, по которому идёт поиск, не проиндексирован. Откройте конфигуратор, найдите реквизит и проверьте свойство «Индексировать». Для больших справочников без индекса поиск сканирует всю таблицу. Если изменять конфигурацию нельзя, используйте запрос и оценивайте его план.

Как проверить, существует ли элемент, не загружая его данные?

Достаточно выполнить поиск и проверить Пустая() у результата — сама проверка не загружает объект. Если известна ссылка и нужно убедиться, что элемент не удалён физически, сравните Ссылка.ПолучитьОбъект() с Неопределено или используйте запрос по ссылке.