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

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

Как записать текущий документ программно в 1С

Как программно записать текущий документ в 1С: метод Записать(), режимы проведения, работа с формой и объектом, типичные ошибки и примеры кода.

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

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

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

Разница между записью, проведением и отменой проведения

У документа в 1С три базовых состояния: не записан (новый), записан без проведения и проведён. Метод Записать() переводит объект между этими состояниями в зависимости от переданного режима. Если вызвать его без параметров, выполняется РежимЗаписиДокумента.Запись — документ сохраняется, но остаётся непроведённым, а если был проведён — проведение снимается только при явном указании соответствующего режима, либо система выдаст вопрос в интерактивном режиме.

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

Запись документа из формы

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

&НаКлиенте

Процедура КнопкаЗаписать(Команда)

ЭтаФорма.Записать();

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

Чтобы записать документ с проведением, методу передаётся структура с параметрами записи:

&НаКлиенте

Процедура КнопкаПровести(Команда)

ПараметрыЗаписи = Новый Структура;

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

ЭтаФорма.Записать(ПараметрыЗаписи);

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

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

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

Запись документа по ссылке вне формы

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

&НаСервере

Процедура ЗаписатьДокументПоСсылке(ДокументСсылка)

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

ДокОбъект.Комментарий = "Записан программно";

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

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

Типичная ошибка — вызывать Записать() у ссылки. У объекта типа ДокументСсылка такого метода нет: ссылка — это только идентификатор, данные доступны через неё запросом или через получение объекта. Попытка записи через ссылку приводит к ошибке времени выполнения.

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

Проведение с контролем ошибок

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

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

Попытка

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

Исключение

Сообщить("Не удалось провести " + ДокументСсылка + ": "

+ ОписаниеОшибки());

КонецПопытки;

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

bsl
ДокОбъект = ДокументСсылка.ПолучитьОбъект();
ДокОбъект.Дата = ТекущаяДатаСеанса();
Попытка
    ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
    Сообщить("Документ проведён");
Исключение
    Сообщить("Ошибка: " + ОписаниеОшибки());
КонецПопытки;

Запись нового документа программно

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

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

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

Особенности записи в тонком клиенте и на сервере

Метод Записать() объекта документа доступен только на сервере и в толстом клиенте. В тонком клиенте прямой вызов ДокОбъект.Записать() невозможен — объектный API там недоступен. Поэтому в управляемых формах серверная логика выносится в процедуры с директивой &НаСервере, а клиентская часть только вызывает их.

Если запись выполняется внутри формы, предпочтительнее использовать метод формы Записать(), а не получать объект и записывать его отдельно. Запись объекта «мимо формы» приводит к тому, что форма продолжает показывать устаревшие данные, и при следующем сохранении из формы возникнет конфликт версий.

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

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

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

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

Свойство Проведен
Норма

Истина после успешного проведения

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

Ложь — проведение не выполнено или было отменено

Движения по регистрам
Норма

Записи с регистратором = ссылке документа присутствуют

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

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

Сообщения пользователю
Норма

Нет сообщений об ошибках после записи

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

Есть сообщения о незаполненных реквизитах или отказе проведения

FAQ

Чем отличается Записать() у формы от Записать() у объекта?

Метод формы сохраняет данные, которые пользователь видит и редактирует, и синхронизирует форму с базой. Метод объекта работает с отдельным экземпляром в памяти: если тот же документ открыт в форме, запись объекта приведёт к рассинхронизации и конфликту версий при следующем сохранении из формы.

Как провести документ без открытия формы?

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

Почему документ записался, но движений нет?

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

Можно ли записать документ в тонком клиенте напрямую?

Объектный метод Записать() в тонком клиенте недоступен. Используйте запись через форму (ЭтаФорма.Записать()) или выносите логику в серверную процедуру, которую клиент вызывает удалённо.

Как отменить проведение программно?

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

Итог

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

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