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

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

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

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

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

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

Ниже разобраны рабочие варианты кода для обычных и управляемых форм, условия, при которых каждый подход безопасен, и способы проверить результат. Примеры ориентированы на версии платформы 8.3, но общая логика справедлива и для более ранних релизов линейки 8.x.

Что происходит при перепроведении документа

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

Важно понимать: перепроведение не откатывает документ к какому-то прежнему состоянию, а пересчитывает его «с нуля». Если в конфигурации изменился алгоритм проведения, после перепроведения движения будут соответствовать новому алгоритму, даже если сам документ не менялся.

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

Перепроведение одного документа через Записать()

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

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

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

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

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

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

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

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

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

Метод Провести() и отличия от Записать()

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

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

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

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

Оба метода выполняются в транзакции: если в обработчике проведения возникает исключение, движения и сам документ остаются в исходном состоянии. Это защищает базу от «половинчатых» записей, но требует корректной обработки ошибок в вашем коде.

Массовое перепроведение документов за период

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

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

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

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода

| И РеализацияТоваровУслуг.Проведен

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

| РеализацияТоваровУслуг.Дата";

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

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

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

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

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

Попытка

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

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

Исключение

Сообщить("Ошибка: " + Выборка.Ссылка + " — " + ОписаниеОшибки());

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

КонецЦикла;

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

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

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

Перепроведение с восстановлением последовательностей

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

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

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

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

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

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

// перепроведение успешно

КонецЕсли;

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

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

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

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

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

Равно Истина после записи

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

Ложь — проведение не выполнено, ищите ошибку в протоколе

Движения документа
Норма

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

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

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

Итоги отчётов
Норма

Остатки и обороты соответствуют ожиданиям

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

Отрицательные остатки, скачки себестоимости

Граница последовательности
Норма

Стоит на конце периода

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

Съехала на середину — нужно восстановление

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

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

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

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

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

Когда программное перепроведение не нужно

Не каждая задача требует кода. Разовое перепроведение удобнее выполнить интерактивно: открыть документ и нажать «Провести» или «Провести и закрыть». Групповое перепроведение за период в типовых конфигурациях доступно через стандартные обработки («Групповое перепроведение документов», «Проведение документов» в разделе администрирования).

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

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

Интерактивное проведение

Подходит для единичных документов; не требует кода, но не масштабируется

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

Для перепроведения за период без программирования; ограничена стандартными отборами

Свой код с запросом и циклом

Полный контроль отборов, протокола и ошибок; требует тестирования на копии

Восстановление последовательностей

Обязателен при нарушенной хронологии партий и расчётов; дольше простого перепроведения

FAQ

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

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

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

Оперативное проведение фиксирует движения «прямо сейчас» и доступно только для документов с текущей датой. Для документов прошлых периодов используется неоперативное проведение — оно не проверяет совпадение даты документа с текущей.

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

Скорее всего, нарушена хронология: поздние документы уже списали остатки, которые раньше принадлежали этому. Решение — перепроводить документы строго по дате или восстанавливать последовательность целиком.

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

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

Можно ли отменить проведение программно?

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

Попадут ли перепроведённые документы в обмен данными?

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

Итог

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

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