Как правильно удалять строки из табличной части в 1С?

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

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

Почему цикл «Для каждого» не подходит для удаления строк?

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

Рассмотрим рабочие способы, которые позволят избежать этой «ловушки» и корректно очистить табличную часть.

Способ №1: Использование массива строк для удаления

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

Разберем это по шагам:

  1. Создаем пустой массив.
  2. Проходим по табличной части и, если строка удовлетворяет условию, добавляем её в массив.
  3. Проходим по полученному массиву и удаляем каждую строку из исходной таблицы.

// Сбор строк в массив
МассивСтрок = Новый Массив;
Для каждого СтрокаТовары Из Объект.Товары Цикл
    Если СтрокаТовары.Номенклатура <> ВыбраннаяНоменклатура Тогда
        МассивСтрок.Добавить(СтрокаТовары);
    КонецЕсли;
КонецЦикла;

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

Способ №2: Обход табличной части «с конца»

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

Почему это работает? Когда мы удаляем строку с индексом N, индексы элементов, стоящих до нее (от 0 до N-1), остаются неизменными. Это позволяет нам безопасно продолжать проверку оставшихся строк.


КоличествоСтрок = Объект.Товары.Количество();
Для к = 1 По КоличествоСтрок Цикл
    // Берем индекс с конца: из общего количества вычитаем шаг цикла
    ИндексСтроки = КоличествоСтрок - к;
    ТекущаяСтрока = Объект.Товары.Получить(ИндексСтроки);
    
    Если ТекущаяСтрока.Количество = 100 Тогда
        Объект.Товары.Удалить(ТекущаяСтрока);
    КонецЕсли;
КонецЦикла;

Способ №3: Использование временной таблицы значений

Если вам нужно пересобрать табличную часть на основе сложной логики (например, отфильтровать ненужные строки и оставить только определенные), проще всего выгрузить таблицу в ТаблицаЗначений, очистить основной объект и заполнить его заново.


// Выгружаем ТЧ во временную таблицу
ВременнаяТЗ = Объект.Товары.Выгрузить();
Объект.Товары.Очистить();

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

Важные рекомендации

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

← На главную