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

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

Как программно провести документ в 1С 8

Как программно провести документ в 1С 8: методы Записать с РежимЗаписиДокумента.Проведение, обработка ошибок, проведение по регистрам, примеры кода и типичные ошибки.

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

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

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

Базовый способ: метод Записать с режимом проведения

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

Минимальный код проведения выглядит так:

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

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

Метод Записать принимает два параметра: режим записи и режим проведения. Для проведения используются значения перечисления РежимЗаписиДокумента: Проведение — провести документ, ОтменаПроведения — распровести, Запись — просто записать без проведения.

Второй параметр — РежимПроведенияДокумента — управляет оперативностью: Оперативный проверяет, что дата документа соответствует текущему моменту, и контролирует остатки на момент времени документа; Неоперативный позволяет проводить документы задним числом. Если параметр не указан, платформа сама выбирает режим по дате документа.

Проведение вновь созданного документа

Частая задача — создать документ программно и сразу провести. Для этого используется менеджер документа Документы.ИмяДокумента.СоздатьДокумент(), затем заполняются реквизиты и вызывается запись с проведением.

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

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

НовыйДокумент.Контрагент = КонтрагентСсылка;

// заполнение табличной части

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

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

СтрокаТовара.Количество = 5;

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

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

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

Обработка ошибок при проведении

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

Попытка

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

Исключение

ТекстОшибки = ОписаниеОшибки();

ЗаписьЖурналаРегистрации("ПроведениеДокументов",

УровеньЖурналаРегистрации.Ошибка, , ДокументСсылка, ТекстОшибки);

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

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

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

Отмена проведения и перепроведение

Для отмены проведения используется тот же метод с другим режимом: Записать(РежимЗаписиДокумента.ОтменаПроведения). При этом платформа удаляет движения документа по всем регистрам и снимает пометку проведения.

Если нужно перепровести документ после изменения реквизитов, достаточно снова вызвать запись с режимом Проведение — платформа сама удалит старые движения и сформирует новые. Явно отменять проведение перед повторным проведением не требуется.

Для массового перепроведения группы документов существуют типовые механизмы: в конфигурациях на БСП есть обработка «Групповое перепроведение документов», а программно можно использовать метод Документы.ИмяДокумента.ПровестиДокументы() в новых версиях платформы либо последовательный цикл с проведением каждого объекта. Цикл предпочтительнее, когда нужен детальный протокол ошибок по каждому документу.

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

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

Универсальный способ, полный контроль над объектом и обработкой ошибок. Требует получения объекта — дороже по ресурсам при массовой обработке

УстановитьПометкуУдаления / Записать без режима

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

Типовая групповая обработка перепроведения

Готовый инструмент без кода, но с ограниченной диагностикой ошибок и меньшей гибкостью

Проведение в транзакциях и блокировки

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

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

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

Проверка результата: проведён ли документ

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

Если ДокументОбъект.Проведен Тогда

// документ успешно проведён

КонецЕсли;

Для проверки движений используйте запрос к таблице регистра с отбором по регистратору. Это особенно важно, когда модуль проведения может завершиться без ошибки, но не сформировать записи из-за внутренних условий конфигурации.

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

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

Свойство Проведен у объекта или ссылки
Норма

Равно Истина после Записать без исключения

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

Ложь — документ записан, но не проведён

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

Запрос по регистратору возвращает ожидаемые записи

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

Движений нет или набор неполный — проверяйте ОбработкаПроведения

Журнал регистрации
Норма

Нет ошибок по событию проведения

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

Ошибки блокировок или отказ в проведении

Отчёты по учёту (остатки, взаиморасчёты)
Норма

Показатели изменились ожидаемым образом

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

Цифры не изменились — проведение не состоялось

Особенности управляемых форм и клиент-серверного кода

В управляемом приложении код делится на клиентский и серверный. Проведение документа возможно только на сервере, поэтому из клиентской процедуры вызывайте серверный метод общего модуля с признаками Сервер и, при необходимости, ВызовСервера. Директива &НаСервере в модуле формы тоже подходит, если работа идёт с данными текущей формы.

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

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

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

Итог

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

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

Частые вопросы

Чем отличается РежимЗаписиДокумента.Проведение от РежимЗаписиДокумента.Запись?

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

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

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

Почему Записать с режимом проведения не выдаёт ошибку, но документ не проведён?

Чаще всего в процедуре ОбработкаПроведения модуля объекта установлен Отказ = Истина с выводом сообщения пользователю. В толстом клиенте такое сообщение видно в панели сообщений, а программно отказ проявляется как исключение. Проверьте модуль документа и подписки на события проведения.

Как провести документ задним числом?

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

Как программно провести документ из внешней обработки?

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

Что делать при ошибке «Конфликт блокировок при выполнении транзакции»?

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