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

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

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

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

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

Основных подхода три: прямое обращение через точку к объекту или ссылке, выборка через запрос и универсальные функции из библиотеки стандартных подсистем (БСП), например ОбщегоНазначения.ЗначенияРеквизитовОбъекта. У каждого варианта есть свои ограничения по производительности, правам доступа и контексту выполнения.

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

Как устроены реквизиты документа и почему это важно

У документа в 1С есть штатные реквизиты (Ссылка, Номер, Дата, Проведен, ПометкаУдаления), реквизиты шапки, заданные в конфигураторе, и табличные части. Штатные реквизиты доступны всегда, реквизиты шапки — по имени, заданному разработчиком конфигурации, табличные части возвращают коллекцию строк, а не одиночное значение.

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

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

Если у вас есть ссылка на документ или объект, значение реквизита читается прямым обращением по имени:

// Есть ссылка на документ

СсылкаНаДокумент = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("0000-000123", ТекущаяДатаСеанса());

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

Контрагент = СсылкаНаДокумент.Контрагент;

СуммаДокумента = СсылкаНаДокумент.СуммаДокумента;

КонецЕсли;

Такой способ удобен для одного-двух реквизитов в разовой логике. Он читабелен, не требует построения запроса и работает как на сервере, так и в модуле объекта. Обращение к составному реквизиту (например, к реквизиту контрагента документа) тоже возможно: Ссылка.Контрагент.ИНН, но каждое такое «глубокое» обращение порождает дополнительное чтение связанного объекта.

Обязательно проверяйте, что ссылка не пустая и не «битая». Обращение к реквизиту несуществующего объекта вернёт ошибку или неопределённое значение в зависимости от контекста.

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

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

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

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

"ВЫБРАТЬ

| Реализация.Ссылка КАК Ссылка,

| Реализация.Контрагент КАК Контрагент,

| Реализация.СуммаДокумента КАК Сумма

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Ссылка = &Ссылка";

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

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

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

Контрагент = Выборка.Контрагент;

КонецЕсли;

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

Универсальная функция ЗначенияРеквизитовОбъекта из БСП

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

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

СсылкаНаДокумент, "Номер, Дата, Контрагент, СуммаДокумента");

Сумма = Реквизиты.СуммаДокумента;

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

Если конфигурация самописная и БСП в ней нет, имеет смысл написать аналогичную обёртку в общем модуле: динамически формировать текст запроса по переданным именам реквизитов. Это избавляет от дублирования кода чтения по всей системе.

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

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

Подходит для 1–2 реквизитов одного документа в разовой логике. Ограничение: лишние чтения из базы в циклах и при глубоких обращениях через ссылки.

Запрос

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

ЗначенияРеквизитовОбъекта (БСП)

Универсальный компромисс: один запрос, произвольный набор полей, простой вызов. Доступен только в конфигурациях с библиотекой стандартных подсистем.

Реквизиты табличной части и составные типы

Чтение табличной части

Табличная часть не является одиночным реквизитом — это коллекция строк. Через ссылку она читается так же через точку, но результат нужно перебирать:

Для Каждого СтрокаТовара Из СсылкаНаДокумент.Товары Цикл

СуммаСтроки = СтрокаТовара.Сумма;

КонецЦикла;

При массовой обработке табличные части выбирают запросом из виртуальной таблицы вида Документ.РеализацияТоваровУслуг.Товары — это позволяет фильтровать и группировать строки на стороне СУБД.

Реквизиты составного типа

Если реквизит имеет составной тип (например, «ДокументОснование» может хранить ссылки разных видов документов), перед чтением его собственных реквизитов проверяйте тип значения через ТипЗнч(). Обращение к реквизиту, которого нет у конкретного вида документа, вызовет ошибку «Поле объекта не обнаружено».

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

Как выбрать способ

Нужен один реквизит одного известного документаОбратитесь через точку от ссылки — это самый короткий и читаемый код
Нужно несколько реквизитов или обработка списка документовИспользуйте запрос или ЗначенияРеквизитовОбъектов, чтобы уложиться в одно обращение к базе
Конфигурация на БСП и набор полей заранее неизвестенПримените ОбщегоНазначения.ЗначенияРеквизитовОбъекта с перечнем полей строкой
Код выполняется на клиенте в управляемой формеПолучайте значения в серверной процедуре формы — прямое обращение к ссылке с клиента недоступно

Особенности на клиенте, в форме и в момент записи

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

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

Типичные ошибки
01
Чтение реквизитов через точку внутри цикла по тысячам ссылок — каждый проход порождает отдельное чтение из базы, обработка растягивается на минуты вместо секунд
02
Обращение к реквизиту пустой или битой ссылки без проверки — ошибка выполнения или непредсказуемое значение в расчётах
03
Опечатка в имени реквизита в строковом параметре ЗначенияРеквизитовОбъекта — ошибка всплывёт только в момент выполнения, а не при проверке модуля
04
Чтение реквизита ссылки на клиенте управляемого приложения — код недоступен в этом контексте, нужна серверная процедура
05
Обращение к реквизиту составного поля без проверки типа значения — ошибка «Поле объекта не обнаружено» при другом виде документа-основания

Проверка результата и контроль прав доступа

После получения значения убедитесь, что оно соответствует ожиданиям: тип значения совпадает с типом реквизита в конфигураторе, ссылочные реквизиты не пустые, числовые не содержат Неопределено. Для быстрой отладки используйте Сообщить() или точку останова с просмотром значения в отладчике.

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

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

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

Тип полученного значения
Норма

Совпадает с типом реквизита в конфигураторе (ТипЗнч возвращает ожидаемый тип)

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

Возвращается Неопределено или значение другого типа — проверьте имя реквизита и составной тип

Ссылочный реквизит
Норма

Ссылка не пустая, СсылкаСуществует возвращает Истина

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

Пустая ссылка или битая ссылка — документ-основание не заполнен или удалён

Скорость массовой обработки
Норма

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

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

В замере производительности видны тысячи одинаковых запросов чтения — замените обращение через точку на пакетный запрос

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

Как получить номер и дату документа, если есть только ссылка?

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

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

Да. Сначала найдите ссылку методом Документы.ИмяДокумента.НайтиПоНомеру(Номер, ДатаПериода), проверьте, что ссылка не пустая, и затем прочитайте нужный реквизит через точку или запрос. Учтите, что номер уникален только в пределах периода нумерации, поэтому дату периода указывать обязательно.

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

Пометка удаления не ограничивает чтение: реквизиты будут возвращены в полном объёме. Если логика требует исключить такие документы, добавьте проверку Ссылка.ПометкаУдаления или условие в запросе.

Как получить реквизит документа в фоновом задании или регламентной операции?

На сервере в фоновом задании работают все способы: обращение через точку, запрос и функции БСП. Передавать в фоновое задание следует ссылку, а не объект — объект не сериализуется между сеансами.

Почему ЗначенияРеквизитовОбъекта возвращает ошибку, хотя реквизит есть?

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

Какой способ быстрее всего для одного реквизита одного документа?

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

Итог

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

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