Очистка табличной части в 1С: вручную и кодом

· 10 мин

Содержание

Чтобы стереть все строки табличной части целиком, в коде достаточно одной строки — Объект.Товары.Очистить();, а в форме документа нужно выделить строки (Ctrl+A) и нажать Delete. Если нужно убрать не всё, а строки по условию, перебор ведут от конца к началу или через метод НайтиСтроки() — иначе часть строк пропустится.

Разберём оба подхода: ручную чистку через интерфейс и программную — методами встроенного языка. Отдельно — как обработать табличную часть сразу у группы документов, почему запросом очистить ТЧ нельзя и что замедляет работу, когда строк десятки тысяч. Речь про 1С 8.3 с интерфейсом «Такси»; имя Товары в примерах — подставьте фактическое имя своей табличной части.

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

Самый простой случай — убрать строки руками в уже открытом документе или элементе справочника.

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

Чтобы очистить таблицу полностью:

  1. Щёлкните любую строку табличной части, чтобы курсор оказался внутри таблицы.
  2. Выделите все строки — Ctrl+A или щелчок по первой строке и Shift + щелчок по последней.
  3. Нажмите Delete (или крестик на панели).
  4. Запишите документ, чтобы изменения сохранились.

Если таблица большая и прокручивать её долго, выделять мышью необязательно: Ctrl+A выделяет все строки сразу, даже те, что не видны на экране.

В командной панели таблицы есть меню Ещё — через него доступны групповые операции над выделенными строками: сортировка, перемещение вверх-вниз, а в части конфигураций — заполнение по образцу. Если крестика удаления на панели не видно, команда удаления строки всё равно работает по клавише Delete.

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

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

Метод Очистить(): как стереть все строки кодом

В встроенном языке у табличной части есть метод Очистить() — он удаляет все строки за один вызов, независимо от их количества.

В модуле объекта (например, в обработчике ПередЗаписью) обращение идёт напрямую к имени табличной части:

ТабличнаяЧасть.Очистить();

В модуле формы главный реквизит называется Объект, поэтому путь длиннее:

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

Тот же метод работает и для таблицы значений, которую вы создали в коде:

ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура");
// ... заполнение ...
ТЗ.Очистить(); // осталась пустая таблица с теми же колонками

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

После очистки в модуле объекта изменения попадут в базу при записи. Если вы правите реквизит на форме, не забудьте про запись документа — сам по себе вызов метода базу не меняет.

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

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

Чаще нужно убрать не всё, а только строки, подходящие под условие: с нулевым количеством, по конкретной номенклатуре, с пустой ценой. Здесь кроется типичная ошибка — удаление внутри цикла Для Каждого.

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

Индекс = Объект.Товары.Количество() - 1;
Пока Индекс >= 0 Цикл
    Если Объект.Товары[Индекс].Количество = 0 Тогда
        Объект.Товары.Удалить(Индекс);
    КонецЕсли;
    Индекс = Индекс - 1;
КонецЦикла;

Метод Удалить() принимает индекс строки (нумерация с нуля) либо саму строку табличной части.

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

Отбор = Новый Структура("Номенклатура", НужнаяНоменклатура);
НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);
Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
    Объект.Товары.Удалить(СтрокаТЧ);
КонецЦикла;

Не меняйте табличную часть в обычном цикле Для Каждого Строка Из Объект.Товары, удаляя Строка внутри него. Часть строк проскочит, а в ряде случаев платформа выдаст ошибку о том, что коллекция изменилась во время обхода.

Условие может читать несколько полей строки. Пример — убрать строки, где и количество, и сумма нулевые:

Индекс = Объект.Товары.Количество() - 1;
Пока Индекс >= 0 Цикл
    Строка = Объект.Товары[Индекс];
    Если Строка.Количество = 0 И Строка.Сумма = 0 Тогда
        Объект.Товары.Удалить(Индекс);
    КонецЕсли;
    Индекс = Индекс - 1;
КонецЦикла;

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

ТЗ = Объект.Товары.Выгрузить();
НужныеСтроки = ТЗ.НайтиСтроки(Новый Структура("Количество", 0));
Для Каждого Строка Из НужныеСтроки Цикл
    ТЗ.Удалить(Строка);
КонецЦикла;
Объект.Товары.Загрузить(ТЗ);

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

Можно ли очистить ТЧ запросом

Короткий ответ — нет. Запрос в 1С только читает данные, изменять или удалять их он не может. В языке запросов нет аналога UPDATE или DELETE из SQL: результат запроса — это выборка, а не команда на изменение базы.

Поэтому «очистка через запрос» на практике означает связку из двух шагов:

  1. Запросом находим, что нужно обработать — список документов, строки по условию, суммы для проверки.
  2. Для каждого найденного объекта получаем его через ПолучитьОбъект() и уже средствами объектной модели вызываем Очистить() или Удалить().

Запрос удобен именно для отбора: он быстро выбирает документы по периоду, организации, статусу проведения. А само изменение табличной части делается кодом над объектом — другого пути платформа не даёт.

Очистка табличной части у группы документов

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

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг
    |ГДЕ Дата МЕЖДУ &Начало И &Конец";
Запрос.УстановитьПараметр("Начало", НачалоПериода);
Запрос.УстановитьПараметр("Конец", КонецПериода);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();
    ДокОбъект.Товары.Очистить();
    ДокОбъект.Записать();
КонецЦикла;

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

Несколько практических моментов:

  • 📌 Если нужно именно очистить ТЧ, а движения оставить нетронутыми, пишите документ в режиме, который не меняет проведение: ДокОбъект.Записать(РежимЗаписиДокумента.Запись) — но помните, что данные документа и его движения тогда разойдутся, пока вы не перепроведёте.
  • 📌 Проверяйте результат записи. При ошибке в одном документе цикл лучше не прерывать целиком: оберните тело в попытку Попытка … Исключение … КонецПопытки и логируйте проблемные ссылки.
  • 📌 Разовую обработку удобно собрать как внешнюю (.epf) — её не нужно встраивать в конфигурацию.

Большие табличные части: что ускоряет работу

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

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

Объект.Товары.Загрузить(НоваяТаблица);

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

Ещё один тормоз на больших ТЧ — лишние действия в обработчиках событий табличной части (ПриИзменении, ПередУдалением). При массовой программной очистке эти обработчики всё равно отрабатывают на каждое изменение. Если логика позволяет, меняйте данные в модуле объекта, где интерактивные обработчики формы не вызываются.

Сравнение подходов для массовой работы:

ЗадачаМедленноБыстро
Очистить всёцикл Удалить() по строкамОчистить()
Заполнить зановоцикл Добавить()собрать ТЗ → Загрузить()
Выгрузить для анализаручной перебор строкВыгрузить() в таблицу значений

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

Файловая и клиент-серверная база: что учесть

Для изменения данных — а очистка ТЧ это именно изменение — монопольный доступ к базе не нужен. Монополия требуется только для обновления структуры конфигурации, загрузки .dt, тестирования и исправления базы. Очищать табличные части можно при работающих пользователях.

Разница между вариантами касается блокировок и одновременной работы:

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

Код очистки в обоих вариантах одинаков — различается только нагрузка на базу при массовых операциях. Отдельных «файловых» методов для работы с табличной частью в языке нет.

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

Частые ошибки при очистке ТЧ

Диагностика: выберите симптом

Перед правкой рабочих данных кодом полезно пройти короткий самоконтроль:

Перед массовой очисткой ТЧ
Выполнено: 0 / 5

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

Чем `Очистить()` отличается от `Удалить()`?
Очистить() стирает сразу все строки табличной части. Удалить() убирает одну строку — по индексу или по ссылке на строку. Для выборочного удаления по условию нужен Удалить() в цикле от конца к началу.
Сохранятся ли колонки после `Очистить()`?
Да. Метод удаляет только строки, структура колонок табличной части (или таблицы значений) остаётся прежней. Таблица становится пустой, но готовой к заполнению.
Как очистить ТЧ в проведённом документе, не трогая проводки?
Запишите документ без перепроведения: Записать(РежимЗаписиДокумента.Запись). Данные документа и движения при этом разойдутся — согласуйте такой шаг с учётной логикой, обычно документ всё же перепроводят.
Можно ли отменить очистку после записи?
Штатных средств нет. До записи помогает закрытие формы без сохранения, после записи — только восстановление из резервной копии. Поэтому массовые обработки запускают с бэкапом.
Почему нельзя очистить табличную часть одним запросом?
Язык запросов 1С работает только на чтение и не изменяет данные. Запросом отбирают объекты, а очищают их уже кодом через ПолучитьОбъект() и Очистить().