Как правильно удалить выбранную строку в таблице значений в 1С 8.3?

Программист 1С v8.3 (Управляемые формы)
← На главную

Работа с табличными частями и таблицами значений на управляемых формах 1С часто вызывает трудности у начинающих разработчиков. Одной из самых распространенных задач является удаление строки, выбранной пользователем. Казалось бы, задача тривиальная, но она скрывает в себе несколько подводных камней, связанных с архитектурой платформы 1С 8.3. В этой статье мы подробно разберем, почему возникают ошибки типа "Несоответствие типов" или "Индекс находится за границами массива", и научимся удалять строки правильно.

Разберем причину ошибки: Идентификатор против Индекса

Проанализируем типичную ситуацию. В событии Выбор или при получении текущей строки таблицы на управляемой форме, платформа возвращает нам значение в параметре ВыбраннаяСтрока. Основная ошибка заключается в том, что многие программисты принимают это значение за порядковый номер (индекс) строки в массиве. Это не так.

В управляемом приложении мы работаем не напрямую с объектом ТаблицаЗначений, а с его программной оболочкой — ДанныеФормыКоллекция. В этой коллекции у каждой строки есть свой уникальный внутренний Идентификатор. Он не меняется при сортировке или удалении соседних строк, в отличие от индекса. Если вы попытаетесь обратиться к коллекции по идентификатору как к индексу (например, РеестрКонтрактов[ВыбраннаяСтрока]), и этот идентификатор будет равен 10 при наличии всего 5 строк в таблице, система выдаст ошибку "Индекс находится за границами массива".

Решение №1: Использование метода НайтиПоИдентификатору (Лучший способ)

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


&НаКлиенте
Процедура РеестрКонтрактовВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Получаем объект строки по её уникальному идентификатору
    СтрокаДляУдаления = РеестрКонтрактов.НайтиПоИдентификатору(ВыбраннаяСтрока);
    
    Если СтрокаДляУдаления <> Неопределено Тогда
        // Удаляем строку из коллекции данных формы
        РеестрКонтрактов.Удалить(СтрокаДляУдаления);
    КонецЕсли;

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

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

Решение №2: Удаление текущей строки через элементы формы

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


&НаКлиенте
Процедура УдалитьТекущуюСтроку(Команда)
    
    // Получаем идентификатор текущей выделенной строки
    ИдентификаторТекущейСтроки = Элементы.РеестрКонтрактов.ТекущаяСтрока;
    
    Если ИдентификаторТекущейСтроки <> Неопределено Тогда
        
        // Находим строку и удаляем её
        ОбъектСтроки = РеестрКонтрактов.НайтиПоИдентификатору(ИдентификаторТекущейСтроки);
        РеестрКонтрактов.Удалить(ОбъектСтроки);
        
    КонецЕсли;
    
КонецПроцедуры

Обратите внимание, что использование Элементы.ИмяТаблицы.ТекущаяСтрока возвращает именно идентификатор, который идеально подходит для метода НайтиПоИдентификатору.

Решение №3: Поиск строк по значению (Метод НайтиСтроки)

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


&НаКлиенте
Процедура УдалитьКонтрактПоНомеру(НомерДляПоиска)
    
    // Создаем структуру отбора
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("НомерЗакупки", НомерДляПоиска);
    
    // Метод НайтиСтроки возвращает Массив найденных элементов
    НайденныеСтроки = РеестрКонтрактов.НайтиСтроки(ПараметрыОтбора);
    
    // Удаляем все найденные строки
    Для Каждого Стр Из НайденныеСтроки Цикл
        РеестрКонтрактов.Удалить(Стр);
    КонецЦикла;
    
КонецПроцедуры

Важное замечание: Опасность удаления в цикле

Рассмотрим ситуацию, когда вам нужно удалить строки не через массив НайтиСтроки, а просто перебирая таблицу по индексам. Это классическая "ловушка" для программиста. Если вы удаляете строки в цикле от 0 до N, то после удаления первой же строки индексы всех последующих смещаются. В результате вы либо пропустите строки, либо получите ошибку выхода за границы массива.

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


// Неправильно:
Для Счет = 0 По РеестрКонтрактов.Количество() - 1 Цикл
    // При удалении индексы "поплывут"
КонецЦикла;

// Правильно (обратный цикл):
Колво = РеестрКонтрактов.Количество();
Для Индекс = 1 По Колво Цикл
    ТекущийИндекс = Колво - Индекс; // Идем с конца
    Строка = РеестрКонтрактов[ТекущийИндекс];
    Если Строка.НужноУдалить Тогда
        РеестрКонтрактов.Удалить(ТекущийИндекс);
    КонецЕсли;
КонецЦикла;

Работа с множественным выделением

Если в свойствах вашей таблицы на форме включен режим Выделение - Множественное, пользователь может выделить сразу несколько строк. В этом случае ТекущаяСтрока вернет только одну (активную), а остальные останутся. Чтобы удалить все выделенные, используйте свойство ВыделенныеСтроки:


&НаКлиенте
Процедура УдалитьВыделенные(Команда)
    
    МассивИдентификаторов = Элементы.РеестрКонтрактов.ВыделенныеСтроки;
    
    // Массив идентификаторов лучше обходить аккуратно
    Для Каждого Идентификатор Из МассивИдентификаторов Цикл
        Строка = РеестрКонтрактов.НайтиПоИдентификатору(Идентификатор);
        Если Строка <> Неопределено Тогда
            РеестрКонтрактов.Удалить(Строка);
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Подведем итоги

Для успешной работы с удалением строк в 1С 8.3 (Управляемые формы) запомните следующие правила:

  1. Никогда не путайте Индекс строки и её Идентификатор.
  2. Для поиска объекта строки по значению из события Выбор всегда используйте НайтиПоИдентификатору().
  3. Метод НайтиСтроки() требует на вход Структуру, а возвращает Массив.
  4. При массовом удалении строк в цикле по индексам всегда двигайтесь от последней строки к первой.
  5. Не забывайте про СтандартнаяОбработка = Ложь;, если переопределяете стандартное поведение системы при выборе строки, чтобы не открывалась форма объекта.

Соблюдение этих простых правил сделает ваш код стабильным и избавит от трудноловимых ошибок в рантайме.

← На главную