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

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

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

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

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

Типовая задача выглядит так: есть ссылка на документ (полученная запросом, из формы списка или из параметра обработки), и требуется изменить реквизиты, добавить строку в табличную часть или перепровести документ. Для этого используется метод ПолучитьОбъект(), который вызывается у ссылки и возвращает объект типа «ДокументОбъект».

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

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

Ссылка (тип «ДокументСсылка») хранит только уникальный идентификатор записи. Через точку от ссылки доступны значения реквизитов шапки — платформа при обращении неявно выполняет запрос к базе. Однако попытка присвоить реквизиту новое значение через ссылку приведёт к ошибке: ссылка предназначена только для чтения.

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

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

Базовый способ: метод ПолучитьОбъект()

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

ДокументСсылка = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("00000-000001", ТекущаяДатаСеанса());

Если Не ДокументСсылка.Пустая() Тогда

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

Если ДокументОбъект <> Неопределено Тогда

ДокументОбъект.Комментарий = "Изменён программно";

ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

КонецЕсли;

КонецЕсли;

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

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

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

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

НовыйДокумент = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();

НовыйДокумент.Дата = ТекущаяДатаСеанса();

НовыйДокумент.Организация = ОрганизацияПоУмолчанию;

НоваяСтрока = НовыйДокумент.Товары.Добавить();

НоваяСтрока.Номенклатура = НоменклатураТовара;

НоваяСтрока.Количество = 1;

НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);

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

Получение объекта в форме и на сервере

В модуле формы документа

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

&НаСервере

Процедура ИзменитьКомментарийНаСервере()

ДокументОбъект = РеквизитФормыВЗначение("Объект");

ДокументОбъект.Комментарий = "Изменён из формы";

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

ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");

КонецПроцедуры

Во внешних обработках и регламентных заданиях

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

Запись, проведение и пометка удаления объекта

После изменения объекта результат фиксируется методом Записать(). Режим записи определяет поведение: РежимЗаписиДокумента.Запись сохраняет без проведения, РежимЗаписиДокумента.Проведение проводит документ и формирует движения, РежимЗаписиДокумента.ОтменаПроведения очищает движения.

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

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

Если ДокументОбъект <> Неопределено Тогда

ДокументОбъект.УстановитьПометкуУдаления(Истина);

КонецЕсли;

Типичные ошибки при получении объекта

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

Ещё одна группа ошибок связана с блокировками. Если документ открыт другим пользователем или редактируется в параллельном сеансе, запись объекта завершится ошибкой конфликта блокировок. В регламентных заданиях такую ситуацию обрабатывают через попытку/исключение с повторной попыткой или пропуском документа с записью в журнал регистрации.

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

Альтернативы и проверка результата

Не всегда нужен именно объект. Если задача — прочитать реквизиты, достаточно запроса или обращения через ссылку. Если нужно изменить один-два реквизита без запуска обработчиков проведения, иногда применяют ОбменДанными.Загрузка = Истина у объекта перед записью — это отключает бизнес-логику подписок, но требует полного понимания последствий: контроль и проверки при такой записи не выполняются.

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

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

Ссылка.ПолучитьОбъект()

Универсальный способ изменить существующий документ. Требует проверки на Неопределено и последующей записи

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

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

РеквизитФормыВЗначение

Правильный путь в модуле формы: работает с данными открытого документа без конфликтов копий

СоздатьДокумент()

Для новых документов. Ссылка появляется только после первой записи

Итог

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

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

Часто задаваемые вопросы

Что вернёт ПолучитьОбъект(), если документ удалён физически?

Метод вернёт значение Неопределено. Поэтому перед обращением к реквизитам результата всегда выполняйте проверку «Если Объект <> Неопределено Тогда», иначе получите ошибку обращения к свойству неопределённого значения.

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

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

Почему изменения объекта не сохраняются?

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

Как получить объект документа в управляемой форме?

В модуле формы используйте серверную процедуру с вызовом РеквизитФормыВЗначение("Объект") — это вернёт объект текущего документа формы. Получение объекта через Ссылка.ПолучитьОбъект() в форме создаст несинхронизированную копию данных и может привести к ошибкам записи.

Чем отличается Записать() от Провести()?

Метод Записать() с режимом «Запись» только сохраняет данные документа без формирования движений. Проведение выполняется либо методом Записать(РежимЗаписиДокумента.Проведение), либо отдельным вызовом логики проведения — при этом заполняются регистры и отрабатывают обработчики проведения.

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

Технически да, но только после тестирования на копии базы. Перепроведение меняет движения по регистрам и может повлиять на остатки и взаиморасчёты. Обрабатывайте документы по одному в попытке/исключении, фиксируйте ошибки в журнале регистрации и имейте актуальную резервную копию.