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