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