Как быстро и корректно пометить на удаление большое количество документов в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Причина проблемы: Коварство флага ОбменДанными.Загрузка

Рассмотрим ситуацию, описанную в теме: пользователь пытается пометить документы, включив режим ОбменДанными.Загрузка = Истина. Это распространенная ошибка при попытке ускорить процесс. Разберем по шагам, что происходит в системе в этот момент:

  1. Когда установлен этот флаг, платформа 1С отключает выполнение практически всех встроенных проверок и обработчиков событий в модуле объекта (ПередЗаписью, ПриЗаписи).
  2. В нормальном режиме при установке пометки удаления система вызывает метод, который автоматически снимает документ с проведения и инициирует очистку движений по всем регистрам.
  3. В режиме Загрузка = Истина система просто записывает значение Истина в реквизит ПометкаУдаления и устанавливает состояние Проведен = Ложь в заголовке таблицы документа, но не заходит в логику удаления движений.

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

Способ 1. Программная установка пометки через метод объекта

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

Рассмотрим пример кода для такой обработки:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПриходТовара.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.ПриходТовара КАК ПриходТовара
    |ГДЕ
    |	НЕ ПриходТовара.ПометкаУдаления
    |	И ПриходТовара.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания";

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

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

Пока Выборка.Следующий() Цикл
    // Получаем объект документа для изменения
    ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();
    
    // Метод УстановитьПометкуУдаления(Истина) делает все необходимые действия:
    // 1. Снимает с проведения (если был проведен)
    // 2. Очищает движения во всех регистрах
    // 3. Устанавливает флаг пометки удаления
    ДокОбъект.УстановитьПометкуУдаления(Истина);
КонецЦикла;

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

Способ 2. Очистка «повисших» движений вручную

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

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


// Предположим, мы чистим регистр накопления "ТоварыНаСкладах"
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ТоварыНаСкладах.Регистратор КАК Регистратор
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
    |ГДЕ
    |	ТоварыНаСкладах.Регистратор.ПометкаУдаления";

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

Пока Выборка.Следующий() Цикл
    // Создаем пустой набор записей с отбором по конкретному документу
    Набор = РегистрыНакопления.ТоварыНаСкладах.СоздатьНаборЗаписей();
    Набор.Отбор.Регистратор.Установить(Выборка.Регистратор);
    
    // Записываем пустой набор, тем самым удаляя старые записи из БД
    Набор.Записать(Истина); 
КонецЦикла;

Важный нюанс: метод Записать(Истина) с пустым набором эффективно удаляет все записи регистра по данному регистратору. Это значительно быстрее, чем перепроведение документов.

Способ 3. Использование Библиотеки стандартных подсистем (БСП)

В современных конфигурациях (ЕРП, УТ 11, Бухгалтерия 3.0) разработчики 1С уже предусмотрели инструменты для массовой работы с объектами. Если мы хотим сделать все максимально эффективно, стоит обратиться к общему модулю ОбменДаннымиСервер.

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


// Пример использования БСП для очистки движений
Для Каждого ДокСсылка Из МассивДокументов Цикл
    ОбменДаннымиСервер.УдалитьДвиженияДокумента(ДокСсылка);
КонецЦикла;

Способ 4. Массовое удаление через SQL (только для экспертов)

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

  1. Идентифицируются таблицы документов (_DocumentXXX) и таблицы движений (_AccumRegXXX).
  2. Выполняется UPDATE для таблицы документов, устанавливающий флаг пометки удаления и снимающий флаг проведения.
  3. Выполняется DELETE записей в таблицах движений, где идентификатор регистратора совпадает со списком удаляемых документов.
  4. Обязательное условие: После выполнения таких манипуляций в консоли 1С необходимо запустить «Пересчет итогов», иначе данные в отчетах будут неверными из-за того, что агрегированные таблицы итогов не обновились при прямом SQL-удалении.

Рекомендации по ускорению процесса

Если 7 500 документов все же обрабатываются слишком долго (например, из-за сложных подписок на события), проанализируем следующие советы:

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

← На главную