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

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

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

Как найти строку в табличной части документа 1С и удалить её: методы Найти, НайтиСтроки, Удалить, примеры кода, типовые ошибки и проверка результата.

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

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

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

Как устроена табличная часть и почему это важно перед удалением

Табличная часть документа — это объект типа «ТабличнаяЧасть», доступный через свойство объекта документа, например ДокументОбъект.Товары. Каждая строка — это объект со своим набором реквизитов и уникальным в пределах документа номером строки, который пересчитывается автоматически при удалении и вставке.

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

Ещё одна особенность: удаление строки из табличной части объекта в памяти не затрагивает данные в базе до вызова Записать(). Это даёт возможность безопасно «примерить» изменения: найти строки, оценить результат и отказаться от записи, если что-то пошло не так.

Поиск одной строки методом Найти()

Метод Найти(Значение, ИмяКолонки) ищет первую строку, у которой указанный реквизит равен переданному значению. Если строка не найдена, метод возвращает Неопределено — это обязательно нужно проверять перед удалением, иначе получите ошибку обращения к методу.

Типовой фрагмент кода выглядит так:

СтрокаТовара = ДокументОбъект.Товары.Найти(ИскомаяНоменклатура, "Номенклатура");

Если СтрокаТовара <> Неопределено Тогда

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

КонецЕсли;

Обратите внимание: метод ищет только по одному реквизиту и только на строгое равенство. Если нужен отбор по нескольким полям (например, номенклатура плюс характеристика), используйте НайтиСтроки() с отбором-структурой — он поддерживает несколько условий одновременно.

Поиск нескольких строк методом НайтиСтроки()

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

Отбор = Новый Структура;

Отбор.Вставить("Номенклатура", ИскомаяНоменклатура);

Отбор.Вставить("Отменено", Истина);

НайденныеСтроки = ДокументОбъект.Товары.НайтиСтроки(Отбор);

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

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

КонецЦикла;

Такой подход безопасен: массив сформирован до начала удаления, поэтому изменение коллекции внутри цикла не ломает перебор. Это главное преимущество перед удалением прямо в цикле Для Каждого по самой табличной части.

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

Порядок действий
  1. 1
    Получите объект документа: ДокументОбъект = Ссылка.ПолучитьОбъект()
  2. 2
    Сформируйте отбор и найдите строки методом Найти() или НайтиСтроки()
  3. 3
    Проверьте, что строки найдены (не Неопределено, массив не пуст)
  4. 4
    Удалите строки методом Удалить() в цикле по массиву
  5. 5
    Запишите документ: ДокументОбъект.Записать() внутри транзакции
  6. 6
    Проверьте результат: перечитайте документ и убедитесь, что строки исчезли

Удаление строк в цикле: как не сломать перебор

Самая частая ошибка новичков — удалять строки прямо внутри цикла Для Каждого Строка Из ДокументОбъект.Товары Цикл. При удалении текущего элемента коллекция перестраивается, итератор сбивается, и часть строк пропускается. В результате «лишние» строки остаются, хотя код отработал без ошибок.

Есть три корректных способа. Первый — собрать строки через НайтиСтроки() и удалять по массиву, как показано выше. Второй — обратный цикл по индексу от последней строки к первой:

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

РеальныйИндекс = -Индекс;

СтрокаТовара = ДокументОбъект.Товары[РеальныйИндекс];

Если СтрокаТовара.Отменено Тогда

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

КонецЕсли;

КонецЦикла;

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

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

Запись документа и работа в транзакции

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

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

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

Поиск с нестрогими условиями и особые случаи

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

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

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

Сравнение вариантов

Найти() + Удалить()

Подходит для удаления одной строки по одному реквизиту. Ограничение: только точное равенство и только первое совпадение

НайтиСтроки() + цикл Удалить()

Оптимально для нескольких условий и нескольких строк. Безопасен при переборе, так как массив сформирован до удаления

Обратный цикл по индексу

Подходит для сложных условий, которые не выразить отбором. Требует аккуратности с индексами

Очистить()

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

Как проверить, что удаление прошло корректно

Минимальная проверка — после записи перечитать документ из базы и убедиться, что количество строк уменьшилось на ожидаемое число, а целевых строк в коллекции больше нет. В отладчике это видно сразу по ДокументОбъект.Товары.Количество().

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

В пакетных обработках полезно вести журнал: фиксировать ссылку на документ, количество удалённых строк и результат записи. Это позволит быстро найти документы, где обработка завершилась с ошибкой, и повторить её точечно.

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

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

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

Уменьшилось ровно на число удалённых строк

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

Не изменилось — запись не выполнена или поиск вернул пустой результат

Повторный поиск по тому же отбору
Норма

НайтиСтроки() возвращает пустой массив

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

Строки находятся — удаление не сохранено в базе

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

Регистры отражают новый состав строк

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

Движения старые — требуется перепроведение

Часто задаваемые вопросы

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

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

Почему НайтиСтроки() возвращает пустой массив, хотя строка точно есть?

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

Что будет с номерами оставшихся строк после удаления?

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

Нужно ли перепроводить документ после удаления строк?

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

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

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

Можно ли отменить удаление строк после записи документа?

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

Итог

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

Ищите строки через Найти() или НайтиСтроки() с отбором-структурой, удаляйте методом Удалить() по массиву найденных строк, а не в цикле по коллекции. Завершайте работу записью документа, при массовой обработке используйте транзакцию и резервную копию.