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

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

1С: как удалить значение из списка значений

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

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

Ниже разобраны все практические способы: удаление по значению, по индексу, полная очистка, удаление из отборов динамических списков и настроек СКД, а также типичные ошибки, которые приводят к пропуску элементов или падению кода.

Как устроено удаление из списка значений

Тип «СписокЗначений» не имеет метода «УдалитьПоЗначению». Метод Удалить() принимает либо сам элемент списка (объект типа ЭлементСпискаЗначений), либо его числовой индекс. Поэтому стандартная схема удаления по значению — двухшаговая: сначала поиск, потом удаление.

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

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

Удаление элемента по значению

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

Элемент = Список.НайтиПоЗначению(ИскомоеЗначение);

Если Элемент <> Неопределено Тогда

Список.Удалить(Элемент);

КонецЕсли;

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

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

Удаление по индексу и полная очистка

Если позиция элемента известна, удалите его напрямую по индексу:

Если Список.Количество() > 0 Тогда

Список.Удалить(0); // удалить первый элемент

КонецЕсли;

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

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

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

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

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

Для Инд = 1 - Список.Количество() По 0 Цикл

Элемент = Список[-Инд];

Если НужноУдалить(Элемент.Значение) Тогда

Список.Удалить(-Инд);

КонецЕсли;

КонецЦикла;

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

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

Для Каждого Элемент Из Список Цикл

Если НужноУдалить(Элемент.Значение) Тогда

КУдалению.Добавить(Элемент);

КонецЕсли;

КонецЦикла;

Для Каждого Элемент Из КУдалению Цикл

Список.Удалить(Элемент);

КонецЦикла;

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

Удаление значений в управляемых формах и отборах

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

Для удаления значений из отбора динамического списка или настроек СКД работа идёт не со списком значений напрямую, а с коллекцией элементов отбора. Элемент отбора удаляется через Элементы.Удалить(ЭлементОтбора) у коллекции отбора. Если нужно убрать одно значение из отбора «В списке», получите текущий список из ПравоеЗначение, удалите из него элемент описанными выше методами и присвойте обратно.

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

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

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

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

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

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

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

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

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

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

Не изменилось — удаление не сработало или список другой

Повторный поиск значения
Норма

НайтиПоЗначению() возвращает Неопределено

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

Значение найдено — удалено не то вхождение или есть дубли

Сохранённые настройки
Норма

После перезаписи настройки список без удалённых значений

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

После перезапуска значения вернулись — изменения не записаны

Итог

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

Удаление из списка значений выполняется методом Удалить() по элементу или индексу; по значению — через НайтиПоЗначению() с обязательной проверкой на Неопределено. Для нескольких элементов перебирайте список с конца или собирайте кандидатов в массив. Полная очистка — методом Очистить(). После удаления проверяйте количество и повторным поиском, а изменения в хранимых настройках сохраняйте явно.

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

Как удалить все дубли одного значения из списка?

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

Почему при удалении в цикле «Для Каждого» остаются элементы?

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

Как удалить элемент, если известно только представление, а не значение?

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

Чем Очистить() отличается от присвоения нового пустого списка?

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

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

Параметр типа СписокЗначений передаётся в запрос целиком. Извлеките его в переменную, удалите нужные элементы стандартными методами и установите параметр заново через УстановитьПараметр() до выполнения запроса.

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

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