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

Программист 1С v7.7
← На главную

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

Проблема "сдвига" индексов при удалении

Прежде чем перейти к коду, давайте проанализируем ситуацию. Представьте, что мы обходим таблицу с первой строки по последнюю. Как только мы вызываем метод УдалитьСтроку(), все последующие строки поднимаются на одну позицию вверх. Строка, которая была третьей, становится второй. Однако счетчик цикла в следующей итерации переходит к третьему индексу, и бывшая третья (а ныне вторая) строка оказывается необработанной. Именно поэтому при простом переборе "сверху вниз" часть строк, подлежащих удалению, остается в таблице.

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

Способ 1: Обход таблицы с конца (Рекомендуемый)

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


НомСтроки = КоличествоСтрок();
Пока НомСтроки > 0 Цикл
    ПолучитьСтрокуПоНомеру(НомСтроки);
    // Проверяем условие, например, цена меньше 100
    Если Цена < 100 Тогда
        УдалитьСтроку(НомСтроки);
    КонецЕсли;
    НомСтроки = НомСтроки - 1;
КонецЦикла;

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

Способ 2: Использование вспомогательной Таблицы Значений (ТЗ)

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

  1. Выгружаем табличную часть в объект ТаблицаЗначений.
  2. Очищаем табличную часть документа.
  3. В цикле по ТЗ переносим только те строки, которые соответствуют условию "оставить".

Пример реализации:


ТЗ = СоздатьОбъект("ТаблицаЗначений");
ВыгрузитьТабличнуюЧасть(ТЗ);
УдалитьСтроки(); // Очищаем ТЧ документа полностью

ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    // Условие: оставляем только товар с ценой >= 100
    Если ТЗ.Цена >= 100 Тогда
        НоваяСтрока();
        Товар = ТЗ.Товар;
        Количество = ТЗ.Количество;
        Цена = ТЗ.Цена;
        Сумма = ТЗ.Сумма;
        // Переносим все необходимые реквизиты
    КонецЕсли;
КонецЦикла;

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

Способ 3: Прямой обход с корректировкой счетчика

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

Посмотрим на пример:


Ном = 1;
Пока Ном <= КоличествоСтрок() Цикл
    ПолучитьСтрокуПоНомеру(Ном);
    Если Цена < 100 Тогда
        УдалитьСтроку(Ном);
        // Индекс не увеличиваем, так как следующая строка "прыгнула" на текущий индекс
    Иначе
        Ном = Ном + 1; // Переходим дальше
    КонецЕсли;
КонецЦикла;

Способ 4: Оптимизация через сортировку (для профи)

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

Алгоритм действий:

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

Технические нюансы и рекомендации

При реализации удаления в форме документа следует учитывать несколько важных аспектов:

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

Визуальное мерцание: Если вы удаляете много строк непосредственно в форме, интерфейс может "моргать". Для ускорения процесса и улучшения визуального восприятия можно использовать внешние компоненты (например, FormEx) для временной блокировки обновления формы, хотя в стандартной поставке 7.7 такой функционал ограничен.

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

Выясним, какой метод выбрать? Для большинства задач в 1С 7.7 Способ №1 (обратный цикл) является оптимальным сочетанием простоты и надежности. Если же логика отбора строк очень сложная или таблица огромная — используйте Способ №2 (через ТЗ).

← На главную