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