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