Работа с деревьями значений на управляемых формах в 1С часто преподносит сюрпризы, особенно когда дело доходит до программного удаления элементов. Разберем ситуацию, когда привычный цикл для удаления строк из коллекции приводит к ошибке Недопустимое значение параметра.
В платформе 1С:Предприятие при работе с объектами ДанныеФормыКоллекцияЭлементовДерева ссылки на строки в памяти могут «устаревать» или становиться невалидными. Когда мы пытаемся удалить строку, используя сохраненную ранее переменную (объект строки), платформа проверяет её наличие в коллекции. Если за это время структура дерева изменилась, или мы пытаемся удалить дочерний элемент, не обращаясь к его непосредственному родителю, возникает конфликт.
Частые причины сбоя:
Чтобы избежать ошибок, связанных с неактуальными ссылками, рекомендуем использовать метод ПолучитьИдентификатор(). Этот подход гарантирует, что мы всегда работаем с «живой» строкой, найденной в текущем контексте формы прямо перед операцией удаления.
Рассмотрим пошаговую реализацию:
// Сбор идентификаторов строк
МассивУдаляемых = Новый Массив;
Для Каждого стрКоллекции Из КоллекцияСтрок Цикл
МассивУдаляемых.Добавить(стрКоллекции.ПолучитьИдентификатор());
КонецЦикла;
// Безопасное удаление строк
Для Каждого ИдентификаторСтроки Из МассивУдаляемых Цикл
ТекущаяСтрока = ДеталировкаФорма.НайтиПоИдентификатору(ИдентификаторСтроки);
Если ТекущаяСтрока = Неопределено Тогда
Продолжить; // Строка уже удалена (возможно, как часть родительской ветки)
КонецЕсли;
СтрокаРодитель = ТекущаяСтрока.ПолучитьРодителя();
Если СтрокаРодитель = Неопределено Тогда
// Удаление корневой строки
ДеталировкаФорма.ПолучитьЭлементы().Удалить(ТекущаяСтрока);
Иначе
// Удаление дочерней строки из коллекции родителя
СтрокаРодитель.ПолучитьЭлементы().Удалить(ТекущаяСтрока);
КонецЕсли;
КонецЦикла;
Если структура вашего дерева линейна или вы уверены в отсутствии каскадных зависимостей, можно воспользоваться классическим методом обхода коллекции с конца. Это избавляет от проблем со смещением индексов при удалении элементов.
КоллекцияСтрок = СтрокаМатериал.ПолучитьЭлементы();
КоличествоСтрок = КоллекцияСтрок.Количество();
// Обход от последнего элемента к первому
Для Индекс = 1 По КоличествоСтрок Цикл
ОбратныйИндекс = КоличествоСтрок - Индекс;
КоллекцияСтрок.Удалить(ОбратныйИндекс);
КонецЦикла;
Важное примечание: Всегда проверяйте, не удаляете ли вы «родителя» и «потомка» одновременно. Если вы удаляете родительскую строку, все вложенные в неё элементы удаляются автоматически. Попытка повторного удаления дочернего элемента из «уже несуществующего» родителя также вызовет ошибку. Метод с использованием НайтиПоИдентификатору в сочетании с проверкой на Неопределено является наиболее надежным способом избежать подобных исключений.
Применяя эти методы, вы обеспечите стабильную работу алгоритмов обработки данных формы и избавитесь от назойливых ошибок контекста.