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