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

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

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

Как программно очистить движения документа в 1С: методы Очистить(), УстановитьАктивность, запись набора записей, типичные ошибки и проверка результата.

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

Ключевой объект для работы — коллекция Движения объекта документа. Каждый элемент коллекции — это набор записей по конкретному регистру, у которого есть методы Очистить(), Записать() и свойство активности. Важно понимать: просто вызвать Очистить() недостаточно — набор записей нужно ещё и записать в базу, иначе изменения останутся только в памяти.

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

Как устроены движения документа и когда их нужно очищать

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

Очистка движений требуется в нескольких типовых сценариях:

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

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

Способ 1: отмена проведения — самый безопасный вариант

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

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

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

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

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

Способ 2: очистка наборов записей через коллекцию Движения

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

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

Для Каждого НаборЗаписей Из ДокументОбъект.Движения Цикл

НаборЗаписей.Очистить();

НаборЗаписей.Записать(Истина);

КонецЦикла;

Параметр Истина в методе Записать() означает запись с замещением: существующие записи регистратора удаляются и заменяются содержимым набора (в данном случае — пустым). Если вызвать Записать() без параметра, замещение также выполняется по умолчанию, но явное указание делает код понятнее.

Если нужно очистить движения только по одному регистру, обращайтесь к набору по имени регистра:

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

Набор = ДокументОбъект.Движения.ОстаткиТоваров;

Набор.Очистить();

Набор.Записать(Истина);

bsl
ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
Для Каждого НаборЗаписей Из ДокументОбъект.Движения Цикл
	НаборЗаписей.Очистить();
	НаборЗаписей.Записать(Истина);
КонецЦикла;

Способ 3: прямая работа с набором записей регистра без объекта документа

Необязательно получать объект документа целиком. Можно создать набор записей регистра напрямую, установить отбор по регистратору и записать пустой набор. Это быстрее при массовой обработке, потому что не загружаются реквизиты и табличные части документа.

НаборЗаписей = РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);

НаборЗаписей.Записать(Истина);

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

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

Маршрут решения

Как выбрать способ

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

Установка активности вместо удаления записей

Альтернатива физическому удалению — установить движениям признак неактивности. Неактивные записи остаются в таблице регистра, но не участвуют в расчёте итогов. Это полезно, когда нужно временно исключить влияние документа с возможностью быстрого восстановления.

НаборЗаписей = РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);

НаборЗаписей.Прочитать();

НаборЗаписей.УстановитьАктивность(Ложь);

НаборЗаписей.Записать();

Здесь важен порядок: сначала Прочитать(), чтобы загрузить существующие записи, затем УстановитьАктивность(Ложь), затем запись. Если пропустить чтение, набор будет пустым и записывать активность будет нечему. Обратное включение выполняется тем же кодом с параметром Истина.

Удаление или деактивация

Очистить() + Записать(Истина)

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

УстановитьАктивность(Ложь)

Записи остаются в базе, но исключаются из итогов. Подходит для временного отключения. Легко откатить, но таблица регистра не уменьшается.

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

Штатный режим: удаляет движения и снимает пометку проведения. Самый безопасный, но меняет статус документа.

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

После очистки убедитесь, что записи действительно удалены. Проще всего выполнить запрос к регистру с отбором по регистратору и проверить, что результат пустой:

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

Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 * ИЗ РегистрНакопления.ОстаткиТоваров

|ГДЕ Регистратор = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

Если Запрос.Выполнить().Пустой() Тогда

// движения очищены

КонецЕсли;

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

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

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

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

Записи регистра по регистратору
Норма

Запрос с отбором по регистратору возвращает пустой результат

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

Записи остались — запись набора не выполнилась или очищён другой регистр

Статус документа
Норма

Статус соответствует замыслу: непроведён после ОтменаПроведения или проведён после ручной очистки

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

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

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

Остатки и обороты пересчитались без влияния документа

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

Отчёт показывает старые цифры — проверьте актуальность итогов регистра

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

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

Ещё несколько ограничений, о которых нужно помнить:

  • при записи наборов срабатывают подписки на события регистров — если в них есть логика, рассчитанная на непустой набор, возможны ошибки;
  • запись наборов документа, находящегося в закрытом периоде, блокируется датой запрета изменения данных — обходите через привилегированный режим только осознанно;
  • если документ входит в последовательность, очистка движений не сдвигает границу последовательности автоматически — восстанавливайте её отдельно;
  • в регистрах бухгалтерии наборы записей могут быть связаны с корреспонденциями и субконто — прямая очистка допустима, но проверяйте отчёты по счетам после обработки.
Типичные ошибки
01
Вызвали Очистить(), но не вызвали Записать() — записи в базе остались, обработка отработала «вхолостую»
02
Записали пустой набор без параметра замещения в регистре, где это критично, или наоборот — с замещением затёрли записи другого регистратора при ошибке в отборе
03
Не установили отбор по регистратору у набора записей — риск затронуть лишние данные при записи
04
Обратились к Движения.ИмяРегистра у документа, который не является регистратором этого регистра — исключение и остановка обработки
05
Очистили движения в цикле без транзакции — при сбое часть документов осталась в промежуточном состоянии

FAQ

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

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

Почему после Очистить() записи остались в регистре?

Метод Очистить() удаляет строки только в памяти. Чтобы изменения попали в базу, нужно вызвать Записать(Истина) у того же набора записей. Также проверьте, что запись не завершается исключением, которое перехватывается без сообщения.

Чем отличается Записать(Истина) от Записать(Ложь) у набора записей?

Параметр управляет замещением. Записать(Истина) сначала удаляет существующие записи по регистратору, затем записывает содержимое набора. Записать(Ложь) добавляет записи без удаления существующих, что для регистров с уникальным регистратором обычно приводит к конфликту или дублям.

Как очистить движения у большого количества документов без падения производительности?

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

Можно ли восстановить очищенные движения?

Если документ сохранил данные, движения восстанавливаются перепроведением: Записать(РежимЗаписиДокумента.Проведение). Если записи были деактивированы через УстановитьАктивность(Ложь), достаточно прочитать набор и установить активность обратно в Истина.

Очистка движений влияет на границу последовательности?

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

Итог

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

Очистка движений выполняется либо штатной отменой проведения, либо записью пустых наборов записей с замещением. Очистить() без Записать() не меняет данные в базе. Для массовой обработки используйте прямые наборы записей и транзакции, а перед запуском — резервную копию. Если влияние документа нужно отключить временно, используйте УстановитьАктивность(Ложь) вместо удаления записей.