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

Справочники и Данные · 10 мин

1С: как получить значение из справочника

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

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

Главное, что нужно понимать: в 1С различают ссылку на элемент справочника и объект — загруженную в память копию элемента. Для чтения реквизита чаще всего достаточно ссылки: платформа сама подтянет данные из базы. Получение объекта требуется только тогда, когда вы собираетесь изменять данные, и это более «тяжёлая» операция.

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

Обращение к реквизиту через ссылку

Самый простой случай — ссылка на элемент справочника у вас уже есть. Например, она хранится в реквизите документа или пришла как параметр в процедуру. Тогда значение любого реквизита читается «через точку»:

Контрагент = ДокументОбъект.Контрагент; // это ссылка

ИННКонтрагента = Контрагент.ИНН; // чтение реквизита

НаименованиеПолное = Контрагент.НаименованиеПолное;

Платформа при таком обращении выполняет неявное чтение данных из базы. Это удобно для одного-двух реквизитов, но в цикле по тысяче элементов каждый вызов «через точку» — отдельное обращение к базе, и код начнёт работать медленно. Для массовой обработки используйте запрос, о нём ниже.

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

Поиск элемента: НайтиПоКоду и НайтиПоНаименованию

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

// Поиск по коду

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

// Поиск по наименованию (точное совпадение)

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

// Поиск с учётом иерархии — внутри конкретной группы

Группа = Справочники.Номенклатура.НайтиПоНаименованию("Материалы");

Элемент = Справочники.Номенклатура.НайтиПоНаименованию("Краска белая", Истина, Группа);

Особенности поиска по наименованию

НайтиПоНаименованию ищет только точное совпадение строки, включая регистр в некоторых СУБД и лишние пробелы. Если наименование в базе «Краска белая » с пробелом в конце, поиск без пробела ничего не вернёт. Для неточного поиска используйте запрос с конструкцией ПОДОБНО.

Поиск по реквизиту

Метод НайтиПоРеквизиту("ИНН", "7707083893") работает только для реквизитов, у которых в конфигураторе установлено свойство «Индексировать». Иначе поиск будет выполняться полным перебором и на больших справочниках займёт заметное время.

Порядок действий при поиске элемента
  1. 1
    Определите, что известно: код, наименование или значение реквизита
  2. 2
    Вызовите соответствующий метод менеджера справочника
  3. 3
    Проверьте результат: СсылкаНайдена.Пустая() — значит, элемент не найден
  4. 4
    Только после проверки обращайтесь к реквизитам найденного элемента
  5. 5
    Если элемент не найден — решите: создать его, сообщить пользователю или пропустить

Получение значений запросом

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

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

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

"ВЫБРАТЬ

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

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

| Номенклатура.ЕдиницаИзмерения КАК Единица

|ИЗ

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

|ГДЕ

| Номенклатура.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", НоменклатураСсылка);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Ставка = Выборка.СтавкаНДС;

КонецЕсли;

Запрос также позволяет искать по части наименования через ГДЕ Наименование ПОДОБНО "%Краска%", фильтровать по нескольким условиям и сразу получать значения из связанных справочников через точку в тексте запроса — без дополнительных обращений к базе.

Способы получения значения

Через точку от ссылки

Подходит для 1–3 реквизитов одного элемента. Просто и читаемо, но в цикле даёт обращение к базе на каждый реквизит.

НайтиПоКоду / НайтиПоНаименованию

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

Запрос

Для массового чтения, сложных условий и поиска по части строки. Требует больше кода, но самый быстрый при обработке множества элементов.

Проверка результата и пустые ссылки

Частая причина падения кода — обращение к реквизиту пустой ссылки. Если НайтиПоКоду ничего не нашёл, он возвращает пустую ссылку, и попытка прочитать ПустаяСсылка.СтавкаНДС вернёт Неопределено или вызовет ошибку в зависимости от контекста. Всегда проверяйте результат поиска:

ЭлементСсылка = Справочники.Контрагенты.НайтиПоНаименованию(ИскомоеИмя);

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

Сообщить("Контрагент не найден: " + ИскомоеИмя);

Возврат;

КонецЕсли;

ИНН = ЭлементСсылка.ИНН;

Также учитывайте, что элемент может существовать, но быть помеченным на удаление. Проверяйте Ссылка.ПометкаУдаления, если логика не должна работать с «удалёнными» данными. И наоборот: НайтиПоНаименованию находит и помеченные элементы, что иногда приводит к неожиданным результатам при дублях наименований.

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

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

Результат НайтиПоКоду / НайтиПоНаименованию
Норма

Ссылка не пустая, Ссылка.Пустая() = Ложь

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

Пустая ссылка — элемент не найден, обращение к реквизитам даст ошибку

Пометка удаления
Норма

Ссылка.ПометкаУдаления = Ложь

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

Элемент помечен на удаление — используйте осознанно

Значение реквизита
Норма

Реквизит заполнен и имеет ожидаемый тип

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

Пустое значение или Неопределено — реквизит не заполнен в карточке

Когда нужен объект: ПолучитьОбъект()

Метод Ссылка.ПолучитьОбъект() загружает элемент целиком, включая табличные части, и нужен только для изменения данных. Для чтения реквизита вызывать его не следует: это лишняя нагрузка и риск блокировок.

// Изменение значения реквизита

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

КонтрагентОбъект.ИНН = "7707083893";

КонтрагентОбъект.Записать();

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

Типичные ошибки и ограничения

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

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

Ещё одно ограничение: в клиент-серверном варианте обращение к базе с тонкого клиента проходит через сервер, поэтому серверные вызовы в цикле особенно дороги. Выносите чтение данных справочников в серверные процедуры и по возможности получайте всё нужное одним запросом.

Итог

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

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

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

Чем ссылка отличается от объекта справочника?

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

Как получить значение из табличной части элемента справочника?

Через ссылку табличная часть недоступна. Используйте либо Ссылка.ПолучитьОбъект() с последующим обходом коллекции, либо запрос к таблице вида Справочник.ИмяСправочника.ИмяТабличнойЧасти — второй способ предпочтительнее для чтения.

НайтиПоНаименованию не находит элемент, хотя он есть. Почему?

Метод ищет точное совпадение. Проверьте лишние пробелы, регистр букв, неразрывные пробелы и то, не ищете ли вы внутри конкретной группы иерархического справочника. Для неточного поиска используйте запрос с ПОДОБНО.

Можно ли получить значение предопределённого элемента без поиска?

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

Что вернёт обращение к реквизиту, если элемент помечен на удаление?

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

Как быстро получить реквизиты сразу для списка ссылок?

Сформируйте запрос с условием Ссылка В (&СписокСсылок), передав массив или список значений как параметр. Один запрос вернёт все нужные реквизиты для всех элементов — это на порядок быстрее обхода с обращением через точку.