Как программно удалить строку таблицы в управляемой форме 1С 8.3

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

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

Реализация удаления с вопросом пользователю

Рассмотрим стандартную ситуацию: нам нужно перехватить стандартное удаление или создать свою кнопку, которая перед действием спрашивает пользователя: "Вы уверены?". Поскольку в управляемом приложении (особенно в веб-клиенте) выполнение кода не останавливается на методе Вопрос(), мы должны использовать ОписаниеОповещения и метод ПоказатьВопрос().

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


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

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


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

Почему важен Идентификатор, а не Индекс?

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

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

Удаление строк при перетаскивании (Drag-and-Drop)

Рассмотрим более сложный случай — перемещение строк между таблицами (например, в реализации канбан-доски). Часто при событии ОкончаниеПеретаскивания возникает ошибка "Значение индекса выходит за границы диапазона". Это происходит потому, что программист пытается удалить строку по старому индексу, который стал неактуален после изменения состава коллекции.

Посмотрим на правильный подход к решению этой задачи:


&НаКлиенте
Процедура ТаблицаИсточникОкончаниеПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)
    
    // ТекущаяСтрока здесь — это идентификатор строки, которую мы перетащили
    ИдСтроки = Элемент.ТекущаяСтрока;
    
    // Вызываем вспомогательную процедуру удаления
    УдалитьСтрокуПоИдентификатору("МояТаблица", ИдСтроки);
    
КонецПроцедуры

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

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

Зачастую пользователю нужно удалить не одну строку, а сразу несколько выделенных. В этом случае свойство ТекущаяСтрока вернет только одну строку (последнюю выбранную). Нам же понадобится свойство ВыделенныеСтроки элемента формы.

Проанализируем алгоритм массового удаления:

  1. Получаем массив идентификаторов выделенных строк из Элементы.ИмяТаблицы.ВыделенныеСтроки.
  2. Для каждого идентификатора из этого массива выполняем поиск в коллекции Объект.ТабличнаяЧасть.
  3. Удаляем найденную строку.

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


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

Стандартные механизмы платформы

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

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

Особенности динамических списков

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

Для удаления строки из динамического списка нам необходимо:

  1. Получить ссылку на объект базы данных из текущей строки списка.
  2. Вызвать серверную процедуру для удаления записи из БД.
  3. Обновить динамический список методом Элементы.ИмяСписка.Обновить().

Заключение и полезные советы

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

Рассмотренные нами методы позволяют создавать надежный и отзывчивый интерфейс, который предсказуемо ведет себя в условиях асинхронности управляемых форм 1С.

← На главную