При разработке в среде 1С:Предприятие 8.3 часто возникает задача: выполнить определенное действие или добавить элементы на форму именно в тот момент, когда пользователь нажимает клавишу Delete в списке элементов (например, в справочнике или документе, где может потребоваться программное создание колонок). Казалось бы, задача простая, но начинающие разработчики часто сталкиваются с тем, что привычные события формы, такие как ПередУдалением или ПриЗаписи на уровне формы, просто не срабатывают. В этой статье мы подробно разберем, почему это происходит, и рассмотрим правильные архитектурные подходы к решению этой задачи, включая работу со списками значений — для автоматизации этого процесса есть автоматизированный контроль изменений и истории удалений в 1С.
Проанализируем ситуацию, которая часто встречается в конфигурациях на управляемых формах, таких как УНФ, ERP или Бухгалтерия. Когда пользователь находится в динамическом списке и нажимает кнопку Delete, платформа 1С по умолчанию инициирует команду «Установить пометку на удаление». Важно понимать разницу между физическим удалением записи из базы данных и установкой пометки на удаление.
Удалить(), либо через стандартную обработку «Удаление помеченных объектов». При нажатии Delete в списке физического удаления не происходит, поэтому это событие игнорируется.Выясним причину успеха: для платформы установка пометки на удаление — это прежде всего запись объекта с измененным значением реквизита ПометкаУдаления. Следовательно, нам нужно «ловить» это действие в модуле объекта или через подписки на события — для этого подойдёт контроль и запрет записи документов в 1С без изменения кода.
Рассмотрим наиболее надежный способ, который будет работать независимо от того, как была установлена пометка: нажатием клавиши Delete, через меню «Еще» или программно из другой части кода. Для этого нам понадобится процедура ПередЗаписью в модуле объекта того справочника, с которым мы работаем.
Посмотрим на пример кода, который позволяет определить, что пометка на удаление была изменена именно в текущий момент:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Проверяем, не является ли объект новым
Если ЭтоНовый() Тогда
Возврат;
КонецЕсли;
// Сравниваем текущее состояние объекта с данными, которые уже записаны в базе
// Если в базе пометки нет, а в текущем объекте она появилась - значит, сработал Delete
Если ЭтотОбъект.ПометкаУдаления И Не Ссылка.ПометкаУдаления Тогда
// Здесь пишем логику по добавлению записи в Регистр Сведений
МенеджерЗаписи = РегистрыСведений.ИсторияУдалений.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = Ссылка;
МенеджерЗаписи.ДатаСобытия = ТекущаяДата();
МенеджерЗаписи.Записать();
Сообщить("Объект помечен на удаление, запись в регистр добавлена.");
// Если наоборот: в базе пометка была, а сейчас ее сняли
ИначеЕсли Не ЭтотОбъект.ПометкаУдаления И Ссылка.ПометкаУдаления Тогда
// Логика удаления записи из регистра
НаборЗаписей = РегистрыСведений.ИсторияУдалений.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Объект.Установить(Ссылка);
НаборЗаписей.Записать();
Сообщить("Пометка удаления снята, запись из регистра удалена.");
КонецЕсли;
КонецПроцедуры
В данном примере мы используем обращение к Ссылка.ПометкаУдаления. Это позволяет нам прочитать значение реквизита напрямую из базы данных до того, как новые изменения будут зафиксированы. Сравнение ЭтотОбъект.ПометкаУдаления (новое значение) и Ссылка.ПометкаУдаления (старое значение) — это классический прием в разработке на 1С — его заменяет готовая подсистема детального логирования истории и восстановления удаленных данных 1С.
Если вы работаете с типовой конфигурацией (например, УНФ) и не хотите снимать объект с поддержки, проанализируем вариант с использованием Подписки на события. Этот механизм позволяет «вклиниться» (поможет расширение для настройки обработчиков событий и управления формами 1С) в процесс записи объекта, не меняя его модуль.
Разберем по шагам создание подписки:
ОбработатьПометкуУдаленияСправочника.СправочникОбъект для всех справочников сразу).ПередЗаписью.Пример кода в общем модуле для подписки:
Процедура ПриЗаписиОбъектаДляРегистраПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Параметр Источник - это и есть наш объект справочника
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Источник.ПометкаУдаления <> Источник.Ссылка.ПометкаУдаления Тогда
// Логика аналогична первому способу
Если Источник.ПометкаУдаления Тогда
// Обработка установки пометки
Иначе
// Обработка снятия пометки
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Использование свойства ОбменДанными.Загрузка крайне важно. Это гарантирует, что ваш код не будет выполняться при синхронизации данных, а сработает только при интерактивном или программном изменении внутри текущей базы.
Иногда требуется, чтобы логика срабатывала только при нажатии кнопки в конкретном списке, а не при любом изменении объекта. В этом случае мы можем пойти путем перехвата управления в самой форме.
Рассмотрим, как это сделать:
УстановитьПометкуУдаления.КомандаУдалитьИнтерактивно.Del (Delete).Пример программного кода для такой команды:
&НаКлиенте
Процедура КомандаУдалитьИнтерактивно(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Опишем вопрос пользователю
ТекстВопроса = "Вы уверены, что хотите изменить пометку удаления?";
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВопросаОбУдалении", ЭтотОбъект, ТекущиеДанные.Ссылка);
ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаОбУдалении(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Вызываем серверный метод для изменения пометки и записи в регистр
ВыполнитьИзменениеПометкиНаСервере(ДополнительныеПараметры);
КонецЕсли;
КонецПроцедуры
Этот метод более трудозатратен, так как требует ручной обработки стандартного поведения (вопросы пользователю, проверка прав), но он дает 100% контроль над интерфейсом.
Проанализируем важный аспект: целостность данных. Когда вы пишете код в событии ПередЗаписью, он выполняется внутри транзакции записи. Это означает, что если при записи в ваш Регистр Сведений произойдет ошибка (например, не заполнено обязательное измерение), то транзакция откатится, и пометка на удаление у объекта справочника также не будет установлена.
Это гарантирует, что в системе не возникнет ситуации «фантомных» записей, когда объект помечен, а запись в регистре не появилась, или наоборот. Если вы хотите жестко запретить удаление при определенных условиях, просто установите Отказ = Истина в процедуре ПередЗаписью, и платформа сама выведет сообщение о невозможности совершения операции — для этого подойдёт конструктор запрета удаления и настройки прав доступа для 1С.
Мы рассмотрели три способа перехвата нажатия кнопки Delete. Подведем итоги нашего анализа:
ПередЗаписью).Помните, что правильное понимание жизненного цикла объекта 1С и механизмов работы управляемых форм позволяет создавать надежные и отказоустойчивые решения.