К статье
Практический материал

Разработка и Конфигурация · 9 мин

Удаление строк из таблицы значений по условию в 1С

Как в 1С удалить строки из таблицы значений по условию: методы НайтиСтроки, Удалить, обход в обратном порядке, примеры кода и типичные ошибки.

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

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

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

Какие методы используются для удаления строк

Для удаления строк таблица значений предоставляет три базовых метода: Удалить(Строка) — удаляет конкретную строку, Удалить(Индекс) — удаляет по номеру, и Очистить() — удаляет все строки сразу. Условие отбора реализуется отдельно, через поиск или перебор.

Метод НайтиСтроки(ПараметрыОтбора) возвращает массив строк, удовлетворяющих отбору. Отбор задаётся структурой, где ключ — имя колонки, а значение — искомое значение. Поддерживается только сравнение на равенство, поэтому для условий «больше», «не равно», «содержит» нужен ручной перебор.

Удаление через НайтиСтроки — простое условие на равенство

Если нужно удалить строки, где колонка равна конкретному значению, достаточно связки НайтиСтроки + Удалить. Это самый читаемый и безопасный вариант: сначала формируется массив найденных строк, затем они удаляются по ссылке на объект строки, а не по индексу.

Отбор = Новый Структура;

Отбор.Вставить("Статус", "Отменен");

НайденныеСтроки = ТаблицаДанных.НайтиСтроки(Отбор);

Для Каждого Строка Из НайденныеСтроки Цикл

ТаблицаДанных.Удалить(Строка);

КонецЦикла;

Отбор по нескольким колонкам задаётся добавлением элементов в структуру — условия объединяются по «И». Например, можно удалить строки, где одновременно количество равно нулю и склад равен конкретному значению.

Обход таблицы с конца — сложные условия

Когда условие не сводится к равенству — например, «сумма меньше 100», «дата старше текущей», «наименование содержит подстроку» — таблицу перебирают циклом. Удалять строки при прямом обходе нельзя: после удаления индексы сдвигаются, и следующая строка будет пропущена.

Решение — идти от последней строки к первой. Удаление строки с большим индексом не влияет на индексы строк перед ней, поэтому перебор остаётся корректным.

КоличествоСтрок = ТаблицаДанных.Количество();

Для Сч = 1 По КоличествоСтрок Цикл

Индекс = КоличествоСтрок - Сч;

Строка = ТаблицаДанных[Индекс];

Если Строка.Сумма < 100

Или Строка.Количество = 0 Тогда

ТаблицаДанных.Удалить(Индекс);

КонецЕсли;

КонецЦикла;

Порядок действий при ручном переборе
  1. 1
    Сохраните количество строк в переменную до начала цикла
  2. 2
    Организуйте цикл от последнего индекса к нулевому
  3. 3
    Проверьте условие для текущей строки
  4. 4
    Удалите строку методом Удалить(Индекс)
  5. 5
    После цикла проверьте итоговое количество строк

Удаление через запрос — когда данных много

Если таблица получена из запроса или содержит десятки тысяч строк, часто эффективнее не чистить готовую таблицу, а сразу выбрать только нужные данные. Таблицу значений можно поместить во временную таблицу запроса и применить условие ГДЕ.

Запрос = Новый Запрос;

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

Запрос.Текст =

"ВЫБРАТЬ Т.Номенклатура, Т.Количество

|ПОМЕСТИТЬ ВТ ИЗ &Таблица КАК Т;

|ВЫБРАТЬ * ИЗ ВТ КАК ВТ

|ГДЕ ВТ.Количество > 0";

Запрос.УстановитьПараметр("Таблица", ТаблицаДанных);

ТаблицаДанных = Запрос.Выполнить().Выгрузить();

Этот подход также позволяет использовать функции языка запросов: ПОДОБНО для поиска по шаблону, проверку В ИЕРАРХИИ, соединения с другими таблицами. Минус — дополнительные затраты на передачу таблицы в запрос, поэтому для небольших коллекций проще перебор.

Сравнение способов удаления

НайтиСтроки + Удалить

Подходит для отбора на равенство по одной или нескольким колонкам. Простой и безопасный код, но не поддерживает сравнения «больше/меньше».

Обратный перебор

Универсален для любых условий, включая вычисляемые. Требует аккуратности с индексами.

Запрос с временной таблицей

Оправдан на больших таблицах и сложных условиях. Избыточен для пары сотен строк.

Частые ошибки при удалении строк

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

Вторая ошибка — сравнение значений разных типов. Например, колонка «Количество» имеет тип «Число», а в отбор передаётся строка. НайтиСтроки молча вернёт пустой массив, и алгоритм «успешно» ничего не удалит.

Третья типичная ситуация — удаление из таблицы, которая связана с элементом формы (табличное поле, динамический список на форме). Изменения нужно делать через объект данных формы, а не через копию, иначе пользователь не увидит результата.

Типичные ошибки
01
Удаление внутри цикла Для Каждого по той же таблице — пропускаются строки или обход обрывается
02
Прямой перебор по индексу с удалением — после сдвига индексов проверка пропускает соседнюю строку
03
Отбор строковым значением по числовой колонке — НайтиСтроки возвращает пустой массив без ошибки
04
Удаление из копии таблицы, а не из реквизита формы — на экране данные не меняются

Как проверить результат удаления

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

БылоСтрок = ТаблицаДанных.Количество();

// ... удаление ...

СталоСтрок = ТаблицаДанных.Количество();

Сообщить("Удалено строк: " + (БылоСтрок - СталоСтрок));

Для отладки удобно временно заменить удаление на вывод отбираемых строк в сообщение или табличный документ. Убедившись, что условие отбирает именно то, что нужно, верните удаление.

Контрольные точки

Как проверить результат

Количество строк после удаления
Норма

Уменьшилось ровно на число строк, попадавших под условие

Тревожный признак

Не изменилось (условие не сработало) или таблица пуста (условие слишком широкое)

Содержимое оставшихся строк
Норма

Ни одна строка не удовлетворяет условию удаления

Тревожный признак

Часть лишних строк осталась — возможен пропуск из-за прямого перебора

Типы значений в отборе
Норма

Тип значения отбора совпадает с типом колонки

Тревожный признак

Передана строка вместо числа или даты — отбор молча не срабатывает

Альтернатива: не удалять, а формировать заново

В ряде задач проще не удалять строки, а построить новую таблицу только с нужными данными: создать копию структуры методом СкопироватьКолонки() и в цикле добавлять подходящие строки. Такой код легче читать и отлаживать, а исходная таблица остаётся нетронутой для сравнения.

Ещё один вариант — метод Скопировать(Отбор), который вернёт новую таблицу со строками, удовлетворяющими отбору на равенство. Это фактически «удаление наоборот»: вместо исключения плохих строк вы забираете хорошие.

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

Что важно запомнить

Для равенства используйте НайтиСтроки + Удалить, для сложных условий — перебор от последней строки к первой, для больших таблиц — запрос с условием ГДЕ. Никогда не удаляйте строки внутри прямого обхода и проверяйте типы значений в отборе.

Частые вопросы

Почему НайтиСтроки возвращает пустой массив, хотя подходящие строки есть?

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

Можно ли удалить строки по условию «не равно» через НайтиСтроки?

Нет, НайтиСтроки поддерживает только равенство. Для условия «не равно» используйте обратный перебор с проверкой в цикле либо запрос с условием ГДЕ Колонка <> &Значение.

Что быстрее: перебор с удалением или запрос?

На небольших таблицах (сотни — тысячи строк) разница незаметна, и перебор проще. На больших таблицах со сложными условиями запрос обычно выигрывает, так как фильтрация выполняется на стороне СУБД без перебора в коде.

Как удалить дубли строк в таблице значений?

Используйте метод Свернуть() с указанием колонок группировки — он объединит одинаковые строки и, при необходимости, просуммирует числовые колонки. Если суммировать ничего не нужно, укажите только колонки группировки.

Безопасно ли удалять строки из таблицы, отображаемой на форме?

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

Как удалить только первую найденную строку по условию?

Используйте метод Найти(Значение, ИмяКолонки) — он вернёт одну строку или Неопределено. Проверьте результат на Неопределено и удалите найденную строку методом Удалить().