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