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