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