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