Разработка и Конфигурация · 10 мин
Как получить объект документа в 1С
Разбираем, как получить объект документа в 1С: метод ПолучитьОбъект, отличие ссылки от объекта, примеры кода, типичные ошибки и проверка результата.
Во встроенном языке 1С документ существует в двух формах: как ссылка (ДокументСсылка) и как объект (ДокументОбъект). Ссылка — это лёгкий указатель на запись в базе, который позволяет читать реквизиты, но не даёт их менять. Объект — это полноценная структура данных документа в памяти, которую можно редактировать, записывать и проводить.
Чтобы получить объект документа, чаще всего используют метод ПолучитьОбъект(), вызванный у ссылки. Альтернативные пути — создание нового объекта через менеджер документа (Документы.РеализацияТоваровУслуг.СоздатьДокумент()) или получение объекта из данных формы. Выбор способа зависит от задачи: изменить существующий документ, создать новый или просто прочитать данные.
Неправильное понимание различий между ссылкой и объектом — одна из самых частых причин ошибок «Поле объекта не обнаружено» и проблем с производительностью. Универсальные механизмы вроде обмена данными или печатных форм работают именно через объект, поэтому умение корректно его получать — базовый навык разработчика 1С.
Чем ссылка отличается от объекта документа
Ссылка (ДокументСсылка.ИмяДокумента) — это значение, которое однозначно идентифицирует документ в информационной базе. Через ссылку доступны реквизиты шапки документа в режиме чтения: платформа неявно выполняет запрос к базе при обращении к полю. Табличные части через ссылку недоступны, изменить значения тоже нельзя.
Объект (ДокументОбъект.ИмяДокумента) — это загруженная в память копия данных документа: шапка, табличные части, движения. Объект поддерживает методы Записать(), УстановитьПометкуУдаления(), обработчики событий (ПередЗаписью, ПриЗаписи) и блокировку данных при записи.
Практическое правило: если нужно только прочитать номер, дату или пару реквизитов — работайте через ссылку или запрос. Если нужно изменить документ, заполнить табличную часть или перепровести — получайте объект.
Сравнение вариантов
Подходит для чтения реквизитов шапки, передачи в параметры, хранения в реквизитах других объектов. Не позволяет изменять данные и обращаться к табличным частям.
Нужен для изменения, записи и проведения документа, работы с табличными частями и движениями. Требует больше памяти и времени на получение.
Оптимален для массового чтения данных без получения объекта. Не подходит для изменения данных.
Как получить объект документа по ссылке
Основной способ — вызвать метод ПолучитьОбъект() у значения типа ДокументСсылка. Метод обращается к базе, загружает все данные документа и возвращает объект, готовый к редактированию.
ДокОбъект = ДокументСсылка.ПолучитьОбъект();
ДокОбъект.Комментарий = "Изменено программно";
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);Если ссылка указывает на несуществующий (удалённый физически) документ, ПолучитьОбъект() вернёт Неопределено. Поэтому перед работой с объектом полезно проверять результат, особенно когда ссылка приходит из внешних источников — обменов, файлов, параметров обработки.
Проверить «битую» ссылку можно двумя способами: сравнить результат ПолучитьОбъект() с Неопределено или заранее убедиться, что ДокументСсылка.ПолучитьОбъект() <> Неопределено. Также применяют проверку через запрос к таблице документа — она быстрее, если данных много.
Как создать объект нового документа
Если документа ещё нет в базе, объект создаётся через менеджер документа: Документы.ИмяДокумента.СоздатьДокумент(). Возвращается новый объект с незаполненными реквизитами, датой по умолчанию и без номера — номер будет присвоен при записи.
НовыйДок = Документы.ПриходныйОрдерНаТовары.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДатаСеанса();
НовыйДок.Склад = СкладПоУмолчанию;
НовыйДок.Записать(РежимЗаписиДокумента.Запись);После записи ссылку на созданный документ можно получить через свойство НовыйДок.Ссылка. Это удобно, когда документ создаётся программно и его нужно вернуть в вызывающий код — например, при создании документов на основании или при загрузке из файла.
Как получить объект из формы документа
В модуле формы документа данные хранятся в реквизите формы (обычно Объект типа ДанныеФормыСтруктура), а не как настоящий ДокументОбъект. Чтобы получить полноценный объект на сервере, используют метод РеквизитФормыВЗначение("Объект").
&НаСервере
Процедура ПересчитатьНаСервере()
ДокОбъект = РеквизитФормыВЗначение("Объект");
ДокОбъект.ДополнительныеСвойства.Вставить("РежимПересчёта", Истина);
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедурыОбратное преобразование выполняется через ЗначениеВРеквизитФормы(). Важно понимать: пока форма открыта, вызывать Ссылка.ПолучитьОбъект() и записывать документ «в обход» формы опасно — при сохранении из формы изменения затрут друг друга, а пользователь получит ошибку оптимистической блокировки «Данные были изменены другим пользователем».
Получение объекта в запросах и обходе выборок
Запрос всегда возвращает ссылки, а не объекты. Типовой сценарий: запросом выбираются ссылки нужных документов, затем в цикле для каждой ссылки вызывается ПолучитьОбъект(), если документ требуется изменить.
- 1Составьте запрос, выбирающий ссылки документов по нужному условию
- 2Выполните запрос и получите выборку
- 3В цикле для каждой ссылки вызовите ПолучитьОбъект()
- 4Проверьте, что объект не равен Неопределено
- 5Измените реквизиты и вызовите Записать() с нужным режимом
- 6По завершении убедитесь, что все документы записаны без исключений
Если документов много, оборачивайте обработку в транзакцию порциями или используйте отложенные механизмы. Запись тысяч объектов по одному вне транзакции — частая причина тайм-аутов и блокировок в многопользовательском режиме.
Проверка результата и типичные ошибки
После получения объекта и записи стоит убедиться, что операция прошла корректно. Признаки успеха: объект не равен Неопределено, метод Записать() не вызвал исключения, у проведённого документа Проведен = Истина, а движения появились в регистрах.
Как проверить результат
Возвращён объект, реквизиты доступны
Возвращено Неопределено — ссылка битая или документ удалён
Записать() выполнен без исключения, Проведен = Истина
Исключение о нарушении прав, блокировке или ошибке проверки заполнения
Записи в регистрах соответствуют ожиданиям
Движений нет — документ записан без проведения или обработчик очистил наборы
Ограничения и безопасная работа
Получение объекта требует права на чтение документа, а запись — права на изменение и проведение. В механизмах с RLS (ограничением доступа на уровне записей) объект может быть получен, но запись завершится ошибкой, если документ не проходит по условиям доступа.
При программной записи срабатывают все обработчики событий объекта и подписки на события. Это значит, что «тихая» правка реквизита может запустить бизнес-логику: пересчёт итогов, отправку сообщений обмена, регистрацию изменений. Перед массовой обработкой изучите подписки на события в конфигурации и при необходимости используйте Объект.ОбменДанными.Загрузка = Истина для служебной загрузки — но помните, что в этом режиме проверки и обработчики отключаются, и ответственность за корректность данных ложится на ваш код.
Перед массовой обработкой документов сделайте копию базы или выполните пробный прогон на одном-двух документах с выводом результата в журнал. Так проще поймать ошибки в обработчиках событий, которые проявляются только при записи конкретных данных.
Что важно запомнить
Объект существующего документа получают через Ссылка.ПолучитьОбъект(), новый — через Документы.Имя.СоздатьДокумент(), из формы — через РеквизитФормыВЗначение(). Для чтения данных объект не нужен: используйте ссылку или запрос. Всегда проверяйте результат на Неопределено и записывайте объект методом Записать().
Частые вопросы
Чем ПолучитьОбъект() отличается от обращения к реквизиту через ссылку?
Обращение через ссылку (ДокументСсылка.Номер) выполняет точечное чтение поля из базы и не загружает весь документ. ПолучитьОбъект() загружает документ целиком, включая табличные части, и создаёт редактируемую копию в памяти. Для чтения одного поля ссылка быстрее и безопаснее.
Почему ПолучитьОбъект() возвращает Неопределено?
Чаще всего это «битая ссылка»: документ был физически удалён из базы, а ссылка на него осталась в другом объекте или пришла извне. Также причина может быть в том, что переменная содержит пустую ссылку другого вида документа. Всегда проверяйте результат перед обращением к реквизитам.
Как получить объект документа, если известны только номер и дата?
Сначала найдите ссылку методом Документы.ИмяДокумента.НайтиПоНомеру(Номер, Дата) или запросом, затем вызовите у найденной ссылки ПолучитьОбъект(). Учтите, что номер уникален только в пределах периода нумерации, поэтому дату передавать обязательно.
Можно ли изменить документ без получения объекта?
Нет, изменение данных документа возможно только через объект. Через ссылку доступно лишь чтение. Альтернатива — изменение движений напрямую через наборы записей регистров, но это обходной путь, который нарушает логику проведения и применяется только в служебных сценариях опытными разработчиками.
Что делать, если при записи объекта возникает ошибка блокировки?
Ошибка означает, что документ изменяется в другом сеансе или открыт в форме. Варианты действий: повторить попытку позже, получить объект заново и применить изменения к свежей версии, либо договориться о регламенте, исключающем одновременное редактирование. Не отключайте контроль блокировок — это приводит к потере данных.
Нужно ли освобождать объект после работы?
Специальных действий не требуется: сборщик мусора платформы освободит память, когда переменная выйдет из области видимости. Достаточно не хранить объекты в глобальных переменных и не накапливать их в массивах при массовой обработке — обрабатывайте и записывайте документы по одному.