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

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

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

Анализ проблемы и выбор метода проверки

Прежде всего, проанализируем ситуацию: нам необходимо проверить реквизит Физлицо в табличной части Список документа Приказ. Если это поле не заполнено, документ должен быть помечен на удаление.

Важно понимать разницу между типами данных. Если реквизит является ссылкой на справочник (в нашем случае Справочник.ФизическиеЛица), то использование метода ПустаяСтрока() технически неверно. Этот метод предназначен исключительно для строковых типов данных. Для проверки заполненности ссылочных полей, дат или чисел в 1С предусмотрена универсальная функция ЗначениеЗаполнено(). Она возвращает Ложь, если значение является «пустым» для своего типа (пустая ссылка, 0, пустая дата и т.д.).

Способ 1. Перебор объектов (объектная техника)

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

Разберем пример кода для кнопки выполнения:


Процедура КнопкаВыполнитьНажатие(Кнопка)
    // Выбираем все документы типа Приказ
    Выборка = Документы.Приказ.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        ДокументОбъект = Выборка.ПолучитьОбъект();
        НужноУдалить = Ложь;
        
        // Перебираем строки табличной части "Список"
        Для каждого СтрокаТЧ Из ДокументОбъект.Список Цикл
            // Проверяем, заполнено ли физическое лицо
            Если Не ЗначениеЗаполнено(СтрокаТЧ.Физлицо) Тогда
                НужноУдалить = Истина;
                Прервать; // Если нашли хотя бы одну пустую строку, дальше можно не искать
            КонецЕсли;
        КонецЦикла;
        
        // Если условие выполнено и документ еще не помечен на удаление
        Если НужноУдалить И Не ДокументОбъект.ПометкаУдаления Тогда
            Попытка
                ДокументОбъект.УстановитьПометкуУдаления(Истина);
                Сообщить("Документ " + ДокументОбъект + " помечен на удаление.");
            Исключение
                Сообщить("Не удалось обработать документ: " + ОписаниеОшибки());
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

Способ 2. Оптимизированный подход через Запрос (профессиональный метод)

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

Рассмотрим подробнее реализацию этого метода. Мы обратимся напрямую к таблице табличной части документа.


Процедура ВыполнитьПометкуЧерезЗапрос()
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |   ПриказСписок.Ссылка КАК Ссылка
    |ИЗ
    |   Документ.Приказ.Список КАК ПриказСписок
    |ГДЕ
    |   ПриказСписок.Физлицо = ЗНАЧЕНИЕ(Справочник.ФизическиеЛица.ПустаяСсылка)";
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Получаем объект только для тех документов, которые точно нужно пометить
        ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();
        
        Если Не ДокументОбъект.ПометкаУдаления Тогда
            // Используем режим загрузки для ускорения и обхода лишних проверок
            ДокументОбъект.ОбменДанными.Загрузка = Истина;
            ДокументОбъект.УстановитьПометкуУдаления(Истина);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

В этом коде мы использовали ключевое слово РАЗЛИЧНЫЕ. Выясним причину: если в одном документе будет несколько пустых строк, запрос без этого слова вернет одну и ту же ссылку несколько раз. Это приведет к лишним операциям чтения и записи.

Тонкости и рекомендации по безопасной обработке данных

Проанализируем несколько критически важных моментов, которые помогут избежать ошибок при массовом изменении данных:

  1. Режим загрузки: Использование свойства ДокументОбъект.ОбменДанными.Загрузка = Истина позволяет временно отключить прикладные проверки в модуле объекта (например, проверки на корректность заполнения других полей или подписки на события). Это значительно ускоряет процесс и позволяет пометить документ на удаление даже в том случае, если он не проходит стандартную проверку по другим реквизитам.
  2. Проверка на пустую ТЧ: Бывают случаи, когда табличная часть документа вообще не содержит строк после неудачного переноса. Код, приведенный выше, обрабатывает документы с ПУСТЫМИ значениями в СТРОКАХ, но проигнорирует документы с НУЛЕВЫМ количеством строк. Если нужно найти и такие, следует использовать левое соединение основной таблицы документа с таблицей Список в запросе и искать записи, где НомерСтроки ЕСТЬ NULL.
  3. Тестирование: Всегда выполняйте подобные обработки сначала на копии базы данных. Массовое удаление или пометка на удаление — необратимый процесс с точки зрения истории данных, если у вас не настроено версионирование объектов.
  4. Групповое изменение реквизитов: Помните, что в типовых конфигурациях (например, Бухгалтерия для Казахстана) существует встроенная обработка «Групповое изменение реквизитов». В ней можно настроить отбор по табличной части и установить реквизит ПометкаУдаления в значение Истина без написания кода.

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

← На главную