Как в 1С 7.7 удалить строку из Таблицы Значений и пометить элемент справочника на удаление

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Метод обратного обхода Таблицы Значений

Первое, с чем сталкивается программист при попытке удаления строк в цикле — это изменение индексов. Если мы будем использовать обычный цикл Для от 1 до КоличествоСтрок(), то при удалении текущей строки все последующие сдвинутся вверх. В результате следующая за удаленной строка будет пропущена. Рассмотрим правильный подход — использование обратного цикла. Проанализируем пример кода:


// Создаем объект для работы со справочником
Спр = СоздатьОбъект("Справочник.Контрагенты");

// ТЗконтрагенты - это наша таблица значений на форме или в памяти
// Начинаем цикл с конца таблицы к началу
Для н = -ТЗконтрагенты.КоличествоСтрок() по -1 Цикл
    // Используем отрицательный индекс для получения строки с конца
    ТЗконтрагенты.ПолучитьСтрокуПоНомеру(-н);
    
    Если <УсловиеУдаления> Тогда
        // Сначала работаем с базой данных
        Если Спр.НайтиЭлемент(ТЗконтрагенты.Контрагент) = 1 Тогда
            // Устанавливаем пометку на удаление (параметр 0)
            Спр.Удалить(0); 
        КонецЕсли;
        
        // Затем удаляем строку из самой таблицы
        ТЗконтрагенты.УдалитьСтроку();
    КонецЕсли;
КонецЦикла;

В данном примере мы используем математическую хитрость с отрицательными числами, которая часто встречается в старом коде 1С 7.7. Однако можно использовать и более классический вариант: Для н = КолСтрок По 1 Шаг -1. Главное — удалять элементы именно с конца, чтобы текущий индекс всегда оставался актуальным для еще не обработанных строк.

Различие между физическим удалением и пометкой на удаление

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

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

Если же ваша задача — не пометить на удаление, а просто изменить значение какого-либо реквизита (например, УдалитьИзСписка = Перечисление.Булево.Да), не забывайте вызывать метод Записать() после изменения реквизита, иначе данные в базе не обновятся.

Типичные ошибки при поиске элемента

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

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

Несоответствие видов справочников: Мы должны искать элемент именно тем объектом СоздатьОбъект, к виду которого он относится. Разберем фрагмент кода, добавляющий проверку типов для защиты от ошибок:


Спр = СоздатьОбъект("Справочник.БП_УслугиБанку");
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    ЭлементИзТЗ = ТЗ.Объект;
    
    // Проверяем, является ли значение в ТЗ справочником нужного вида
    Если ТипЗначенияСтр(ЭлементИзТЗ) = "Справочник" Тогда
        Если ЭлементИзТЗ.Вид() = Спр.Вид() Тогда
            Если Спр.НайтиЭлемент(ЭлементИзТЗ) = 1 Тогда
                Спр.Удалить(0); // Помечаем
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Оптимизация работы с большими таблицами

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

Рассмотрим алгоритм ускоренной обработки:

  1. Добавим в ТЗ служебную колонку ФлагУдаления.
  2. Пометим в этой колонке те строки, которые нужно удалить.
  3. Выполним сортировку: ТЗ.Сортировать("ФлагУдаления-");.
  4. Найдем первую строку, подлежащую удалению, через НайтиЗначение().
  5. Выгрузим часть таблицы, которую нужно оставить, в новую ТЗ или используем КоличествоСтрок(), чтобы обрезать таблицу за один прием.

Также для ускорения работы с базой данных при массовой пометке на удаление обязательно используйте транзакции. Это позволит системе выполнить запись всех изменений одним блоком, что в SQL-версиях 1С 7.7 дает прирост скорости в разы:


НачатьТранзакцию();
// ... код цикла с пометкой на удаление элементов ...
ЗафиксироватьТранзакцию();

Заключение

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

← На главную