Как перехватить нажатие кнопки Записать в обычной форме 1С и отличить его от программной записи

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

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

Многие начинающие разработчики пытаются найти обработчик конкретной стандартной кнопки ОсновныеДействияФормыСохранить, но сталкиваются с тем, что прямое перехватывание этой системной команды не всегда очевидно. Разберем подробно, как правильно организовать этот процесс, проанализируем поведение системы и рассмотрим несколько надежных способов реализации задачи.

Способ 1. Использование события модуля формы ПередЗаписью

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

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

  1. Если пользователь нажал кнопку «Записать» (синяя дискета) или «ОК» — событие ПередЗаписью в форме сработает.
  2. Если вы программно открыли форму и вызвали ЭтаФорма.Записать() — событие сработает.
  3. Если же вы в какой-то обработке написали ОбъектСправочника.Записать(), то форма в этом процессе вообще не участвует. Следовательно, код из модуля формы не будет выполнен.

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


Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    // Данный код выполнится только при записи ИЗ ДАННОЙ ФОРМЫ
    Предупреждение("Вы нажали кнопку записи на форме!");
    
    // Здесь можно вызвать свою специфическую процедуру
    МояСпециальнаяЛогикаТолькоДляФормы();
КонецПроцедуры

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

Способ 2. Подмена стандартной кнопки на пользовательскую

Бывают случаи, когда логика ПередЗаписью не подходит (например, вам нужно выполнить действие ДО того, как начнутся стандартные проверки платформы на заполненность реквизитов). В этом случае мы можем пойти по пути создания собственной команды.

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

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

Посмотрим на пример реализации такого обработчика:


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

    // 2. Явно вызываем метод записи объекта формы
    ЭтотОбъект.Записать(); 
    
    // В обычных формах ЭтотОбъект внутри модуля формы 
    // указывает на объект, редактируемый в форме.
КонецПроцедуры

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

Способ 3. Передача контекста через ДополнительныеСвойства

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

Для решения этой задачи выясним, как использовать структуру ДополнительныеСвойства. Это «карман», который есть у любого объекта 1С и который живет в течение одной транзакции записи.

В модуле формы пишем:


Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    // Передаем флаг в модуль объекта
    ЭтотОбъект.ДополнительныеСвойства.Вставить("НажатаКнопкаНаФорме", Истина);
КонецПроцедуры

Затем в модуле объекта (например, справочника) мы можем проверить этот флаг:


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

Важные нюансы обычных форм

Рассмотрим несколько технических моментов, которые часто упускают из виду:

Подведем итог: для большинства задач разделения интерактивной и программной записи достаточно использовать событие ПередЗаписью в модуле формы. Если же вам нужен сверхточный контроль над кнопками — используйте ручное заполнение командной панели. Для передачи признака интерактивности «сквозь слои» системы (из формы в модуль объекта) идеально подходит структура ДополнительныеСвойства.

← На главную