При работе с платформой 1С:Предприятие часто возникает необходимость тонкой настройки поведения системы, в том числе и процесса открытия форм. Будь то стандартные формы документов, справочников или специально разработанные обработки, мы можем столкнуться с задачей перехватить момент их открытия, чтобы выполнить дополнительные действия, изменить состав данных, перенаправить пользователя на другую форму или вовсе отменить открытие. Давайте вместе разберем, как это можно сделать, используя различные механизмы платформы.
Один из наиболее мощных и часто используемых способов для перехвата открытия стандартных форм объектов — это использование предопределенной процедуры ОбработкаПолученияФормы. Эта процедура находится в модуле менеджера объекта метаданных (например, документа, справочника или отчета).
Мы выясним, что событие ОбработкаПолученияФормы вызывается на сервере, когда клиентское приложение запрашивает у сервера стандартную управляемую форму для объекта. Это происходит, например, при двойном клике на элементе списка или при вызове метода ОткрытьФорму() без явного указания конкретного имени формы, например, ОткрытьФорму("Документ.АвансовыйОтчет.ФормаОбъекта").
В этой процедуре мы можем переопределить форму, которая будет открыта. Для этого нам доступны два ключевых параметра:
ВыбраннаяФорма: В этот параметр мы можем установить строку с полным именем формы, которую хотим открыть вместо стандартной.СтандартнаяОбработка: Если мы установим этот параметр в Ложь, то стандартный механизм получения формы будет отменен, и система попытается открыть форму, указанную в ВыбраннаяФорма.Давайте посмотрим на пример кода:
// В модуле менеджера объекта "Документ.АвансовыйОтчет"
Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, СтандартнаяОбработка)
// Допустим, мы хотим открыть нашу кастомную форму вместо стандартной
Если ВидФормы = "ФормаОбъекта" Тогда
ВыбраннаяФорма = "Документ.АвансовыйОтчет.Формы.МояКастомнаяФормаДокумента"; // Полное имя нашей формы
СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку
КонецЕсли;
КонецПроцедуры
Таким образом, при попытке открыть стандартную форму документа "АвансовыйОтчет", вместо нее будет открыта наша МояКастомнаяФормаДокумента.
Здесь мы должны обратить внимание на очень важный нюанс, о котором часто забывают. Событие ОбработкаПолученияФормы не вызывается, если форма открывается с явным указанием полного имени формы. Например, если в коде где-то используется ОткрытьФорму("Документ.АвансовыйОтчет.Форма.ФормаДокумента"), то наша подписка на событие в модуле менеджера не сработает! Мы не сможем перехватить такое открытие этим способом.
Это означает, что для перехвата таких явно указанных форм могут потребоваться другие подходы, например, использование общих команд для проверки прав или переопределение самих методов, которые вызывают эти формы.
Если мы хотим повлиять на поведение уже конкретной, открываемой формы (программное изменение форм), мы можем использовать ее внутренние события.
Это событие вызывается на сервере в процессе создания формы, еще до того, как форма будет передана клиенту. Оно дает нам возможность:
Отказ в Истина, мы можем предотвратить открытие формы.Давайте посмотрим на пример:
// В модуле формы
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверим какое-либо условие
Если Не РазрешеноОткрытиеФормы() Тогда
Отказ = Истина; // Отменяем открытие формы
Сообщить("У вас нет прав для открытия этой формы!", СтатусСообщения.Важное);
КонецЕсли;
// Также можно изменить что-то в форме
Если Параметры.Свойство("ВидОперации") И Параметры.ВидОперации = "Возврат" Тогда
Элементы.ПолеСумма.ЦветФона = Новый Цвет(255, 200, 200); // Подсветим поле
КонецЕсли;
КонецПроцедуры
Мы видим, что ПриСозданииНаСервере — это идеальное место для серверных проверок и инициализации формы.
Событие ПриОткрытии вызывается на клиенте уже после того, как форма создана на сервере и передана клиенту. Это последнее событие, в котором мы можем отказаться от открытия формы, а также выполнить клиентские действия, например, установить фокус на определенный элемент или показать сообщение пользователю.
Пример использования:
// В модуле формы
Процедура ПриОткрытии(Отказ)
// Можно сделать дополнительную проверку на клиенте
Если Не ПолучитьПраваДоступаКлиент() Тогда
Отказ = Истина;
ПоказатьПредупреждение(,"Недостаточно прав для работы с формой!");
КонецЕсли;
// Или просто установить фокус
Если Не Отказ Тогда
Элементы.МойРеквизит.УстановитьФокус();
КонецЕсли;
КонецПроцедуры
Рассмотрев последовательность, мы понимаем, что ПриСозданииНаСервере происходит первым, а затем ПриОткрытии на клиенте.
Механизм расширений предоставляет гибкие возможности для доработки конфигурации без изменения ее исходного кода, что значительно упрощает процесс обновлений. Мы можем использовать расширения для перехвата открытия форм и модификации их поведения.
В расширении мы можем заимствовать существующую форму или создать совершенно новую. Если мы заимствуем форму, то можем вносить в нее изменения (добавлять элементы, менять свойства, переопределять обработчики). Если мы создаем новую форму, то можем затем использовать ее, например, через описанный выше механизм ОбработкаПолученияФормы.
С помощью расширений мы можем модифицировать существующие обработчики событий форм, такие как ПриСозданииНаСервере или ПриОткрытии. Это делается путем заимствования формы и непосредственного изменения ее кода. Также существуют аннотации &Перед, &После, &Вместо, которые позволяют встраивать наш код до, после или вместо оригинального кода процедур и функций.
Для обработчиков событий форм, как правило, удобнее работать непосредственно в заимствованной форме, меняя код, или добавляя новые процедуры и вызывая их из уже существующих обработчиков.
Пример (в заимствованной форме расширения):
// В модуле заимствованной формы расширения
&Вместо Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Здесь мы полностью заменяем типовой обработчик
Если Параметры.РежимОткрытия = "Специальный" Тогда
// Делаем что-то свое
Сообщить("Открытие формы в специальном режиме!", СтатусСообщения.Информация);
Иначе
// Если оригинальный обработчик был, его можно вызвать, если платформа поддерживает
// Иначе просто полностью переопределяем логику
// Пример вызова оригинальной процедуры (если она доступна в контексте)
// ОригинальныйПриСозданииНаСервере(Отказ, СтандартнаяОбработка);
Сообщить("Выполняем альтернативную логику создания формы на сервере.", СтатусСообщения.Информация);
КонецЕсли;
КонецПроцедуры
// Или использовать &После для добавления своей логики
&После Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Этот код выполнится после типового обработчика
Если Не Отказ Тогда
Сообщить("Форма успешно создана на сервере, добавляем нашу дополнительную логику.", СтатусСообщения.Информация);
КонецЕсли;
КонецПроцедуры
Важно помнить, что обработчики событий в расширении выполняются в безопасном режиме. Также при добавлении новых элементов или реквизитов в заимствованную форму, рекомендуется использовать префиксы, чтобы избежать конфликтов и улучшить читаемость.
В процессе работы с перехватом открытия форм, мы часто сталкиваемся с различными ситуациями и потребностями. Рассмотрим некоторые из них:
Если после внесения изменений в конфигурацию или расширение поведение системы кажется некорректным, обязательно проверьте систему на чистой тестовой базе и очистите кэш 1С. Часто проблемы, связанные с отображением или логикой форм, могут быть вызваны старым кэшем. Очистка кэша — это первое, что мы должны сделать при возникновении необъяснимых ошибок.
Мы должны четко понимать разницу между этими методами. Рекомендуется всегда использовать глобальный метод ОткрытьФорму(). Он гарантирует правильную инициализацию формы на сервере, вызывая обработчик ПриСозданииНаСервере. Использование связки ПолучитьФорму() с последующим Форма.Открыть() может привести к тому, что некоторые серверные этапы инициализации формы будут пропущены или выполнены некорректно, что может вызвать непредсказуемое поведение.
При открытии формы для нового объекта, например, для создания нового документа, последовательность событий немного отличается. Сначала происходит начальное заполнение объекта данными (это событие ОбработкаЗаполнения в модуле объекта), и только потом вызываются ПриСозданииНаСервере и ПриОткрытии формы. Для существующих объектов событие ОбработкаЗаполнения не вызывается.
Мы можем передавать дополнительные параметры в открываемую форму, используя структуру параметров в методе ОткрытьФорму(). Эти параметры будут доступны в событиях ПриСозданииНаСервере и ПриОткрытии через свойство формы Параметры.
Пример вызова:
СтруктураПараметров = Новый Структура("Организация, Дата", ТекущаяОрганизация, ТекущаяДата());
ОткрытьФорму("Документ.РасходнаяНакладная.ФормаОбъекта", СтруктураПараметров);
Пример получения в форме:
// В модуле формы в ПриСозданииНаСервере или ПриОткрытии
Если Параметры.Свойство("Организация") Тогда
Сообщить("Организация, переданная в форму: " + Параметры.Организация);
КонецЕсли;
Как мы уже выяснили, если форма открывается с явным указанием полного имени, ОбработкаПолученияФормы не работает. В таких случаях мы можем рассмотреть следующие подходы:
ОбработкаПолученияФормы, или добавить свою логику перед вызовом.Мы проанализировали различные подходы к перехвату открытия форм в 1С. Выбор конкретного метода зависит от многих факторов: какой тип формы мы хотим перехватить (объектная, произвольная), как она открывается (стандартно или по явному имени), какие действия нам нужно выполнить (отмена, модификация, перенаправление) и есть ли у нас возможность изменять конфигурацию или только расширять ее. Внимательное изучение этих механизмов позволит вам эффективно управлять поведением форм в ваших решениях на платформе 1С.