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

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

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

Почему не работают стандартные настройки?

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

Разбор типовой ошибки при реализации подтверждения

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


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

В данном случае строка будет удалена сразу же, как только закроется процедура ПередУдалениемСтрок, поскольку параметр Отказ по умолчанию равен Ложь, а ПоказатьВопрос не останавливает выполнение кода. К моменту, когда пользователь нажмет «Да» или «Нет», строки в таблице уже не будет.

Правильный подход: Отмена и последующее удаление

Для корректной работы нам необходимо применить следующую стратегию:

  1. В процедуре ПередУдалениемСтрок всегда устанавливать Отказ = Истина. Это принудительно останавливает стандартный механизм удаления платформы.
  2. Перед отменой нужно запомнить массив идентификаторов строк, которые пользователь планировал удалить.
  3. Вызвать асинхронный диалог подтверждения.
  4. В процедуре завершения (callback), если пользователь ответил «Да», программно удалить строки из объекта, используя сохраненные идентификаторы.

Реализация обработчика события удаления

Рассмотрим детально код основной процедуры. Здесь мы подготавливаем данные для передачи в процедуру оповещения.


&НаКлиенте
Процедура ТабличнаяЧастьПередУдалениемСтрок(Элемент, Отказ)
    
    // 1. Отменяем стандартное удаление
    Отказ = Истина;
    
    // 2. Проверяем, есть ли выделенные строки
    МассивВыделенныхСтрок = Элемент.ВыделенныеСтроки;
    Если МассивВыделенныхСтрок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // 3. Подготавливаем структуру параметров для процедуры завершения
    // Нам нужно знать, какие строки удалять и из какого элемента формы
    ДопПараметры = Новый Структура;
    ДопПараметры.Вставить("МассивВыделенныхСтрок", МассивВыделенныхСтрок);
    ДопПараметры.Вставить("ИмяТаблицы", Элемент.Имя);
    
    // 4. Описываем оповещение и показываем вопрос
    ТекстВопроса = НСтр("ru='Вы действительно хотите удалить выделенные строки из документа?'");
    ОписаниеОповещения = Новый ОписаниеОповещения("ПередУдалениемСтрокЗавершение", ЭтотОбъект, ДопПараметры);
    ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
    
КонецПроцедуры

Программное удаление по идентификаторам

Теперь выясним важную причину, по которой новички часто сталкиваются с ошибками при удалении. В свойстве Элемент.ВыделенныеСтроки хранятся не индексы (0, 1, 2...), а уникальные идентификаторы строк. Если вы попробуете удалять строки просто по индексу в цикле, то после удаления первой же строки индексы остальных сместятся, и вы либо удалите не те данные, либо получите ошибку «Индекс находится за границами массива».

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


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

Важные нюансы и оптимизация

Разберем несколько тонкостей, которые помогут сделать решение более надежным:

  1. Обновление итогов: После программного удаления строк (через Удалить()) события ПриИзменении табличной части могут не отрабатывать так же, как при интерактивном удалении. Если у вас в документе есть итоги (сумма, количество), после цикла удаления рекомендуется вызвать процедуру их пересчета.
  2. Передача элемента: В структуре ДопПараметры мы передаем имя таблицы. Это позволяет сделать код универсальным, если на форме несколько табличных частей.
  3. Работа с БСП: Если ваша конфигурация использует Библиотеку стандартных подсистем (БСП), вы можете заменить стандартный ПоказатьВопрос на вызов ОбщегоНазначенияКлиент.ПоказатьПодтверждение. Это придаст диалогам стандартный вид, принятый в типовых решениях 1С.

Альтернативный способ: Своя команда удаления

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

В коде такой команды вам не нужно будет использовать Отказ = Истина. Вы просто сначала задаете вопрос, и только при получении ответа «Да» запускаете цикл удаления, описанный выше. Это делает структуру кода более линейной и понятной.

Заключение

Мы рассмотрели основной механизм создания подтверждения при удалении строк. Главный секрет успеха здесь заключается в связке: принудительная отмена стандартного действия + асинхронный вызов вопроса + удаление через НайтиПоИдентификатору. Используя этот шаблон, вы сможете обеспечить надежность работы пользователей и предотвратить случайную порчу документов.

← На главную