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

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

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

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

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

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

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

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

Каждый ссылочный объект в базе 1С хранит служебное поле «Пометка удаления». Когда оно равно Истина, платформа и типовые механизмы трактуют запись как удалённую: она не предлагается в полях ввода при включённом стандартном контроле, не выводится в ряде списков и отчётов, проведённый документ теряет актуальность движений. При этом сама запись физически остаётся в таблицах базы данных.

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

Важно понимать разницу между пометкой и непосредственным удалением. Метод Удалить() у объекта стирает запись немедленно и без проверки ссылок — использовать его в прикладном коде почти никогда не следует. Пометка удаления — безопасный и обратимый способ: снять пометку можно тем же методом с параметром Ложь.

Базовый синтаксис метода УстановитьПометкуУдаления

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

// Пометить элемент справочника на удаление

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

СпрОбъект.УстановитьПометкуУдаления(Истина);

// Снять пометку удаления

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

СпрОбъект.УстановитьПометкуУдаления(Ложь);

Типичная ошибка — попытаться вызвать метод у ссылки: СсылкаНаЭлемент.УстановитьПометкуУдаления(Истина) вызовет ошибку «Метод объекта не обнаружен», потому что у типа СправочникСсылка такого метода нет. Ссылка — это только «указатель»; для изменения объекта нужно сначала получить его объектную сущность через ПолучитьОбъект().

Проверить текущее состояние пометки можно и без получения объекта — у ссылки доступно свойство ПометкаУдаления, которое платформа читает напрямую из данных ссылки:

Если СсылкаНаЭлемент.ПометкаУдаления Тогда

// объект уже помечен

КонецЕсли;

Пометка удаления документов: учёт проведения

С документами есть важная особенность. Если документ проведён, простая установка пометки оставит его движения в регистрах в неоднозначном состоянии. Метод УстановитьПометкуУдаления() при вызове с параметром Истина сам отменяет проведение документа, если документ был проведён, — это стандартное поведение платформы. Тем не менее в коде полезно явно контролировать состояние, чтобы логика обработки была прозрачной.

Процедура ПометитьДокументНаУдаление(ДокументСсылка) Экспорт

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

Если ДокОбъект.ПометкаУдаления Тогда

Возврат; // уже помечен, ничего не делаем

КонецЕсли;

Если ДокОбъект.Проведен Тогда

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

КонецЕсли;

ДокОбъект.УстановитьПометкуУдаления(Истина);

КонецПроцедуры

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

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

Массовая установка пометки: выборка, транзакция, права

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

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| НЕ Номенклатура.ПометкаУдаления

| И Номенклатура.Артикул = """;

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

НачатьТранзакцию();

Попытка

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

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

ОбъектДанных.УстановитьПометкуУдаления(Истина);

КонецЦикла;

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

ВызватьИсключение ОписаниеОшибки();

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

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

Учитывайте права: у пользователя, от имени которого выполняется код, должно быть право «Интерактивная пометка удаления» / право на изменение объекта. В серверном коде при необходимости используют УстановитьПривилегированныйРежим(Истина), но делать это следует осознанно: привилегированный режим обходит и RLS-ограничения, и проверки прав, что может привести к пометке данных, недоступных текущему пользователю.

Интерактивная и программная пометка: в чём разница

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

Кроме того, срабатывают подписки на события и обработчики ПередЗаписью / ПриЗаписи объекта, поскольку установка пометки — это фактически запись объекта. Если в конфигурации есть бизнес-логика на этих событиях (проверки, заполнение служебных полей, регистрация в планах обмена), она выполнится и при программной пометке. Это может быть как полезно (объект корректно зарегистрируется к выгрузке), так и источником неожиданных ошибок — например, обработчик может отказать в записи из-за незаполненного реквизита, который в старых данных пуст.

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

УстановитьПометкуУдаления(Истина)

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

Объект.Удалить()

Немедленное физическое удаление без проверки ссылок. Допустимо только для заведомо изолированных объектов, в прикладном коде почти не используется.

Обработка «Удаление помеченных объектов»

Финальный этап: физически удаляет помеченные объекты с контролем ссылочной целостности. Запускается отдельно, после установки пометок.

Контроль ссылочной целостности и физическое удаление

Установка пометки не проверяет, ссылается ли кто-то на объект. Проверка выполняется на этапе физического удаления — штатной обработкой «Удаление помеченных объектов» (в типовых конфигурациях: раздел «Администрирование» → «Обслуживание»). Обработка строит список помеченных объектов, ищет на них ссылки и удаляет только те, на которые ссылок нет. Объекты со ссылками остаются помеченными, и обработка показывает, где именно они используются.

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

МассивСсылок = Новый Массив;

МассивСсылок.Добавить(СсылкаНаЭлемент);

ТаблицаСсылок = НайтиПоСсылкам(МассивСсылок);

Если ТаблицаСсылок.Количество() = 0 Тогда

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

ОбъектДанных.УстановитьПометкуУдаления(Истина);

Иначе

// объект используется — пометка бессмысленна, физически не удалится

КонецЕсли;

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

Порядок действий для массовой пометки
  1. 1
    Сформируйте запросом список объектов, исключив уже помеченные
  2. 2
    Выведите список на просмотр и убедитесь в корректности отбора
  3. 3
    Сделайте резервную копию базы или выгрузку dt
  4. 4
    Выполните установку пометки в транзакции с обработкой исключений
  5. 5
    Проверьте результат: количество помеченных, отсутствие ошибок в журнале регистрации
  6. 6
    Запустите «Удаление помеченных объектов», если требуется физическое удаление

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

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

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

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

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

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

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

Равно Истина после выполнения кода

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

Осталось Ложь — запись не выполнилась, ищите исключение или отказ в обработчике

Проведённость документа
Норма

Проведен = Ложь, движения отсутствуют

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

Документ помечен, но остался проведённым — проверьте логику отмены проведения

Журнал регистрации
Норма

Нет ошибок за время работы обработки

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

Ошибки записи, блокировок или прав — часть объектов не обработана

Физическое удаление
Норма

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

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

Объект в списке «используется в» — на него есть ссылки, физически не удалится

Частые вопросы

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

Нет, штатного способа изменить пометку через запрос нет: запросы в 1С работают только на чтение. Изменение данных выполняется через объектную модель (ПолучитьОбъект + УстановитьПометкуУдаления) либо через наборы записей и менеджеры записей для регистров. Попытки править таблицы СУБД напрямую нарушают лицензионные ограничения и ломают служебные механизмы платформы.

Почему УстановитьПометкуУдаления завершается ошибкой «Ошибка блокировки»?

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

Как снять пометку удаления у большой группы объектов?

Тем же методом с параметром Ложь: в цикле получаете объект и вызываете УстановитьПометкуУдаления(Ложь). Для документов после снятия пометки проверьте, нужно ли восстановить проведение — автоматически оно не возвращается.

Уйдёт ли пометка удаления в другую базу при синхронизации?

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

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

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

Чем опасен метод Удалить() вместо пометки?

Он стирает объект физически сразу и без проверки ссылок. Все документы и регистры, ссылавшиеся на объект, получат «битые» ссылки вида «Объект не найден», которые сложно восстановить. В прикладном коде используйте пометку удаления, а физическое удаление доверяйте штатной обработке с контролем целостности.

Итог

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

Пометка удаления ставится методом УстановитьПометкуУдаления(Истина) у объектной сущности, полученной через Ссылка.ПолучитьОбъект(). Для документов контролируйте отмену проведения, для массовых операций используйте транзакции и предварительный просмотр отбора. Физическое удаление — отдельный этап через обработку «Удаление помеченных объектов» с контролем ссылочной целостности.