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

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

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

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

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

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

Метод Удалить(): по объекту строки и по индексу

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

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

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

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

КонецЕсли;

Вторая форма принимает индекс строки (нумерация начинается с нуля). Это удобно, когда позиция известна заранее, например нужно удалить первую строку-заголовок после импорта:

// Удалить первую строку

ТаблицаЗначений.Удалить(0);

// Удалить последнюю строку

ТаблицаЗначений.Удалить(ТаблицаЗначений.Количество() - 1);

Перед удалением по индексу всегда проверяйте, что таблица не пуста и индекс находится в допустимых границах. Обращение к несуществующему индексу вызовет ошибку исполнения и прервёт выполнение кода.

Удаление строк по условию

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

Отбор = Новый Структура("Количество", 0);

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

Для Каждого СтрокаТЗ Из МассивСтрок Цикл

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

КонецЦикла;

Метод НайтиСтроки() работает только с равенством значений. Если условие сложнее — например, «сумма меньше нуля» или «дата старше заданной» — используйте обход по индексу в обратном порядке:

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

Индекс = ТаблицаЗначений.Количество() - Сч;

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

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

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

КонецЕсли;

КонецЦикла;

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

Порядок действий при удалении по условию
  1. 1
    Определите условие отбора: равенство значений или сложное выражение
  2. 2
    Для равенства используйте НайтиСтроки() со структурой отбора
  3. 3
    Для сложного условия организуйте цикл по индексам в обратном порядке
  4. 4
    Удаляйте строки методом Удалить() с объектом строки или индексом
  5. 5
    Проверьте результат: Количество() должно уменьшиться на число удалённых строк

Полная очистка таблицы и удаление дублей

Если нужно удалить все строки, но сохранить структуру колонок, используйте метод Очистить():

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

// Колонки остаются, Количество() = 0

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

Для удаления дублей готового метода нет, но типовой приём — свернуть копию таблицы и заменить исходную:

ТаблицаБезДублей = ТаблицаЗначений.Скопировать();

ТаблицаБезДублей.Свернуть("Контрагент, Договор", "Сумма");

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

Удаление строк на клиенте и в форме

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

Для табличного поля, связанного с таблицей значений, текущую строку удаляют через данные формы:

&НаКлиенте

Процедура УдалитьТекущуюСтроку(Команда)

ТекущиеДанные = Элементы.ТаблицаФормы.ТекущиеДанные;

Если ТекущиеДанные = Неопределено Тогда

Возврат;

КонецЕсли;

ТаблицаФормы.Удалить(ТаблицаФормы.Индекс(ТекущиеДанные));

КонецПроцедуры

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

Производительность при удалении большого числа строк

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

Быстрая альтернатива — не удалять, а отобрать нужное. Если удалить требуется большую часть строк, выгоднее скопировать в новую таблицу только те, что должны остаться:

Отбор = Новый Структура("Пометка", Истина);

НоваяТаблица = ТаблицаЗначений.Скопировать(Отбор);

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

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

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

Подходит, когда объект строки уже известен. Простое и безопасное удаление единичных строк.

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

Для удаления по позиции. Требует проверки границ и учёта смещения индексов.

НайтиСтроки + цикл

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

Обратный цикл по индексам

Универсален для любых условий. Немного сложнее в написании.

Скопировать(Отбор)

Быстрее всего, когда удалить нужно большую часть строк, а оставить меньшую.

Типичные ошибки и как их избежать

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

Вторая ошибка — удаление по индексу без проверки Количество(). Если таблица пуста, обращение Удалить(0) вызывает исключение. Третья — использование Найти() без проверки результата на Неопределено: если строка не найдена, передача Неопределено в Удалить() приведёт к ошибке.

Четвёртая — путаница между Очистить() и созданием новой таблицы. Если на исходную таблицу ссылаются другие процедуры или реквизит формы, замена объекта разорвёт эту связь, и изменения «не увидят» в форме.

Типичные ошибки
01
Удаление строк в цикле «Для Каждого» по той же таблице — пропускаются элементы
02
Удалить(0) без проверки Количество() — ошибка исполнения на пустой таблице
03
Передача Неопределено в Удалить() после неудачного Найти() — исключение
04
Замена таблицы новым объектом вместо Очистить() — реквизит формы теряет связь с данными
05
Прямой индексный цикл с удалением — смещение индексов и пропуск строк

Проверка результата

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

В отладчике таблицу значений удобно просматривать через «Вычислить выражение»: укажите имя переменной и раскройте коллекцию. Так видно фактическое содержимое строк и порядок колонок после манипуляций.

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

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

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

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

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

Не изменилось или уменьшилось больше, чем ожидалось

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

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

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

Строки с условием остались — цикл пропускал элементы

Структура колонок
Норма

Колонки и их типы сохранены

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

Таблица заменена новым объектом, связи потеряны

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

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

Напрямую по значению — нет. Сначала найдите строку методом Найти(Значение, "ИмяКолонки") или получите массив через НайтиСтроки(), затем передайте найденный объект в Удалить(). Всегда проверяйте, что поиск вернул строку, а не Неопределено.

Чем отличается Очистить() от присваивания Новый ТаблицаЗначений?

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

Как удалить первые N строк таблицы?

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

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

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

Можно ли отменить удаление строки?

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

Что быстрее: удалить половину строк или скопировать нужные?

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

Итог

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

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