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

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

Как обратиться к реквизиту документа в 1С

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

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

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

Что такое реквизит документа и где он хранится

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

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

Чтение реквизита через точку от ссылки

Самый простой и частый способ — точечный доступ. Если у вас есть переменная типа ДокументСсылка, реквизит читается напрямую:

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

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

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

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

Обращение «по цепочке» тоже допустимо: СсылкаНаДокумент.Контрагент.Наименование. Но каждое звено цепочки — дополнительное чтение, поэтому цепочки длиннее двух-трёх уровней лучше заменять запросом.

Изменение реквизита: работа через объект документа

Присвоить значение реквизиту через ссылку нельзя — попытка вызовет ошибку. Для изменения нужно получить объект документа, изменить реквизит и записать:

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

ДокОбъект.Комментарий = "Скорректировано автоматически";

ДокОбъект.Записать();

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

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

Обращение к реквизитам табличной части

Табличная часть документа (например, «Товары») — это коллекция строк. Через ссылку её можно только читать, через объект — и изменять. Обращение к конкретному реквизиту строки выглядит так:

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

Сообщить(СтрокаТовары.Номенклатура);

Сообщить(СтрокаТовары.Количество);

КонецЦикла;

Для изменения строки получите объект и работайте с его табличной частью: Строка = ДокОбъект.Товары[0]; Строка.Цена = 100;. Индексация строк начинается с нуля. После изменений не забудьте записать объект, иначе правки будут потеряны.

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

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

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

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

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Номер,

| РеализацияТоваровУслуг.Дата,

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

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

|ИЗ

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

|ГДЕ

| РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));

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

Пока Выборка.Следующий() Цикл

Сообщить(Выборка.Номер);

КонецЦикла;

Запрос читает только указанные поля и не создаёт объектов в памяти, поэтому работает быстрее и не блокирует данные. Если по ссылке нужно одно значение, тоже можно использовать запрос с условием ГДЕ Ссылка = &Ссылка — это предпочтительнее, чем ПолучитьОбъект() ради одного реквизита.

Сравнение вариантов

Точечный доступ (Ссылка.Реквизит)

Подходит для одиночного чтения одного-двух полей. Ограничение: медленно в циклах, только чтение.

ПолучитьОбъект()

Необходим для изменения и записи документа. Ограничение: загружает весь документ, создаёт блокировку при записи.

Запрос

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

Обращение к реквизиту из формы документа

В модуле формы документа данные доступны через реквизит формы Объект (в управляемой форме) — это данные формы, а не объект базы напрямую. Обращение выглядит так: Объект.Комментарий = "Текст";. Изменения попадут в базу только после записи документа пользователем или программно методом Записать() формы.

В обычных формах используется аналогичный реквизит формы. Частая ошибка — обращаться к ЭтотОбъект в модуле формы: в управляемой форме такого контекста нет, нужен именно Объект. В модуле объекта (модуль документа), наоборот, реквизиты доступны напрямую по имени: Комментарий = "..."; — без префикса.

Типичные ошибки и как их избежать

Первая ошибка — присвоение через ссылку: Ссылка.Комментарий = "...". Платформа выдаст ошибку, потому что ссылка предназначена только для чтения. Вторая — обращение к реквизиту, которого нет в метаданных: проверяйте точное имя реквизита в конфигураторе, оно чувствительно к написанию (но не к регистру).

Третья ошибка — работа с «битой» ссылкой. Если документ удалён, а ссылка осталась в других объектах, обращение к реквизиту вернёт ошибку или неопределённое поведение. Проверяйте существование: Если Ссылка.ПолучитьОбъект() = Неопределено Тогда ... или запросом с проверкой на NULL. Четвёртая ошибка — забытый Записать() после изменения объекта: все правки теряются без предупреждения.

Типичные ошибки
01
Присвоение значения через ссылку вместо ПолучитьОбъект() — ошибка выполнения
02
Точечный доступ в большом цикле вместо запроса — падение производительности
03
Вызов Записать() без обработки исключений — необработанный конфликт блокировок
04
Опечатка в имени реквизита — ошибка «Поле не обнаружено»
05
Изменение объекта без последующего Записать() — потеря изменений
Контрольные точки

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

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

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

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

Значение старое — запись не выполнена или отменена

Проведение документа
Норма

Свойство Проведен = Истина после Записать(Проведение)

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

Проведен = Ложь — проведение отменено из-за ошибок контроля

Движения по регистрам
Норма

В отчётах по регистрам появились записи документа

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

Записей нет — проверьте обработчик проведения

FAQ

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

Да, через квадратные скобки: ДокОбъект["Комментарий"]. Это полезно, когда имя реквизита вычисляется программно, например при универсальной обработке разных видов документов.

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

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

Почему Ссылка.Реквизит возвращает пустое значение, хотя в документе поле заполнено?

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

Чем отличается обращение к реквизиту в модуле объекта и в модуле формы?

В модуле объекта реквизиты доступны напрямую по имени без префикса. В модуле управляемой формы обращайтесь через реквизит формы Объект: Объект.ИмяРеквизита. Смешивание этих контекстов — частая причина ошибок «Переменная не определена».

Как безопасно изменить реквизит у проведённого документа?

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

Нужен ли ПолучитьОбъект(), чтобы прочитать табличную часть?

Нет, для чтения достаточно ссылки: Ссылка.Товары вернёт табличную часть. ПолучитьОбъект() нужен только если строки табличной части требуется изменить.

Итог

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

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