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

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

Как удалить элемент списка в 1С

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

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

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

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

Удаление элемента списка значений в коде

Список значений — универсальная коллекция, часто используемая для выбора и временного хранения данных. Удалить элемент можно двумя способами: по индексу или передав сам элемент. Индексация начинается с нуля, поэтому первый элемент имеет индекс 0, а последний — Список.Количество() - 1.

1c
Список = Новый СписокЗначений;
Список.Добавить("Первый");
Список.Добавить("Второй");
Список.Добавить("Третий");

// Удаление по индексу (удалит "Второй")
Список.Удалить(1);

// Удаление по найденному значению
Найденный = Список.НайтиПоЗначению("Третий");
Если Найденный <> Неопределено Тогда
    Список.Удалить(Найденный);
КонецЕсли;

Перед удалением по индексу полезно проверять, что индекс находится в допустимых границах. Обращение к несуществующему индексу вызовет ошибку выполнения и прервёт обработку. Минимальная защита — сравнение индекса с количеством элементов.

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

Удаление строк таблицы значений и табличной части

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

1c
// Удаление строки табличной части документа
Для каждого СтрокаТовара Из Объект.Товары Цикл
    Если СтрокаТовара.Количество = 0 Тогда
        // Так делать нельзя - см. раздел про удаление в цикле
    КонецЕсли;
КонецЦикла;

// Правильное удаление одной строки по индексу
Если Объект.Товары.Количество() > 0 Тогда
    Объект.Товары.Удалить(0);
КонецЕсли;

Объект.Записать(); // фиксация изменений в базе

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

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

Удаление элементов коллекции в цикле без ошибок

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

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

1c
ВсегоЭлементов = Список.Количество();
Для Сч = 1 По ВсегоЭлементов Цикл
    Индекс = ВсегоЭлементов - Сч; // идём с конца
    Если Список[Индекс].Пометка = Ложь Тогда
        Список.Удалить(Индекс);
    КонецЕсли;
КонецЦикла;
Типичные ошибки
01
Удаление в прямом цикле — часть элементов пропускается или возникает ошибка выхода за границы
02
Использование устаревшего индекса после удаления — номера элементов уже сместились
03
Удаление строки табличной части без последующей записи объекта — изменения теряются
04
Путаница между индексом (с нуля) и номером строки на форме (с единицы)

Удаление элемента справочника или документа в режиме «Предприятие»

Чтобы удалить объект из списка в пользовательском режиме, выделите его и нажмите клавишу Delete или кнопку «Пометить на удаление» в меню «Ещё». Объект не исчезает из базы — он получает пометку удаления и перестаёт участвовать в большинстве операций, но остаётся доступным для просмотра.

Порядок удаления объекта из списка
  1. 1
    Откройте список справочника или документов и выделите нужный элемент
  2. 2
    Нажмите Delete или «Ещё → Пометить на удаление» и подтвердите действие
  3. 3
    Перейдите в «Администрирование → Обслуживание → Удаление помеченных объектов»
  4. 4
    Выберите режим: автоматическое удаление всех помеченных или выборочное
  5. 5
    Запустите удаление и дождитесь проверки ссылочной целостности
  6. 6
    Если объекты не удалены — откройте список мест использования и уберите ссылки

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

Программное удаление объектов базы данных

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

1c
ОбъектЭлемента = СсылкаНаЭлемент.ПолучитьОбъект();
ОбъектЭлемента.УстановитьПометкуУдаления(Истина);

// Непосредственное удаление (только осознанно!)
ОбъектЭлемента.Удалить();

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

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

Маршрут решения

Как выбрать действие

Нужно убрать строку из списка значений или таблицы в кодеИспользуйте Удалить() по индексу или по элементу, в цикле — обход с конца
Нужно удалить элемент справочника из пользовательского спискаПометьте на удаление, затем выполните удаление помеченных объектов
Объект не удаляется из-за ссылок на негоОткройте список мест использования и сначала уберите или замените ссылки
Нужно очистить коллекцию целикомВызовите метод Очистить() вместо перебора элементов
Удаление массовое и выполняется на рабочей базеСделайте резервную копию и выполняйте операцию вне пиковой нагрузки

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

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

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

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

Количество элементов коллекции после удаления
Норма

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

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

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

Состояние объекта после пометки на удаление
Норма

В списке объект отображается с перечёркнутой пиктограммой

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

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

Результат удаления помеченных объектов
Норма

Объект исчез из списка, отчёт об удалении пуст от ошибок

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

Объект остался, выведен список мест использования

Если объект не удаляется физически, почти всегда причина — существующие ссылки на него. Откройте показанный системой список мест использования, удалите или замените ссылки (например, перепроведите документы с другим значением) и повторите удаление.

Итог

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

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

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

Почему при удалении в цикле пропускаются элементы?

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

Чем отличается пометка на удаление от физического удаления?

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

Объект не удаляется: пишет про ссылки на него. Что делать?

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

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

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

Можно ли восстановить удалённый элемент справочника?

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

Индекс элемента и номер строки на форме — это одно и то же?

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