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

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

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

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

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

Во встроенном языке 1С есть три основных подхода: методы менеджера справочника (НайтиПоКоду, НайтиПоНаименованию, НайтиПоРеквизиту), выборка через Выбрать() и язык запросов. Каждый подходит для своих сценариев и отличается по скорости и гибкости.

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

Как устроено обращение к справочнику

Работа со справочником начинается с менеджера — объекта, который возвращает конструкция Справочники.ИмяСправочника. Например, Справочники.Номенклатура или Справочники.Контрагенты. Через менеджер доступны методы поиска, создания и выборки элементов.

Результатом поиска является ссылка — объект типа СправочникСсылка. Сама по себе ссылка содержит только уникальный идентификатор и минимум данных (код, наименование). Чтобы прочитать произвольный реквизит, нужно либо обратиться к реквизиту через точку (при этом платформа неявно считывает объект из базы), либо получить объект методом ПолучитьОбъект(), либо выбрать данные запросом.

Важно понимать: обращение к реквизиту через ссылку (Элемент.Артикул) выполняет отдельное обращение к базе данных. В цикле по тысяче элементов это даёт тысячу обращений и заметно тормозит код — в таких случаях правильнее использовать запрос.

Поиск элемента по коду, наименованию и реквизиту

Самая частая задача — найти конкретный элемент по известному значению. Менеджер справочника предоставляет три метода поиска:

  • НайтиПоКоду(Код) — поиск по коду элемента;
  • НайтиПоНаименованию(Наименование, ТочноеСоответствие) — поиск по наименованию;
  • НайтиПоРеквизиту(ИмяРеквизита, Значение) — поиск по любому реквизиту.

Пример поиска контрагента по ИНН (реквизит) и проверки результата:

НайденныйЭлемент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7707083893");

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

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

Иначе

Сообщить("Найден: " + НайденныйЭлемент.Наименование);

КонецЕсли;

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

При поиске по наименованию второй параметр отвечает за точное соответствие. По умолчанию он равен Ложь, и поиск идёт по вхождению строки — это может вернуть не тот элемент. Для надёжности передавайте Истина:

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

Обход элементов справочника через Выбрать()

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

Выборка = Справочники.Номенклатура.Выбрать();

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

Если Выборка.ЭтоГруппа Тогда

Продолжить;

КонецЕсли;

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

КонецЦикла;

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

У способа есть ограничение: отбор в Выбрать() работает только по реквизитам, для которых в конфигураторе включено индексирование, и набор условий ограничен. Для сложных отборов, соединений с другими таблицами и агрегации используйте запрос.

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

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

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

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

"ВЫБРАТЬ

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

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

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

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

|ИЗ

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

|ГДЕ

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

| И НЕ Номенклатура.ЭтоГруппа

|УПОРЯДОЧИТЬ ПО

| Наименование";

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

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

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

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

КонецЦикла;

Обратите внимание на фильтр НЕ ПометкаУдаления: запрос по умолчанию возвращает и помеченные на удаление элементы. Если забыть этот отбор, в обработку попадут «мёртвые» записи, что исказит отчёты и выгрузки.

Для передачи условий используйте параметры, а не конкатенацию строк — это защищает от ошибок синтаксиса и упрощает поддержку:

Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты ГДЕ ИНН = &ИНН";

Запрос.УстановитьПараметр("ИНН", "7707083893");

Чтение табличных частей элемента

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

Через объект это выглядит так:

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

Для Каждого СтрокаКИ Из ОбъектКонтрагента.КонтактнаяИнформация Цикл

Сообщить(СтрокаКИ.Вид + ": " + СтрокаКИ.Представление);

КонецЦикла;

То же самое запросом — быстрее и без загрузки всего объекта в память:

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

"ВЫБРАТЬ

| КИ.Вид КАК Вид,

| КИ.Представление КАК Представление

|ИЗ

| Справочник.Контрагенты.КонтактнаяИнформация КАК КИ

|ГДЕ

| КИ.Ссылка = &Ссылка";

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

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

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

СпособКогда применятьОграничения
НайтиПоКоду / НайтиПоНаименованиюПоиск одного известного элементаВозвращает один элемент; наименование не уникально
НайтиПоРеквизитуПоиск по ИНН, артикулу, штрихкодуБез индекса по реквизиту поиск медленный
Выбрать()Простой обход с фильтром по родителю или владельцуОграниченные отборы, по одному обращению на элемент
ЗапросСложные отборы, соединения, большие объёмы, отчётыТребует знания языка запросов
ПолучитьОбъект()Изменение и запись элемента, чтение табличных частейЗагружает весь объект в память; не для массового чтения
Маршрут решения

Как выбрать способ

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

Частые ошибки и как их избежать

Первая и самая массовая ошибка — обращение к реквизитам через ссылку внутри цикла. Конструкция Выборка.Ссылка.Артикул в цикле по тысяче элементов выполняет тысячу запросов к базе. Решение — выбрать все нужные поля одним запросом.

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

Третья группа ошибок связана с контекстом выполнения. На управляемых формах код с директивой &НаКлиенте не имеет доступа к менеджерам справочников — обращение к Справочники.Номенклатура вызовет ошибку. Чтение данных выполняйте в серверных процедурах (&НаСервере или &НаСервереБезКонтекста).

Типичные ошибки
01
Обращение к реквизитам через ссылку в цикле — тысячи лишних обращений к базе и зависание обработки
02
Отсутствие проверки Пустая() после поиска — пустые значения попадают в документы и отчёты
03
Забытый отбор по ПометкаУдаления в запросе — в выгрузку попадают удалённые элементы
04
Вызов Справочники.* в клиентском коде управляемой формы — ошибка компиляции или выполнения
05
Поиск по наименованию без точного соответствия — находится чужой элемент с похожим названием

Как проверить, что данные получены правильно

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

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

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

Найден ли элемент
Норма

Пустая() возвращает Ложь, ссылка открывается в режиме предприятия

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

Пустая() возвращает Истина — значение поиска не совпало с данными

Полнота выборки
Норма

Количество строк совпадает с числом элементов в списке справочника с теми же отборами

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

Строк больше — попали помеченные на удаление или группы

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

Совпадают с данными формы элемента

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

Пустые или устаревшие значения — читается не тот реквизит или кэш

Скорость выполнения
Норма

Обработка тысячи элементов занимает секунды

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

Обработка идёт минутами — в цикле есть обращения к базе через ссылку

Дополнительный приём — замер производительности через ТекущаяУниверсальнаяДатаВМиллисекундах() до и после выборки. Если замена цикла с обращениями через ссылку на один запрос сокращает время в десятки раз, вы на верном пути.

Итог

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

Один элемент ищите методами НайтиПоКоду, НайтиПоНаименованию или НайтиПоРеквизиту и всегда проверяйте результат на пустую ссылку. Массовое чтение реквизитов делайте запросом — это одно обращение к базе. В запросах фильтруйте пометку удаления, а в управляемых формах выполняйте чтение на сервере.

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

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

Используйте конструкцию: Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор("строка-guid")). Метод не проверяет существование элемента — чтобы убедиться, что элемент реально есть в базе, выполните запрос по полученной ссылке или проверьте любой реквизит. Это стандартный способ обмена между базами, где коды не синхронизированы.

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

Проще всего запросом: ВЫБРАТЬ Ссылка, Наименование ИЗ Справочник.Номенклатура. Альтернатива — Выбрать() без параметров с циклом по выборке. Для больших справочников предпочтителен запрос: он быстрее и позволяет сразу исключить помеченные на удаление и группы.

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

Частые причины: лишние пробелы или неразрывные пробелы в наименовании, разный регистр букв в некоторых СУБД, элемент помечен на удаление, поиск выполняется с точным соответствием, а строки отличаются. Скопируйте наименование прямо из формы элемента и попробуйте поиск без второго параметра.

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

Да. Список справочника можно вывести в табличный документ через «Ещё → Вывести список» в типовых конфигурациях. Гибкие выборки с отборами даёт универсальный отчёт или произвольный отчёт на СКД. Этого достаточно для разовой выгрузки в Excel без написания кода.

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

Через менеджер по имени, заданному в конфигураторе: Справочники.Валюты.Рубль — если элемент с таким именем предопределён. Универсальный способ получить имя предопределённого элемента по ссылке — функция ОбщегоНазначения.ПредопределенныйЭлемент() в конфигурациях на БСП или запрос вида ВЫБРАТЬ Ссылка ИЗ Справочник.Валюты ГДЕ Предопределенный.

Чем опасен ПолучитьОбъект() при массовом чтении?

Метод загружает в память весь объект со всеми табличными частями и блокирует его для конкурентного изменения в некоторых сценариях. В цикле по тысячам элементов это даёт огромный расход памяти и времени. Для чтения используйте запрос; ПолучитьОбъект() оправдан только когда элемент нужно изменить и записать.