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

Разработка и Конфигурация · 12 мин

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

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

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

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

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

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

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

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

Поиск элемента по коду

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

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

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

Сообщить("Элемент с таким кодом не найден");

Иначе

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

КонецЕсли;

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

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

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

Метод НайтиПоНаименованию() ищет точное совпадение строки наименования. Частичное совпадение он не поддерживает — для поиска «по фрагменту» понадобится запрос с оператором ПОДОБНО.

// Точный поиск по наименованию

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

// Поиск по значению реквизита, например по ИНН

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

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

Перебор элементов через Выбрать()

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

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

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

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

Продолжить;

КонецЕсли;

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

КонецЦикла;

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

При обходе иерархического справочника не забывайте про группы: в выборке они присутствуют наравне с элементами. Проверка Выборка.ЭтоГруппа или отбор по ПометкаУдаления помогает отсеять лишнее.

Получение элементов запросом

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

|ГДЕ

| Номенклатура.Наименование ПОДОБНО &Фрагмент

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

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

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

Пока Результат.Следующий() Цикл

Сообщить(Результат.Наименование);

КонецЦикла;

Параметры запроса всегда передавайте через УстановитьПараметр(), а не конкатенацией строк — это защищает от ошибок синтаксиса и делает код устойчивым к спецсимволам в данных. Результат можно получить выборкой (Выбрать()) или выгрузить в таблицу значений (Выгрузить()), если нужен произвольный доступ к строкам.

Сравнение способов получения элементов

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

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

Выбрать()

Простой перебор элементов с отбором по родителю или владельцу. Не подходит для сложных условий и соединений.

Запрос

Любые условия, соединения, группировки, сортировка. Оптимален для больших выборок, но требует написания текста запроса.

Работа с предопределёнными элементами

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

Склад = Справочники.Склады.ОсновнойСклад;

Ставка = Справочники.СтавкиНДС.НДС20;

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

Альтернативный способ — метод ПолучитьСсылку() с уникальным идентификатором, когда GUID элемента известен заранее, например при обмене между базами. Проверить, существует ли элемент с таким GUID, помогает сравнение полученной ссылки с результатом запроса или проверка через ОбщегоНазначения.СсылкаСуществует() в типовых конфигурациях на БСП.

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

Типичные ошибки и их диагностика

Большинство проблем при получении элементов сводится к нескольким повторяющимся сценариям. Знание их признаков экономит часы отладки.

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

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

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

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

Ссылка после поиска
Норма

Пустая() возвращает Ложь

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

Пустая() возвращает Истина — элемент не найден

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

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

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

Элемент помечен на удаление, но участвует в логике

Скорость поиска по реквизиту
Норма

Поиск выполняется мгновенно, реквизит индексирован

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

Заметная задержка — вероятно, индекса нет

Как выбрать способ в конкретной задаче

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

Маршрут решения

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

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

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

Итог

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

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

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

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

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

Как найти элемент по части наименования?

Метод НайтиПоНаименованию ищет только точное совпадение. Для поиска по фрагменту используйте запрос с оператором ПОДОБНО и символами процента вокруг искомой строки, например "%кабель%".

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

Методы НайтиПоКоду, НайтиПоНаименованию и НайтиПоРеквизиту возвращают пустую ссылку соответствующего типа, а не Неопределено. Проверка выполняется методом Пустая(): если она вернула Истина, элемент отсутствует.

Почему поиск по реквизиту работает медленно?

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

Находит ли поиск помеченные на удаление элементы?

Да, методы поиска по умолчанию находят и помеченные элементы. Если нужны только актуальные данные, добавьте проверку реквизита ПометкаУдаления после поиска или условие НЕ ПометкаУдаления в текст запроса.

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

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