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