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

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

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

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

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

Главная сложность — удаление строк внутри цикла. Если перебирать таблицу от первой строки к последней и удалять элементы «на ходу», индексы смещаются, и часть строк пропускается. Это самая частая ошибка начинающих разработчиков, и ниже разобраны безопасные приёмы, которые её исключают.

Все примеры приведены для встроенного языка 1С (1С:Предприятие 8.x) и работают как на сервере, так и на клиенте, если таблица значений доступна в данном контексте.

Основные методы удаления строк

У объекта ТаблицаЗначений есть три базовых подхода к удалению данных. Метод Удалить() удаляет конкретную строку — либо по ссылке на объект строки, либо по её индексу. Метод Очистить() удаляет все строки, сохраняя структуру колонок. Отдельно стоит приём с НайтиСтроки(), который возвращает массив строк по отбору, после чего их можно удалить в простом цикле.

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

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

Удалить(Строка)

Подходит, когда есть ссылка на строку — например, из Найти() или НайтиСтроки(). Не зависит от индексов.

Удалить(Индекс)

Подходит, когда известна позиция строки. Требует контроля границ, иначе ошибка обращения к индексу.

Очистить()

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

Цикл с конца таблицы

Подходит для удаления по сложному условию, которое нельзя задать через НайтиСтроки().

Как удалить одну строку

Если строка уже получена — например, через поиск, — удаление выполняется одной командой:

СтрокаТЗ = ТаблицаЗначений.Найти(ИскомоеЗначение, "Номенклатура");

Если СтрокаТЗ <> Неопределено Тогда

ТаблицаЗначений.Удалить(СтрокаТЗ);

КонецЕсли;

Удаление по индексу выглядит так:

Если ТаблицаЗначений.Количество() > 0 Тогда

ТаблицаЗначений.Удалить(0); // удаляем первую строку

КонецЕсли;

Проверка результата Найти() на Неопределено обязательна: если значение не найдено, метод вернёт Неопределено, и попытка удалить его приведёт к ошибке. Аналогично при работе с индексом — убедитесь, что таблица не пуста и индекс не выходит за границы.

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

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

Отбор = Новый Структура("Склад", СкладДляУдаления);

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

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

ТаблицаЗначений.Удалить(СтрокаТЗ);

КонецЦикла;

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

Удаление в цикле без пропуска строк

Почему прямой цикл пропускает строки

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

Цикл от конца к началу

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

Для Индекс = -ТаблицаЗначений.Количество() + 1 По 0 Цикл

РеальныйИндекс = -Индекс;

СтрокаТЗ = ТаблицаЗначений[РеальныйИндекс];

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

ТаблицаЗначений.Удалить(РеальныйИндекс);

КонецЕсли;

КонецЦикла;

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

Сбор строк в отдельный массив

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

СтрокиКУдалению = Новый Массив;

Для Каждого СтрокаТЗ Из ТаблицаЗначений Цикл

Если СтрокаТЗ.Сумма < 0 Тогда

СтрокиКУдалению.Добавить(СтрокаТЗ);

КонецЕсли;

КонецЦикла;

Для Каждого СтрокаТЗ Из СтрокиКУдалению Цикл

ТаблицаЗначений.Удалить(СтрокаТЗ);

КонецЦикла;

Типичные ошибки
01
Удаление строк в прямом цикле — индексы смещаются, часть строк пропускается и остаётся в таблице
02
Удаление по индексу без проверки количества строк — ошибка обращения за границы таблицы
03
Удаление результата Найти() без проверки на Неопределено — падение кода, если значение не найдено
04
Попытка задать в НайтиСтроки() условие «больше» или «содержит» — метод поддерживает только равенство, условие молча не сработает как ожидалось

Полная очистка таблицы

Для удаления всех строк используется метод Очистить():

ТаблицаЗначений.Очистить();

Метод удаляет только строки; колонки, их типы и индексы сохраняются. Это важно, если таблица дальше снова заполняется — структуру пересоздавать не нужно. Если требуется удалить и колонки, используется ТаблицаЗначений.Колонки.Очистить() или таблица создаётся заново.

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

Особенности для таблиц на форме и в запросах

На управляемой форме табличные данные часто хранятся как реквизит типа ДанныеФормыКоллекция. У такого объекта тоже есть методы Удалить() и Очистить(), и приёмы с обратным циклом работают аналогично. Однако метод НайтиСтроки() у ДанныеФормыКоллекция отсутствует — вместо него используется перебор или предварительная выгрузка через Выгрузить() в таблицу значений.

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

Маршрут решения

Как выбрать способ

Условие — простое равенство одного или нескольких полейИспользуйте НайтиСтроки() и удаляйте найденные строки в цикле
Условие сложное: сравнения, вычисления, несколько альтернативПеребирайте таблицу циклом от конца к началу и удаляйте по индексу
Нужно удалить всёВызовите Очистить() — структура колонок сохранится
Данные ещё можно отфильтровать на этапе полученияДобавьте условие в запрос и не выгружайте лишние строки вовсе

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

После удаления полезно убедиться, что таблица пришла в ожидаемое состояние. Минимальная проверка — сравнить количество строк до и после операции. Для отладки удобно вывести количество в сообщение или журнал:

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

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

Сообщить("Удалено строк: " + (БылоСтрок - ТаблицаЗначений.Количество()));

Дополнительно стоит повторно выполнить НайтиСтроки() с тем же отбором: если удаление прошло корректно, массив должен быть пустым. Это простой способ поймать ошибку пропуска строк ещё на этапе разработки, а не в рабочей базе.

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

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

Повторный НайтиСтроки() с тем же отбором
Норма

Возвращает пустой массив

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

Строки снова находятся — удаление пропустило часть данных

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

Разница равна числу строк, подлежащих удалению

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

Удалено меньше или больше ожидаемого

Поведение на пустой таблице
Норма

Код отрабатывает без ошибок, ничего не удаляется

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

Ошибка обращения по индексу или Неопределено

Часто задаваемые вопросы

Можно ли удалить строку таблицы значений по значению, а не по индексу?

Да, но не напрямую. Сначала строку нужно найти методом Найти() или НайтиСтроки(), а затем передать полученный объект строки в метод Удалить(). Передать само значение в Удалить() нельзя — метод принимает строку таблицы или её индекс.

Почему после удаления в цикле в таблице остаются строки, которые должны были удалиться?

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

Чем Очистить() отличается от присвоения таблице значения Неопределено?

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

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

Штатного метода «удалить дубли» нет. Типовой приём — свернуть таблицу методом Свернуть() с указанием колонок группировки и суммируемых колонок, либо перебрать таблицу, запоминая комбинации ключевых полей в соответствии, и удалять повторные строки в обратном цикле.

Работает ли НайтиСтроки() для реквизита формы с табличными данными?

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

Можно ли отменить удаление строк из таблицы значений?

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

Итог

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

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