Разработка и Конфигурация · 11 мин
Как удалить строки из таблицы значений в 1С
Как удалить строки из таблицы значений в 1С: методы Удалить, Очистить, НайтиСтроки, удаление по условию в цикле. Примеры кода, ошибки и проверка результата.
Таблица значений в 1С — универсальная структура для промежуточного хранения и обработки данных: в неё выгружают результаты запросов, собирают данные перед печатью, передают между процедурами. Практически всегда после наполнения таблицы возникает задача убрать лишние строки — пустые, не подходящие по условию или дублирующиеся.
Встроенный язык 1С предлагает несколько способов удаления: метод Удалить() для конкретной строки, Очистить() для полного удаления всех строк и комбинацию НайтиСтроки() с циклом для выборочного удаления по условию. У каждого подхода есть свои ограничения и типичные ловушки, главная из которых — удаление строк внутри цикла перебора той же таблицы.
Ниже разобраны рабочие варианты кода для управляемых и обычных форм, способы удаления по условию, удаления дублей и пустых строк, а также контрольные точки для проверки результата.
Основные методы удаления строк
Объект «ТаблицаЗначений» имеет три базовых механизма удаления. Метод Удалить() принимает либо саму строку (объект типа «СтрокаТаблицыЗначений»), либо её индекс — целое число от нуля. Метод Очистить() удаляет все строки, оставляя структуру колонок нетронутой. Третий вариант — получить строку через Найти() или набор строк через НайтиСтроки() и удалить их по одной.
// Удаление по индексу (индексация с нуля)
ТаблицаТоваров.Удалить(0); // удалит первую строку
// Удаление конкретной строки
СтрокаТаблицы = ТаблицаТоваров[2];
ТаблицаТоваров.Удалить(СтрокаТаблицы);
// Полная очистка таблицы
ТаблицаТоваров.Очистить();
Важно понимать разницу: Очистить() сохраняет колонки и их типы, поэтому таблицу можно сразу заполнять заново. Если нужно удалить и структуру колонок, придётся работать с коллекцией Колонки отдельно — метод Очистить() этого не делает.
Удаление строк по условию через НайтиСтроки
Самый безопасный и читаемый способ удалить строки, подходящие под условие, — сначала собрать их в массив методом НайтиСтроки(), а затем пройти по массиву и удалить каждую строку. Метод принимает структуру, где ключ — имя колонки, а значение — искомое значение. Поиск работает на точное совпадение, без подобия и без учёта сложных условий.
Отбор = Новый Структура;
Отбор.Вставить("Количество", 0);
НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);
Для Каждого СтрокаТаблицы Из НайденныеСтроки Цикл
ТаблицаТоваров.Удалить(СтрокаТаблицы);
КонецЦикла;
Такой подход корректен, потому что перебирается отдельный массив, а не сама таблица: сдвиг индексов при удалении никак не влияет на цикл. Условий в структуре отбора может быть несколько — тогда строка должна удовлетворять всем условиям одновременно (логическое «И»).
Ограничение метода: сравнение идёт на строгое равенство. Условия вида «больше», «меньше», «содержит подстроку» через НайтиСтроки() не выразить — для них нужен перебор или запрос.
- 1Сформируйте структуру отбора: имя колонки и искомое значение
- 2Вызовите НайтиСтроки(Отбор) и получите массив строк
- 3Пройдите по массиву циклом и удалите каждую строку методом Удалить()
- 4Проверьте Количество() таблицы до и после — разница должна равняться числу найденных строк
Удаление строк в цикле перебора: как не допустить ошибку
Классическая ошибка начинающих разработчиков — удалять строки прямо внутри цикла Для Каждого ... Из Таблица Цикл. При удалении текущей строки коллекция перестраивается, индексы сдвигаются, и следующая итерация обращается уже не к той строке. В результате часть строк пропускается, а итоговое содержимое таблицы отличается от ожидаемого без каких-либо сообщений об ошибке.
Если условие сложное и НайтиСтроки() не подходит, используйте обратный перебор по индексу — от последней строки к первой. При удалении строки сдвигаются только индексы после неё, а ещё не обработанные строки с меньшими индексами остаются на месте.
// Обратный перебор — безопасное удаление в цикле
Для Индекс = 1 - ТаблицаТоваров.Количество() По 0 Цикл
СтрокаТаблицы = ТаблицаТоваров[-Индекс];
Если СтрокаТаблицы.Сумма < 100 Тогда
ТаблицаТоваров.Удалить(СтрокаТаблицы);
КонецЕсли;
КонецЦикла;
Альтернатива — собрать подлежащие удалению строки в отдельный массив внутри обычного цикла, а удалить их после его завершения. Это нагляднее, но требует двух проходов. Для больших таблиц обратный перебор обычно предпочтительнее.
Удаление дублей и пустых строк
Полные дубликаты строк проще всего убрать через промежуточную таблицу: свернуть исходную методом Свернуть() без указания суммируемых колонок — тогда останутся только уникальные комбинации значений. Учтите, что Свернуть() меняет исходную таблицу, поэтому при необходимости сохранить её работайте с копией через Скопировать().
// Удаление полных дублей (таблица изменяется!)
ТаблицаТоваров.Свернуть("Номенклатура, Склад, Цена");
// Удаление строк с пустым значением в колонке
Отбор = Новый Структура("Номенклатура", Справочники.Номенклатура.ПустаяСсылка());
ПустыеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);
Для Каждого СтрокаТаблицы Из ПустыеСтроки Цикл
ТаблицаТоваров.Удалить(СтрокаТаблицы);
КонецЦикла;
Если дубли считаются не по всем колонкам, а по ключевым (например, только по номенклатуре), Свернуть() с перечислением этих колонок оставит по одной строке на ключ, но остальные колонки будут потеряны, если их не указать как суммируемые. Когда нужно оставить первую из дублирующихся строк со всеми данными, используйте перебор с соответствием для контроля встреченных ключей.
Сравнение способов удаления
Подходит для точного равенства по одной или нескольким колонкам. Код простой и безопасный. Не работает с условиями больше/меньше/содержит
Подходит для любых сложных условий и вычислений. Требует аккуратности с синтаксисом обхода
Подходит для удаления полных дублей. Изменяет исходную таблицу и может отбросить ненужные колонки
Подходит для больших объёмов и сложной фильтрации. Требует помещения таблицы во временную таблицу
Удаление строк через запрос для больших таблиц
Когда таблица содержит десятки тысяч строк, а условие отбора сложное, эффективнее поместить таблицу во временную таблицу запроса и получить результат уже без лишних строк. Запрос выполняет фильтрацию на уровне движка, что заметно быстрее построчного перебора в коде.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ Т.Номенклатура, Т.Количество
|ПОМЕСТИТЬ ВТ
|ИЗ &Таблица КАК Т;
|ВЫБРАТЬ * ИЗ ВТ
|ГДЕ ВТ.Количество > 0";
Запрос.УстановитьПараметр("Таблица", ТаблицаТоваров);
ТаблицаТоваров = Запрос.Выполнить().Выгрузить();
Условие в запросе может быть любым: сравнения, ПОДОБНО, соединения с другими таблицами, группировки. Обратная сторона — дополнительный код и необходимость следить за типами колонок: при передаче таблицы в параметр типы определяются по её колонкам, и пустая таблица без типизированных колонок может вызвать ошибку запроса.
Перед серией удалений полезно запомнить исходное количество строк и после операции сравнить его с ожидаемым. Разница, равная числу найденных строк, — простейший способ убедиться, что условие отбора сработало правильно и ничего лишнего не удалено.
Удаление строк табличной части и таблицы на форме
Табличная часть документа или справочника — не таблица значений, но методы удаления у неё аналогичные: Удалить(Строка) и Очистить() работают так же. Для реквизита формы типа «ТаблицаЗначений» в управляемой форме применимы те же приёмы, включая НайтиСтроки() и обратный перебор.
Специфика формы в том, что изменения таблицы сразу видны пользователю. Если удаление выполняется в цикле над большой таблицей на форме, интерфейс может заметно «подтормаживать» из-за перерисовки. В таких случаях обработку лучше вынести на сервер: изменить данные в серверной процедуре и вернуть результат одним вызовом.
Для динамических списков на форме методы Удалить() недоступны — данные там формируются запросом, и «удалить строку» можно только изменив отбор списка или сами данные в базе.
Как проверить результат
Уменьшилось ровно на число строк, подходящих под условие
Количество не изменилось или уменьшилось больше ожидаемого
В таблице нет строк, подходящих под условие удаления — повторный НайтиСтроки возвращает пустой массив
Повторный поиск снова находит строки — значит, часть пропущена из-за удаления в цикле
Колонки и их типы сохранились после Очистить() или Удалить()
Пропали колонки — вероятно, применён Свернуть с неполным списком колонок
Частые вопросы
Как удалить все строки таблицы значений одной командой?
Вызовите метод Очистить(): Таблица.Очистить(). Удалятся все строки, а колонки и их типы останутся, поэтому таблицу можно сразу заполнять заново без пересоздания структуры.
Почему при удалении в цикле пропускаются строки?
При удалении строки индексы всех последующих сдвигаются на единицу, а цикл продолжает со следующего индекса — одна строка оказывается пропущенной. Решение: обратный перебор от конца таблицы к началу или предварительный сбор строк в массив через НайтиСтроки() с удалением после цикла.
Можно ли удалить строки по условию «больше» или «меньше»?
Метод НайтиСтроки() поддерживает только точное равенство. Для условий сравнения используйте обратный перебор с проверкой условия внутри цикла либо запрос с предложением ГДЕ, передав таблицу как параметр во временную таблицу.
Чем отличается удаление строк в табличной части документа от таблицы значений?
Синтаксис практически совпадает: Удалить(Строка) и Очистить() работают одинаково. Отличие в том, что табличная часть хранится в объекте базы данных, и изменения запишутся только при записи объекта. Кроме того, у табличных частей нет метода Свернуть — для группировки нужна выгрузка в таблицу значений.
Как удалить дубли строк, оставив все колонки?
Метод Свернуть() подходит только если нужны перечисленные колонки. Чтобы убрать дубли по ключевым полям и сохранить все данные первой строки, переберите таблицу, запоминая встреченные ключи в соответствии, и удаляйте повторные строки обратным перебором.
Удаляет ли Очистить() колонки таблицы значений?
Нет. Очистить() удаляет только строки. Чтобы удалить колонку, используйте Таблица.Колонки.Удалить(Таблица.Колонки.ИмяКолонки) — это отдельная операция над коллекцией колонок.
Что важно запомнить
Для точечного удаления используйте Удалить(Строка), для полной очистки — Очистить(), для удаления по условию — НайтиСтроки() с последующим циклом по массиву. Никогда не удаляйте строки внутри прямого цикла перебора той же таблицы: используйте обратный перебор или запрос для сложных условий. После операции проверяйте количество строк и повторным поиском убеждайтесь, что условие больше не находит данных.