Как отловить и обработать нажатие кнопки Delete в формах 1С 8.3

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

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

Разберем причину: почему не работают события формы?

Проанализируем ситуацию, которая часто встречается в конфигурациях на управляемых формах, таких как УНФ, ERP или Бухгалтерия. Когда пользователь находится в динамическом списке и нажимает кнопку Delete, платформа 1С по умолчанию инициирует команду «Установить пометку на удаление». Важно понимать разницу между физическим удалением записи из базы данных и установкой пометки на удаление.

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

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

Решение 1: Использование модуля объекта (универсальный способ)

Рассмотрим наиболее надежный способ, который будет работать независимо от того, как была установлена пометка: нажатием клавиши Delete, через меню «Еще» или программно из другой части кода. Для этого нам понадобится процедура ПередЗаписью в модуле объекта того справочника, с которым мы работаем.

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


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Проверяем, не является ли объект новым
    Если ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;

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

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

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

Решение 2: Подписки на события (для сохранения типовой конфигурации)

Если вы работаете с типовой конфигурацией (например, УНФ) и не хотите снимать объект с поддержки, проанализируем вариант с использованием Подписки на события. Этот механизм позволяет «вклиниться» (поможет расширение для настройки обработчиков событий и управления формами 1С) в процесс записи объекта, не меняя его модуль.

Разберем по шагам создание подписки:

  1. В дереве конфигурации найдем ветку Общие -> Подписки на события.
  2. Создадим новую подписку, назовем ее ОбработатьПометкуУдаленияСправочника.
  3. В поле Источник выберем тип справочника, который нам интересен (или СправочникОбъект для всех справочников сразу).
  4. В поле Событие выберем ПередЗаписью.
  5. В поле Обработчик укажем процедуру в общем модуле. Обратите внимание: общий модуль должен быть серверным.

Пример кода в общем модуле для подписки:


Процедура ПриЗаписиОбъектаДляРегистраПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
    
    // Параметр Источник - это и есть наш объект справочника
    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    Если Источник.ПометкаУдаления <> Источник.Ссылка.ПометкаУдаления Тогда
        // Логика аналогична первому способу
        Если Источник.ПометкаУдаления Тогда
            // Обработка установки пометки
        Иначе
            // Обработка снятия пометки
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Использование свойства ОбменДанными.Загрузка крайне важно. Это гарантирует, что ваш код не будет выполняться при синхронизации данных, а сработает только при интерактивном или программном изменении внутри текущей базы.

Решение 3: Переопределение команды Delete на форме (UI-подход)

Иногда требуется, чтобы логика срабатывала только при нажатии кнопки в конкретном списке, а не при любом изменении объекта. В этом случае мы можем пойти путем перехвата управления в самой форме.

Рассмотрим, как это сделать:

  1. Откроем форму списка справочника в конфигураторе.
  2. Найдем в свойствах таблицы (Динамического списка) стандартную команду УстановитьПометкуУдаления.
  3. В командной панели формы снимем флаг «Автозаполнение».
  4. Создадим свою команду, назовем ее КомандаУдалитьИнтерактивно.
  5. В свойствах нашей команды в поле Сочетание клавиш укажем Del (Delete).
  6. Теперь платформа при нажатии этой клавиши будет вызывать именно наш программный код.

Пример программного кода для такой команды:


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

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

Этот метод более трудозатратен, так как требует ручной обработки стандартного поведения (вопросы пользователю, проверка прав), но он дает 100% контроль над интерфейсом.

Важные нюансы работы с транзакциями

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

Это гарантирует, что в системе не возникнет ситуации «фантомных» записей, когда объект помечен, а запись в регистре не появилась, или наоборот. Если вы хотите жестко запретить удаление при определенных условиях, просто установите Отказ = Истина в процедуре ПередЗаписью, и платформа сама выведет сообщение о невозможности совершения операции — для этого подойдёт конструктор запрета удаления и настройки прав доступа для 1С.

Итоги

Мы рассмотрели три способа перехвата нажатия кнопки Delete. Подведем итоги нашего анализа:

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

← На главную