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

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

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

Как получить значение реквизита в 1С: обращение через точку, запрос, функция ЗначениеРеквизитаОбъекта, работа с табличной частью. Примеры кода и типичные ошибки.

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

Главное, что нужно понять перед выбором способа: реквизит существует либо у объекта в памяти (справочник-объект, документ-объект), либо у ссылки, либо у данных формы. От этого зависит, можно ли прочитать значение напрямую или потребуется запрос. Ниже разобраны все основные сценарии с примерами кода, которые работают в типовых конфигурациях на платформе 1С:Предприятие 8.3.

Обращение к реквизиту через точку

Базовый способ — прямое обращение через точку. Если в переменной находится объект (например, полученный методом ПолучитьОбъект() или созданный в модуле объекта), значение реквизита читается напрямую:

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

ИНН = КонтрагентОбъект.ИНН;

Наименование = КонтрагентОбъект.Наименование;

Тот же синтаксис работает и для ссылки: СсылкаНаКонтрагента.ИНН. Однако здесь есть важный нюанс — при обращении к реквизиту через ссылку платформа неявно выполняет запрос к базе данных и загружает объект целиком. Одно такое обращение не критично, но в цикле по тысяче элементов это даёт тысячу отдельных обращений к СУБД и заметно тормозит выполнение кода.

Обращение через точку к реквизиту, которого нет в метаданных, вызывает ошибку «Поле объекта не обнаружено». Поэтому при написании универсального кода, где имя реквизита приходит строкой, используйте квадратные скобки: Объект["ИНН"]. Это позволяет подставлять имя реквизита из переменной и при необходимости перехватывать ошибку через Попытка/Исключение.

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

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

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

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

"ВЫБРАТЬ

| Контрагенты.ИНН КАК ИНН,

| Контрагенты.КПП КАК КПП

|ИЗ

| Справочник.Контрагенты КАК Контрагенты

|ГДЕ

| Контрагенты.Ссылка = &Ссылка";

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

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

ИНН = Выборка.ИНН;

КонецЕсли;

Обязательно проверяйте результат через Выборка.Следующий() или Результат.Пустой(): если ссылка битая или объект удалён, выборка окажется пустой, и обращение к полям без проверки приведёт к ошибке. Для массового чтения передайте в параметр массив ссылок и используйте условие Ссылка В (&МассивСсылок) — один запрос заменит сотни обращений через точку.

Порядок действий при чтении реквизита запросом
  1. 1
    Сформируйте текст запроса с перечислением только нужных полей
  2. 2
    Передайте ссылку или массив ссылок через УстановитьПараметр
  3. 3
    Выполните запрос и проверьте выборку методом Следующий()
  4. 4
    Прочитайте поля выборки и обработайте случай пустого результата

Функция ЗначениеРеквизитаОбъекта в типовых конфигурациях

В конфигурациях на базе Библиотеки стандартных подсистем (УТ, ERP, Бухгалтерия, ЗУП) есть готовая серверная функция ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "ИмяРеквизита"). Она внутри выполняет запрос и возвращает значение одного реквизита. Для нескольких реквизитов есть вариант ЗначенияРеквизитовОбъекта, принимающий строку с именами через запятую и возвращающий структуру.

ИНН = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаКонтрагента, "ИНН");

Реквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(

СсылкаНаКонтрагента, "ИНН, КПП, НаименованиеПолное");

ИНН = Реквизиты.ИНН;

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

Получение реквизита на клиенте и в форме

В управляемой форме данные объекта обычно доступны через реквизит формы (чаще всего Объект). В клиентской процедуре значение читается так: Объект.Номенклатура или Объект.Количество. Это не обращение к базе — данные уже загружены в форму, поэтому чтение мгновенное.

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

&НаКлиенте

Процедура КонтрагентПриИзменении(Элемент)

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

КонецПроцедуры

&НаСервереБезКонтекста

Функция ПолучитьИНННаСервере(Контрагент)

Возврат ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Контрагент, "ИНН");

КонецФункции

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

Чтение реквизитов табличной части

Реквизиты табличной части читаются через обращение к строке. В форме текущая строка доступна через Элементы.Товары.ТекущиеДанные, в объекте — через коллекцию Объект.Товары:

// В модуле объекта или на сервере

Для Каждого СтрокаТовары Из Объект.Товары Цикл

СуммаСтроки = СтрокаТовары.Количество * СтрокаТовары.Цена;

КонецЦикла;

// В клиентской процедуре формы

ТекущиеДанные = Элементы.Товары.ТекущиеДанные;

Если ТекущиеДанные <> Неопределено Тогда

Цена = ТекущиеДанные.Цена;

КонецЕсли;

Обязательно проверяйте ТекущиеДанные на Неопределено: если таблица пуста или фокус не установлен, обращение к полям вызовет ошибку. Для чтения табличной части по ссылке без загрузки объекта используйте запрос с обращением к таблице вида Документ.РеализацияТоваровУслуг.Товары.

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

Какой способ выбрать в разных ситуациях

Выбор способа сводится к трём вопросам: что у вас есть (объект или ссылка), где выполняется код (клиент или сервер) и сколько раз нужно прочитать значение. Для одиночного чтения в модуле объекта или при уже загруженном объекте достаточно точки. Для одиночного чтения по ссылке в типовой конфигурации удобнее ЗначениеРеквизитаОбъекта. Для массового чтения — только запрос.

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

Как выбрать действие

Объект уже получен (модуль объекта, ПолучитьОбъект)Читайте реквизит напрямую через точку
Есть только ссылка, нужен один реквизит, конфигурация типоваяИспользуйте ОбщегоНазначения.ЗначениеРеквизитаОбъекта()
Нужно прочитать реквизиты у множества ссылокНапишите запрос с условием Ссылка В (&МассивСсылок)
Код выполняется на клиенте, а реквизита нет в данных формыВызовите серверную функцию, которая вернёт значение
Имя реквизита известно только во время выполненияИспользуйте обращение Объект["ИмяРеквизита"] с обработкой исключения
Контрольные точки

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

Значение получено
Норма

Переменная содержит ожидаемое значение нужного типа

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

Переменная содержит Неопределено или пустое значение при заполненном реквизите

Производительность в цикле
Норма

Код отрабатывает быстро, замер показывает один запрос

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

Замер производительности показывает запрос на каждой итерации

Работа с пустыми данными
Норма

При битой или пустой ссылке код отрабатывает без исключения

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

На пустой ссылке возникает ошибка обращения к полям

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

Как получить значение реквизита, если известно только его имя в виде строки?

Используйте обращение через квадратные скобки: Объект["ИНН"] или ДанныеФормы[ИмяРеквизита]. Для ссылки на сервере напишите запрос с программно сформированным именем поля, предварительно проверив, что реквизит существует в метаданных через Метаданные.НайтиПоТипу или описание объекта метаданных.

Почему Ссылка.Реквизит работает, хотя ссылка — это не объект?

Платформа поддерживает «разыменование» ссылки: при обращении к реквизиту она неявно загружает объект из базы. Это удобно для разового чтения, но скрывает обращение к СУБД, поэтому в циклах и при массовой обработке такой приём недопустим.

Как получить реквизит объекта, не открывая его на изменение?

Чтение реквизитов запросом или через ЗначениеРеквизитаОбъекта не блокирует объект и не требует вызова ПолучитьОбъект(). Метод ПолучитьОбъект() нужен только если вы собираетесь изменять и записывать данные.

Что вернётся, если реквизит не заполнен?

Вернётся пустое значение соответствующего типа: пустая строка для строк, 0 для чисел, дата 01.01.0001 для дат, пустая ссылка для ссылочных типов. Проверяйте результат функцией ЗначениеЗаполнено(), прежде чем использовать значение в расчётах.

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

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

Итог

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

Объект — читаем через точку, ссылка — через запрос или ЗначениеРеквизитаОбъекта, клиент — через серверный вызов. Никогда не читайте реквизиты через точку в цикле и всегда проверяйте результат выборки и заполненность значения.