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