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

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

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

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

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

Ниже разобраны оба метода с примерами кода для обычных и управляемых форм, проверка прав и ссылочной целостности, а также типичные ошибки, которые приводят к «битым» ссылкам и потере данных. Примеры написаны на встроенном языке 1С и подходят для типовых и самописных конфигураций на платформе 8.3.

Какие способы удаления документа существуют в 1С

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

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

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

Пометка удаления

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

Непосредственное удаление

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

Как пометить документ на удаление программно

Чтобы установить пометку удаления, нужно получить объект документа по ссылке и вызвать метод УстановитьПометкуУдаления(). Метод автоматически отменяет проведение документа, если оно было выполнено, и записывает объект с новым признаком.

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

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

Если ДокументОбъект = Неопределено Тогда

Возврат; // объект не найден в базе

КонецЕсли;

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

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

Для снятия пометки тот же метод вызывается с параметром Ложь. Если документ был проведён, пометка удаления автоматически его распроводит; при снятии пометки проведение не восстанавливается — документ нужно провести заново.

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

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

Непосредственное удаление выполняется методом Удалить() объекта документа. Документ стирается вместе с движениями по регистрам без каких-либо проверок ссылочной целостности.

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

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

Если ДокументОбъект = Неопределено Тогда

Возврат;

КонецЕсли;

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

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

Для массового удаления удобнее функция УдалитьОбъекты(МассивСсылок, РежимКонтроля). Вторым параметром можно указать РежимУдаленияОбъектов.Контролируемый — тогда платформа проверит ссылки и не удалит объекты, на которые есть ссылки, вернув список ошибок. Режим Неконтролируемый удаляет всё без проверок.

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

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

УдаленныеОбъекты = Неопределено;

УдалитьОбъекты(МассивСсылок,

РежимУдаленияОбъектов.Контролируемый, УдаленныеОбъекты);

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

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

Если Не ПравоДоступа("Удаление",

Метаданные.Документы.РеализацияТоваровУслуг) Тогда

ВызватьИсключение "Недостаточно прав для удаления документа";

КонецЕсли;

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

Порядок безопасного удаления
  1. 1
    Сделайте резервную копию базы или убедитесь, что она есть
  2. 2
    Проверьте право Удаление через ПравоДоступа()
  3. 3
    Найдите ссылки на документ через НайтиПоСсылкам()
  4. 4
    Установите пометку удаления или удалите объект выбранным методом
  5. 5
    Проверьте результат: пометка установлена, ссылок на объект не осталось

Как найти и обработать ссылки на удаляемый документ

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

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

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

НайденныеСсылки = НайтиПоСсылкам(МассивСсылок);

Если НайденныеСсылки.Количество() > 0 Тогда

// есть зависимые объекты — удалять неконтролируемо нельзя

КонецЕсли;

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

Массовое удаление документов за период

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

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

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

"ВЫБРАТЬ

| Реализация.Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Дата МЕЖДУ &Начало И &Конец";

Запрос.УстановитьПараметр("Начало", НачалоДня(ДатаНачала));

Запрос.УстановитьПараметр("Конец", КонецДня(ДатаОкончания));

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

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

Попытка

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

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

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

КонецЦикла;

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

Исключение

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

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

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

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

Для разовой очистки данных часто удобнее не писать код, а воспользоваться типовой обработкой «Групповое изменение реквизитов» или «Удаление помеченных объектов» из раздела «Администрирование». Код оправдан, когда удаление нужно выполнять регулярно по расписанию или в рамках обмена данными.
ПЗ
Практическое замечание

Типичные ошибки при программном удалении

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

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

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

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

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

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

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

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

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

Равно Истина после пометки

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

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

ПолучитьОбъект() после Удалить()
Норма

Возвращает Неопределено

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

Объект существует — удаление не выполнено

НайтиПоСсылкам() после удаления
Норма

Таблица ссылок пуста

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

Найдены битые ссылки — требуется очистка зависимых объектов

Итог

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

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

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

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

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

Почему документ не удаляется и выдаёт ошибку?

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

Как удалить помеченные документы окончательно?

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

Как удалить документ в фоновом задании или по расписанию?

Оберните логику удаления в серверную процедуру общего модуля с признаком «Сервер» и вызывайте её через ФоновыеЗадания.Выполнить() или регламентное задание. В фоне недоступен интерактивный контекст, поэтому все параметры (период, вид документа) передавайте явно, а ошибки пишите в журнал регистрации.

Восстановятся ли движения документа после снятия пометки удаления?

Нет. При установке пометки удаления проведение отменяется и движения очищаются. После снятия пометки документ нужно провести заново — тогда движения сформируются повторно по текущим данным документа.

Можно ли удалить документ, на который есть ссылки?

Технически да — через неконтролируемое удаление, но в ссылающихся объектах останутся битые ссылки вида «Объект не найден». Правильный путь — сначала очистить или заменить ссылки в зависимых объектах (их находит НайтиПоСсылкам), и только потом удалять документ.