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