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