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