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

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

Как программно очистить табличную часть документа в 1С

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

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

Чаще всего задача сводится к одной строке кода: Объект.Товары.Очистить();. Однако на практике возникают нюансы: очистка из формы требует обращения через объект данных формы, при управляемых формах важно учитывать контекст сервера и клиента, а удаление строк в цикле «вперёд» приводит к пропуску элементов. Разберём все рабочие варианты с примерами.

Материал ориентирован на платформу 1С:Предприятие 8.2 и 8.3, но синтаксис работы с табличными частями един и для более ранних версий линейки 8.x. Примеры приведены на встроенном языке и подходят как для управляемых, так и для обычных форм с учётом указанных оговорок.

Метод Очистить() — самый простой способ

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

// В модуле объекта или внешней обработке

ДокОбъект = Документы.РеализацияТоваровУслуг.НайтиПоНомеру(НомерДок, ДатаДок).ПолучитьОбъект();

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

ДокОбъект.Записать();

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

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

Метод не возвращает значения и не вызывает запись документа сам по себе. Если вы получили объект через ПолучитьОбъект() во внешней обработке и не вызвали Записать(), изменения останутся только в памяти и будут потеряны.

Очистка табличной части из формы документа

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

&НаКлиенте

Процедура ОчиститьТовары(Команда)

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

КонецПроцедуры

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

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

Выборочное удаление строк в цикле

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

Обход в обратном порядке

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

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

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

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

КонецЕсли;

КонецЦикла;

Такой подход корректен, потому что удаление «хвостовых» строк не влияет на индексы ещё не обработанных элементов в начале коллекции.

Через массив найденных строк

Более читаемый вариант — сначала собрать строки для удаления, затем удалить их отдельным проходом:

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

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

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

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

КонецЕсли;

КонецЦикла;

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

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

КонецЦикла;

Этот способ удобен, когда условие сложное или когда строки нужно предварительно показать пользователю для подтверждения.

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

Очистка и связанные с ней механизмы

Табличная часть документа редко существует изолированно. Перед программной очисткой оцените, что затронет операция.

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

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

Зависимые табличные части. В типовых конфигурациях очистка одной табличной части (например, «Товары») может требовать синхронной очистки другой (например, «Серии» или «Услуги»), иначе в документе останутся «осиротевшие» строки.

Пакетная очистка во внешней обработке

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| РеализацияТовары.Ссылка КАК Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары

|ГДЕ

| РеализацияТовары.Номенклатура = &Номенклатура

| И РеализацияТовары.Ссылка.Дата МЕЖДУ &Начало И &Конец";

// ... установка параметров и обход выборки

Пока Выборка.Следующий() Цикл

ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();

// выборочное удаление или полная очистка

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

КонецЦикла;

Для больших объёмов полезно выполнять обработку в транзакции с фиксацией порциями, чтобы не блокировать таблицы надолго и не потерять весь результат при сбое на последнем документе.

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

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

Иногда вместо построчного удаления удобнее загрузить в табличную часть пустую таблицу значений методом Загрузить():

ПустаяТЗ = Объект.Товары.Выгрузить();

ПустаяТЗ.Очистить();

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

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

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

Сравнение способов очистки

Очистить()

Полное удаление всех строк одной командой. Самый быстрый и читаемый вариант, но не подходит для выборочного удаления

Удалить() в обратном цикле

Выборочное удаление по условию. Требует аккуратности с индексами, чуть больше кода

Массив строк + Удалить()

Выборочное удаление сложным условием с возможностью предварительного просмотра. Расходует память на массив ссылок на строки

Загрузить(пустая ТЗ)

Замена содержимого целиком. Уместно, когда дальше загружается новый набор строк

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

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

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

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

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

ТабличнаяЧасть.Количество() = 0 после Очистить()

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

Строки остались — возможно, очищалась другая табличная часть или копия данных

Состояние в базе
Норма

После Записать() документ открывается с пустой табличной частью

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

В форме строки есть, в базе нет (или наоборот) — объект не записан

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

После перепроведения движения соответствуют пустой табличной части

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

Старые движения остались — документ не был перепроведён

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

Сумма документа пересчитана и равна нулю

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

Шапка показывает старую сумму — не вызван пересчёт итогов

Программно проверить результат можно сразу после записи, повторно прочитав объект из базы и сравнив количество строк. Это особенно полезно в пакетных обработках — добавьте в цикл контроль и журналирование, чтобы видеть, на каких документах операция завершилась с ошибкой.

Итог

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

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

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

Можно ли очистить табличную часть без получения объекта документа?

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

Почему после Очистить() строки снова появляются при открытии документа?

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

Как очистить табличную часть у проведённого документа?

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

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

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

Как очистить табличную часть в управляемой форме на клиенте?

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

Есть ли разница между Очистить() и Удалить() в цикле по скорости?

Для полного удаления всех строк Очистить() предпочтительнее: это одна атомарная операция над коллекцией. Цикл с Удалить() оправдан только при выборочном удалении, когда проверяется условие для каждой строки.