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

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

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

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

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

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

Как удалить строку интерактивно, без программирования

Пользователю достаточно встать на нужную строку табличной части и нажать клавишу Delete либо кнопку с крестиком на командной панели таблицы. В управляемых формах доступны также пункт контекстного меню «Удалить» и сочетание Shift+Delete в ряде конфигураций. Для удаления нескольких строк подряд выделите их с зажатой клавишей Shift, для выборочного выделения — с Ctrl, затем нажмите Delete.

Учтите, что удаление происходит только в памяти: изменения зафиксируются после записи документа кнопкой «Записать» или «Провести». Если закрыть форму без записи, платформа спросит о сохранении изменений — при отказе удалённые строки вернутся. В проведённом документе после удаления строк и перепроведения движения по регистрам пересчитаются автоматически.

Удаление одной строки программно: метод Удалить()

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

// Удаление текущей строки на форме документа

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

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

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

КонецЕсли;

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

Если Объект.Товары.Количество() > 0 Тогда

Объект.Товары.Удалить(0);

КонецЕсли;

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

bsl
Объект.Товары.Удалить(Объект.Товары[0]); // удалить первую строку

Полная очистка табличной части: метод Очистить()

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

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

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

Удаление строк по условию: правильный цикл

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

// ТАК ДЕЛАТЬ НЕЛЬЗЯ: часть строк будет пропущена

Для Каждого СтрокаТовара Из Объект.Товары Цикл

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

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

КонецЕсли;

КонецЦикла;

Корректные способы — обратный цикл по индексу либо предварительный сбор строк в массив:

// Способ 1: обратный перебор по индексу

Для Инд = 1 По Объект.Товары.Количество() Цикл

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

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

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

КонецЕсли;

КонецЦикла;

// Способ 2: сначала собрать, потом удалить

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

Для Каждого СтрокаТовара Из Объект.Товары Цикл

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

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

КонецЕсли;

КонецЦикла;

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

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

КонецЦикла;

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

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

Особенности для управляемых форм и клиент-серверного кода

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

Если обработка выполняется во внешней обработке или регламентном задании, работайте с объектом напрямую: получите его через Ссылка.ПолучитьОбъект(), измените табличную часть и вызовите Записать(). Для проведённого документа используйте режим записи РежимЗаписиДокумента.Проведение, чтобы движения обновились сразу.

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

Проверка результата и контрольные точки

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

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

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

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

Равно ожидаемому: исходное минус число удалённых

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

Не изменилось или строк удалено больше, чем планировалось

Движения документа по регистрам
Норма

После перепроведения соответствуют оставшимся строкам

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

Движения содержат удалённые позиции — документ не перепроведён

Итоговые суммы документа
Норма

Пересчитаны по оставшимся строкам

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

Сумма устарела — не отработали пересчёты в обработчиках

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

Итог

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

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

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

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

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

Почему при удалении в цикле «Для Каждого» остаются лишние строки?

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

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

Переберите табличную часть в обратном порядке и проверяйте условие: Если СтрокаТовара.Количество = 0 Тогда Объект.Товары.Удалить(СтрокаТовара); КонецЕсли;. Учитывайте, что пустое числовое значение в 1С равно нулю, поэтому отдельная проверка на «пусто» для чисел обычно не требуется.

Удалил строки программно, но в документе ничего не изменилось. В чём причина?

Скорее всего, объект не был записан. При работе через ПолучитьОбъект() изменения существуют только в памяти до вызова Записать(). Также проверьте, что обработка вообще выполнилась: добавьте вывод количества строк до и после удаления через Сообщить().

Можно ли удалить строки в проведённом документе, не распроводя его?

Можно, если записать объект с режимом РежимЗаписиДокумента.Проведение — документ останется проведённым, а движения пересчитаются по новому составу строк. Запись в режиме ПростаяЗапись оставит старые движения, что приведёт к расхождению данных. Учитывайте также права пользователя и закрытые периоды.

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

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