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

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

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

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

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

Чтобы получить объект документа, чаще всего используют метод ПолучитьОбъект(), вызванный у ссылки. Альтернативные пути — создание нового объекта через менеджер документа (Документы.РеализацияТоваровУслуг.СоздатьДокумент()) или получение объекта из данных формы. Выбор способа зависит от задачи: изменить существующий документ, создать новый или просто прочитать данные.

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

Чем ссылка отличается от объекта документа

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

Объект (ДокументОбъект.ИмяДокумента) — это загруженная в память копия данных документа: шапка, табличные части, движения. Объект поддерживает методы Записать(), УстановитьПометкуУдаления(), обработчики событий (ПередЗаписью, ПриЗаписи) и блокировку данных при записи.

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

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

Ссылка (ДокументСсылка)

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

Объект (ДокументОбъект)

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

Запрос к таблице документа

Оптимален для массового чтения данных без получения объекта. Не подходит для изменения данных.

Как получить объект документа по ссылке

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

bsl
ДокОбъект = ДокументСсылка.ПолучитьОбъект();
ДокОбъект.Комментарий = "Изменено программно";
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

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

Проверить «битую» ссылку можно двумя способами: сравнить результат ПолучитьОбъект() с Неопределено или заранее убедиться, что ДокументСсылка.ПолучитьОбъект() <> Неопределено. Также применяют проверку через запрос к таблице документа — она быстрее, если данных много.

Как создать объект нового документа

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

bsl
НовыйДок = Документы.ПриходныйОрдерНаТовары.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДатаСеанса();
НовыйДок.Склад = СкладПоУмолчанию;
НовыйДок.Записать(РежимЗаписиДокумента.Запись);

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

Как получить объект из формы документа

В модуле формы документа данные хранятся в реквизите формы (обычно Объект типа ДанныеФормыСтруктура), а не как настоящий ДокументОбъект. Чтобы получить полноценный объект на сервере, используют метод РеквизитФормыВЗначение("Объект").

bsl
&НаСервере
Процедура ПересчитатьНаСервере()
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    ДокОбъект.ДополнительныеСвойства.Вставить("РежимПересчёта", Истина);
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры

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

Получение объекта в запросах и обходе выборок

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

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

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

Проверка результата и типичные ошибки

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

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

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

Результат ПолучитьОбъект()
Норма

Возвращён объект, реквизиты доступны

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

Возвращено Неопределено — ссылка битая или документ удалён

Запись объекта
Норма

Записать() выполнен без исключения, Проведен = Истина

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

Исключение о нарушении прав, блокировке или ошибке проверки заполнения

Движения документа
Норма

Записи в регистрах соответствуют ожиданиям

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

Движений нет — документ записан без проведения или обработчик очистил наборы

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

Ограничения и безопасная работа

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

При программной записи срабатывают все обработчики событий объекта и подписки на события. Это значит, что «тихая» правка реквизита может запустить бизнес-логику: пересчёт итогов, отправку сообщений обмена, регистрацию изменений. Перед массовой обработкой изучите подписки на события в конфигурации и при необходимости используйте Объект.ОбменДанными.Загрузка = Истина для служебной загрузки — но помните, что в этом режиме проверки и обработчики отключаются, и ответственность за корректность данных ложится на ваш код.

Перед массовой обработкой документов сделайте копию базы или выполните пробный прогон на одном-двух документах с выводом результата в журнал. Так проще поймать ошибки в обработчиках событий, которые проявляются только при записи конкретных данных.
ПЗ
Практическое замечание
Итог

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

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

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

Чем ПолучитьОбъект() отличается от обращения к реквизиту через ссылку?

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

Почему ПолучитьОбъект() возвращает Неопределено?

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

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

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

Можно ли изменить документ без получения объекта?

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

Что делать, если при записи объекта возникает ошибка блокировки?

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

Нужно ли освобождать объект после работы?

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