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

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

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

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

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

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

Получение объекта документа для проведения

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

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

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

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

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

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

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

НовыйДок.Организация = Организация;

// заполнение табличной части Товары

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

Режимы записи: проведение, отмена проведения, оперативное проведение

Метод Записать() принимает два параметра: режим записи и режим проведения. Режим записи определяет, что произойдёт с документом:

  • РежимЗаписиДокумента.Запись — простое сохранение без движений по регистрам;
  • РежимЗаписиДокумента.Проведение — сохранение и формирование движений;
  • РежимЗаписиДокумента.ОтменаПроведения — сохранение с удалением движений.

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

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

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

// Оперативное проведение

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

РежимПроведенияДокумента.Оперативный);

Проведение без открытия объекта: пакетная обработка документов

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ПриходнаяНакладная.Ссылка

|ИЗ

| Документ.ПриходнаяНакладная КАК ПриходнаяНакладная

|ГДЕ

| ПриходнаяНакладная.Дата МЕЖДУ &Нач И &Кон

| И НЕ ПриходнаяНакладная.ПометкаУдаления

|УПОРЯДОЧИТЬ ПО

| ПриходнаяНакладная.Дата";

Запрос.УстановитьПараметр("Нач", НачалоПериода);

Запрос.УстановитьПараметр("Кон", КонецПериода);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Попытка

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

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

Исключение

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

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

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

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

КонецЦикла;

Обратите внимание на сортировку по дате: перепроведение в хронологическом порядке критично, когда документы контролируют остатки. Если провести отгрузку раньше поступления, контроль остатков её отклонит, хотя при правильном порядке всё прошло бы успешно.

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

Порядок пакетного перепроведения
  1. 1
    Сделайте резервную копию базы или убедитесь, что есть актуальный бэкап
  2. 2
    Сформируйте запрос по документам периода с сортировкой по дате
  3. 3
    Обойдите выборку, проводя каждый документ в попытке/исключении
  4. 4
    Записывайте ошибки в журнал регистрации с указанием ссылки
  5. 5
    После завершения разберите список непроведённых документов вручную

Транзакции, блокировки и многопоточность

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

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

На управляемых формах не вызывайте серверные методы записи напрямую из клиентского кода объекта — используйте серверные процедуры общих модулей с признаком «Сервер». Контекст формы и объект документа на клиенте — это ДанныеФормыСтруктура, для программного проведения нужен отдельный серверный вызов.

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

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

Типичные причины отказа в проведении:

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

Для диагностики полезно обернуть запись и вывести ОписаниеОшибки() вместе с представлением документа — в пакетных обработках это единственный способ понять, какие именно документы не провелись и почему.

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

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

Признак Проведен у объекта после Записать()
Норма

Равен Истина

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

Ложь — проведение не выполнено, смотрите сообщения об ошибках

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

Наборы записей заполнены согласно логике документа

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

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

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

Нет записей об ошибках по обработанным документам

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

Есть ошибки блокировок, прав или контроля остатков

Типичные ошибки и ограничения

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

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

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

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

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

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

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

Вынесите логику проведения в серверную процедуру общего модуля и запустите её через ФоновыеЗадания.Выполнить() или ДлительныеОперации.ВыполнитьВФоне() в БСП. Учтите, что в фоне недоступны интерактивные вызовы, а пользовательским контекстом будет сеанс фонового задания — проверьте его права.

Чем отличается Записать с проведением от УстановитьПроведен?

Стандартного метода «УстановитьПроведен» у объекта документа нет. Изменить признак проведения можно только через Записать() с соответствующим режимом: это гарантирует выполнение обработчиков проведения и корректное формирование или удаление движений по регистрам.

Почему документ не проводится программно, хотя вручную проводится?

Чаще всего дело в контексте: у фонового задания или текущего пользователя кода нет нужных прав, либо в модуле проведения есть обращение к данным, которые при интерактивной работе берутся из формы (например, параметры сеанса или реквизиты, заполняемые обработчиками формы). Сравните описание ошибки из попытки/исключения с логикой модуля документа.

Нужно ли открывать транзакцию вручную при проведении одного документа?

Нет, метод Записать() сам выполняется в транзакции: либо документ проводится целиком, либо не проводится вообще. Явная транзакция нужна только когда требуется атомарно записать несколько объектов — несколько документов или документ вместе со связанными записями.

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

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

Итог

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

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