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

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

1С: как программно пометить на удаление элемент справочника

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

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

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

Ключевой момент, который нужно понять сразу: пометка устанавливается не у ссылки, а у объекта. Ссылка — это только «указатель» на данные, изменить её нельзя. Чтобы изменить состояние элемента, нужно получить объект через метод ПолучитьОбъект(), изменить его и записать.

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

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

ЭлементСсылка = Справочники.Номенклатура.НайтиПоКоду("000000123");

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

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

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

КонецЕсли;

Метод сам выполняет запись объекта, поэтому отдельно вызывать Записать() после него не требуется. Если элемент уже имел нужную пометку, платформа просто зафиксирует состояние без ошибки.

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

bsl
ЭлементОбъект = ЭлементСсылка.ПолучитьОбъект();
ЭлементОбъект.УстановитьПометкуУдаления(Истина); // пометить
ЭлементОбъект.УстановитьПометкуУдаления(Ложь);   // снять пометку

Альтернатива: установка свойства ПометкаУдаления вручную

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

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

ЭлементОбъект.ПометкаУдаления = Истина;

ЭлементОбъект.Записать();

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

Важное ограничение: прямое изменение свойства ПометкаУдаления у ссылки невозможно. Конструкция ЭлементСсылка.ПометкаУдаления = Истина работать не будет — у ссылочного типа свойство доступно только для чтения. Это одна из самых частых ошибок начинающих разработчиков.

Массовая пометка элементов по условию

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

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

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

"ВЫБРАТЬ

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

|ИЗ

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

|ГДЕ

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

| И Номенклатура.Архивный";

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

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

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

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

КонецЦикла;

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

Пометка групп и подчинённых элементов

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

Для пометки всей ветки используйте запрос с условием В ИЕРАРХИИ(&Группа). Это гарантирует, что будут обработаны все подчинённые элементы независимо от глубины вложенности.

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

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

"ВЫБРАТЬ

| Контрагенты.Ссылка КАК Ссылка

|ИЗ

| Справочник.Контрагенты КАК Контрагенты

|ГДЕ

| Контрагенты.Ссылка В ИЕРАРХИИ(&Группа)

| И НЕ Контрагенты.ПометкаУдаления";

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

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

Проверка результата и контрольные точки

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

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

Сообщить("Элемент помечен на удаление");

КонецЕсли;

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

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

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

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

Возвращает Истина после пометки

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

Возвращает Ложь — запись не выполнилась, ищите ошибку в логах

Отображение в списке справочника
Норма

Элемент с перечёркнутой иконкой или скрыт фильтром

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

Элемент выглядит обычно — пометка не установлена

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

Есть запись о изменении данных

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

Ошибки записи, отказ в подписках на события

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

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

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

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

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

Снятие пометки и восстановление элемента

Пометка на удаление обратима. Чтобы восстановить элемент, вызовите тот же метод с параметром Ложь или присвойте свойству значение Ложь и запишите объект. Никакие данные элемента при пометке не теряются — меняется только один служебный признак.

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

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

Восстановление безопасно до тех пор, пока элемент не удалён физически обработкой «Удаление помеченных объектов». После физического удаления вернуть данные штатными средствами нельзя — только из резервной копии. Поэтому пометка на удаление — это «карантин», а не удаление, и путать эти состояния нельзя.

Чем пометка отличается от непосредственного удаления

Метод Удалить() у объекта справочника удаляет элемент немедленно и без проверки ссылочной целостности: если на элемент ссылаются документы или регистры, в них останутся «битые ссылки» вида «Объект не найден». Именно поэтому в прикладном коде непосредственное удаление почти никогда не применяют.

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

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

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

Рекомендуемый способ: явно выражает намерение, сам выполняет запись, корректно работает с обработчиками событий

ПометкаУдаления = Истина + Записать()

Подходит, когда пометка меняется вместе с другими реквизитами в одной записи; чуть менее читаемо

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

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

Итог

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

Пометка на удаление устанавливается у объекта, а не у ссылки: ПолучитьОбъект() → УстановитьПометкуУдаления(Истина). Для снятия пометки используется тот же метод с параметром Ложь. Физическое удаление выполняется отдельно штатной обработкой с контролем ссылочной целостности, поэтому пометка — безопасный и обратимый способ вывода элемента из работы.

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

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

Нет. Любое изменение данных в 1С выполняется через объектную модель: сначала Ссылка.ПолучитьОбъект(), затем изменение и запись. Ссылка предназначена только для чтения реквизитов и идентификации элемента.

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

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

Нужно ли вызывать Записать() после УстановитьПометкуУдаления?

Нет, метод сам выполняет запись объекта. Дополнительный вызов Записать() приведёт к повторной записи и повторному срабатыванию подписок на события, что при массовой обработке заметно замедлит выполнение.

Пометится ли группа справочника вместе с элементами внутри?

Программно — нет, автоматической рекурсии не происходит. Чтобы пометить всю ветку, выберите элементы запросом с условием В ИЕРАРХИИ(&Группа) и обработайте каждый в цикле.

Что произойдёт с документами, где используется помеченный элемент?

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

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

Оберните код в УстановитьПривилегированныйРежим(Истина) в серверном контексте. В этом режиме проверки прав отключаются, поэтому корректность отбора элементов полностью ложится на разработчика — используйте приём осознанно.