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

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

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

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

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

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

Метод Удалить(): синтаксис и два варианта вызова

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

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Номенклатура");

ТЗ.Колонки.Добавить("Количество");

// ... заполнение таблицы ...

// Вариант 1: удаление по объекту строки

СтрокаДляУдаления = ТЗ[0];

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

// Вариант 2: удаление по индексу

ТЗ.Удалить(0); // удалит текущую первую строку

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

Если передать в метод индекс, выходящий за границы коллекции (например, ТЗ.Удалить(10) при трёх строках), платформа выдаст ошибку «Индекс находится за границами массива». Перед удалением по индексу всегда проверяйте, что таблица не пуста и индекс допустим.

Удаление строки, найденной через Найти()

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

СтрокаНайденная = ТЗ.Найти(Справочники.Номенклатура.ПустаяСсылка(), "Номенклатура");

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

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

КонецЕсли;

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

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

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

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

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

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

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

ТЗ.Удалить(Строка);

КонецЦикла;

Этот способ безопасен: массив сформирован заранее, и удаление строк из таблицы не влияет на перебор. Второй подход — обход коллекции с конца, когда удаление не сдвигает ещё не проверенные элементы:

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

Строка = ТЗ[ТЗ.Количество() - 1 - Инд];

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

ТЗ.Удалить(Строка);

КонецЕсли;

КонецЦикла;

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

Полная очистка таблицы и альтернативные подходы

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

ТЗ.Очистить(); // строк нет, колонки и их типы сохраняются

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

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

Сравнение вариантов

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

Точечное удаление одной известной строки. Не подходит для массовой очистки по условию

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

Удаление всех строк по отбору. Простой и безопасный код, но на очень больших таблицах — лишний проход по коллекции

Цикл с конца

Удаление по сложному условию, которое не выразить структурой отбора. Требует аккуратности с индексами

Очистить()

Полное удаление всех строк с сохранением структуры колонок

Фильтрация в запросе / Скопировать()

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

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

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

ОбъектДокумента.Товары.Очистить();

// или удаление конкретной строки:

ОбъектДокумента.Товары.Удалить(СтрокаТЧ);

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

Отдельный случай — строки, помеченные пользователем в управляемой форме. Для удаления выделенных строк обходят массив Элементы.ИмяТаблицы.ВыделенныеСтроки, получают строки по идентификаторам через НайтиПоИдентификатору() и удаляют каждую из реквизита формы.

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

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

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

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

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

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

// Контроль: строк под условие не осталось

Если ТЗ.НайтиСтроки(Новый Структура("Количество", 0)).Количество() > 0 Тогда

Сообщить("Внимание: часть строк не удалена!");

КонецЕсли;

При отладке в конфигураторе удобно остановиться точкой останова сразу после удаления и посмотреть содержимое таблицы через «Вычислить выражение» — ТЗ.Количество() и значения колонок конкретных строк. Это быстрее, чем выводить таблицу целиком в сообщения.

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

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

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

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

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

Не изменилось или уменьшилось больше ожидаемого — проверьте условие отбора

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

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

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

Строки остались — удаление шло в прямом цикле и часть пропущена

Структура таблицы после Очистить()
Норма

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

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

Ошибки при добавлении строк — возможно, таблица пересоздана без колонок

Производительность при работе с большими таблицами

На таблицах в десятки и сотни тысяч строк способ удаления начинает влиять на скорость. Метод НайтиСтроки() выполняет полный проход по коллекции, и если вызывать его многократно в цикле, время обработки растёт квадратично. Для ускорения поиска по конкретной колонке добавьте индекс: ТЗ.Индексы.Добавить("Номенклатура").

Если из большой таблицы нужно оставить лишь небольшую часть строк, эффективнее не удалять лишнее, а скопировать нужное: НоваяТЗ = ТЗ.Скопировать(Отбор). А лучший вариант для данных из запроса — отфильтровать строки ещё на уровне СУБД, добавив условие в текст запроса, чтобы лишние данные вообще не попадали в память.

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

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

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

Вызовите ТЗ.Удалить(ТЗ.Количество() - 1). Предварительно проверьте, что ТЗ.Количество() > 0, иначе получите ошибку выхода индекса за границы коллекции.

Почему при удалении в цикле удаляется не всё?

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

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

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

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

Да, но учтите различие в нумерации: метод НомерСтроки у строки таблицы значений начинается с 1, а индекс для Удалить() — с 0. Поэтому корректный вызов: ТЗ.Удалить(Строка.НомерСтроки - 1).

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

Стандартного метода «удалить дубликаты» нет. Обычно используют ТЗ.Свернуть("Колонка1,Колонка2", "СуммаКолонка") — он группирует строки по указанным измерениям и суммирует числовые колонки. Если суммировать нечего, свёртку вызывают без второго параметра, но тогда останутся только колонки группировки.

Выдаётся ошибка «Значение не является значением объектного типа» при удалении — в чём причина?

Чаще всего в Удалить() передано Неопределено — результат Найти(), который ничего не нашёл. Добавьте проверку Если Строка <> Неопределено Тогда перед удалением. Реже причина в том, что переменная вообще не содержит строку таблицы — проверьте её значение в отладчике.

Итог

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

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