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

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

Как в 1С программно получить данные из справочника

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

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

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

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

Объектная модель: менеджер, ссылка и объект справочника

Работа со справочником в коде строится через три сущности. Менеджер справочника доступен как Справочники.ИмяСправочника и предоставляет методы поиска и создания элементов. Ссылка (СправочникСсылка) — это лёгкий указатель на элемент: через неё можно обращаться к реквизитам через точку, но при первом обращении к каждому реквизиту выполняется обращение к базе данных.

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

Пример чтения реквизита через ссылку без получения объекта:

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

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

ИНН = Контрагент.ИНН;

КонецЕсли;

Как найти элемент по коду и наименованию

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

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

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

// Поиск по наименованию с учётом родителя

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

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

У НайтиПоНаименованию() второй параметр отвечает за точное соответствие: Истина — поиск по полному совпадению, Ложь — по началу наименования. Третьим параметром можно передать ссылку на родителя для поиска внутри конкретной группы, четвёртым — владельца, если справочник подчинённый.

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

Типичные ошибки
01
Поиск по наименованию без проверки дублей: при нескольких совпадениях возвращается произвольный элемент, и логика работает непредсказуемо.
02
Отсутствие проверки на пустую ссылку: обращение к реквизитам несуществующего элемента приводит к ошибке выполнения или пустым значениям.
03
Использование НайтиПоНаименованию с параметром Ложь и ожидание точного совпадения: поиск идёт по началу строки, и найденный элемент может отличаться от нужного.

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

Если известен GUID элемента — например, он сохранён в другой системе, регистре сведений или передан через веб-сервис, — ссылку получают методом ПолучитьСсылку():

УИД = Новый УникальныйИдентификатор("b2c3d4e5-...");

СсылкаНаЭлемент = Справочники.Номенклатура.ПолучитьСсылку(УИД);

Если СсылкаНаЭлемент.ПолучитьОбъект() = Неопределено Тогда

// Элемента с таким GUID в базе нет

КонецЕсли;

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

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

Выборка элементов: перебор справочника в цикле

Метод Выбрать() возвращает выборку — последовательность ссылок, которую можно перебирать в цикле. Выборку можно ограничить родителем, владельцем и отбором по реквизитам:

Отбор = Новый Структура("ПометкаУдаления", Ложь);

Выборка = Справочники.Контрагенты.Выбрать( , , Отбор);

Пока Выборка.Следующий() Цикл

Сообщить(Выборка.Наименование + " — " + Выборка.ИНН);

КонецЦикла;

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

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

Получение данных запросом

Язык запросов — основной инструмент массового чтения данных в 1С. Запрос позволяет отобрать элементы по любым реквизитам, соединить справочник с другими таблицами, получить итоги и упорядочить результат:

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

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

"ВЫБРАТЬ

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

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

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

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

|ИЗ

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

|ГДЕ

| НЕ Номенклатура.ПометкаУдаления

| И Номенклатура.Артикул = &Артикул";

Запрос.УстановитьПараметр("Артикул", "АРТ-1001");

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

Если Не Результат.Пустой() Тогда

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

// Обработка строки результата

КонецЦикла;

КонецЕсли;

Обязательно передавайте значения условий через параметры (&ИмяПараметра), а не конкатенацией строк. Это защищает от ошибок синтаксиса при специальных символах в значениях и позволяет СУБД повторно использовать план запроса.

Для получения одного значения удобен метод Выгрузить() с последующим чтением первой строки, либо выборка с единственной итерацией. Если запрос вернул несколько строк, а нужна одна, добавьте конструкцию ВЫБРАТЬ ПЕРВЫЕ 1 и упорядочивание, чтобы результат был детерминированным.

Сравнение способов получения данных

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

Быстрый точечный поиск по стандартным реквизитам. Не подходит для отбора по произвольным реквизитам и при дублях наименований.

Выборка (метод Выбрать)

Простой перебор элементов с отбором. Медленна на больших объёмах из-за обращений к базе на каждый элемент.

Запрос

Оптимален для массового чтения, отборов по любым реквизитам и соединений. Требует аккуратности с параметрами и текстом запроса.

ПолучитьСсылку по GUID

Для интеграций и обменов. Требует отдельной проверки существования элемента.

Как проверить результат и избежать пустых ссылок

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

Проверка выполняется двумя эквивалентными способами:

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

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

ВызватьИсключение "Номенклатура с кодом 000123 не найдена";

КонецЕсли;

// Альтернатива:

Если Элемент = Справочники.Номенклатура.ПустаяСсылка() Тогда

// Элемент не найден

КонецЕсли;

Для запросов проверка выполняется методом Результат.Пустой() до начала обхода выборки. Для ссылок, полученных по GUID, — через попытку получить объект или запросом по ссылке.

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

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

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

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

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

Ссылка пустая — элемент не найден или неверные параметры поиска

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

Результат.Пустой() возвращает Ложь, выборка содержит строки

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

Пустой результат — проверьте параметры и условия отбора

Ссылка по GUID
Норма

ПолучитьОбъект() возвращает объект, реквизиты доступны

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

ПолучитьОбъект() возвращает Неопределено — элемента нет в базе

Производительность и безопасная работа с данными

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

При чтении реквизитов через точку от ссылки помните: каждое обращение к новому реквизиту — это обращение к базе. Если нужно прочитать много реквизитов многих элементов, запрос будет на порядок эффективнее.

Отдельного внимания заслуживают помеченные на удаление элементы. Методы поиска и выборки по умолчанию возвращают и их. Если бизнес-логика этого не требует, добавляйте отбор ПометкаУдаления = Ложь, иначе в документы и отчёты могут попасть «мёртвые» элементы.

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

FAQ

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

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

Чем отличается НайтиПоНаименованию с параметром Истина от Ложь?

Параметр Истина включает поиск по точному совпадению всей строки наименования. Ложь (значение по умолчанию) означает поиск по началу наименования: запрос «Краска» найдёт и «Краска белая», и «Краска синяя» — вернётся первый по порядку элемент.

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

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

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

Частые причины: код хранится как строка с лидирующими нулями, а в метод передано число или строка без нулей; элемент помечен на удаление и поиск выполняется с отбором; в справочнике несколько элементов с одинаковым кодом в разных группах (при отключённом контроле уникальности). Передавайте код в том же типе и формате, в каком он хранится.

Как получить данные подчинённого справочника?

Используйте метод Выбрать() с параметром владельца: Справочники.ЕдиницыИзмерения.Выбрать(, СсылкаНаНоменклатуру) вернёт элементы, подчинённые конкретной номенклатуре. В запросе условие задаётся через поле Владелец: ГДЕ Единицы.Владелец = &Владелец.

Можно ли читать данные справочника из внешней обработки без изменения конфигурации?

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

Итог

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

Точечный поиск — НайтиПоКоду и НайтиПоНаименованию, массовое чтение — запрос, интеграции — ПолучитьСсылку по GUID. Всегда проверяйте результат на пустую ссылку, исключайте помеченные на удаление элементы, а массовые изменения сначала тестируйте на копии базы.