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