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