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