Как правильно подменить стандартную форму объектом из расширения в 1С

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

При разработке расширений конфигурации часто возникает задача переопределить стандартную форму объекта (справочника, документа или отчета) либо открывать специальную форму в зависимости от прав и роли текущего пользователя. Попытки реализовать такую подмену по аналогии с обычными формами через перехват событий ПриОткрытии или ПередОткрытием часто приводят к ошибкам выполнения и некорректному изменению интерфейса.

Рассмотрим детально, почему ошибочен подход с открытием формы из события ПриОткрытии, а также проанализируем штатные механизмы платформы 1С:Предприятие 8.3 для динамической подмены форм.

Типичные ошибки при попытке подмены формы в расширении

Проанализируем распространенную ошибку, с которой сталкиваются разработчики при попытке подменить форму через расширение:


&НаСервере
Процедура Расш1_ПриОткрытииПередНаСервере()
    СтандартнаяОбработка = Ложь;
    Документы.ПриходнаяНакладная.ПолучитьФорму("Расш1_ФормаЗапрет").Открыть();
    Сообщить("123");
КонецПроцедуры

&НаКлиенте
Процедура Расш1_ПриОткрытииПеред(Отказ)
    Расш1_ПриОткрытииПередНаСервере();
КонецПроцедуры

В приведенном коде допущено сразу несколько критических ошибок платформенного характера:

  1. Вызов клиентских методов на сервере: Метод формы Открыть() доступен исключительно на клиенте. Вызов этого метода в контексте &НаСервере вызывает фатальную ошибку.
  2. Неверный синтаксис обращения к форме: Метод ПолучитьФорму() в управляемом приложении требует указания полного пути к форме метаданных (например, "Документ.ПриходнаяНакладная.Форма.Расш1_ФормаЗапрет"). Указание только короткого имени вызывает ошибку "Неверный параметр 1".
  3. Путаница в параметрах событий: В клиентском обработчике ПриОткрытии параметра СтандартнаяОбработка не существует — там доступен только параметр Отказ.
  4. Нарушение логики работы интерфейса: Если перехватывать открытие через обработчик &Перед("ПриОткрытии"), сначала начнет инициализироваться и создаваться стандартная форма, и лишь затем отработает код расширения. Это приводит к лишним вызовам сервера, визуальному мерцанию окон и некорректной работе платформы.

Способ 1. Динамическая подмена через обработчик "ОбработкаПолученияФормы" (Рекомендуемый)

Основным и наиболее корректным механизмом платформы для переопределения открываемой формы является обработка события ОбработкаПолученияФормы в модуле менеджера объекта. Этот обработчик срабатывает до того, как платформа начнет создавать и отрисовывать форму в интерфейсе.

Разберем по шагам, как настроить этот механизм в расширении:

  1. Найдите нужный объект (например, документ ПриходнаяНакладная) и заимствуйте его Модуль менеджера в расширение.
  2. В модуле менеджера расширения добавьте аннотированную процедуру ОбработкаПолученияФормы.
  3. Проверьте необходимые условия (роли пользователя, параметры объекта) и укажите альтернативную форму в параметре ВыбраннаяФорма.

Рассмотрим пример кода в модуле менеджера расширения:


&Вместо("ОбработкаПолученияФормы")
Процедура Расш1_ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
    
    // Проверяем, открывается ли форма объекта
    Если ВидФормы = "ФормаОбъекта" Тогда
        
        // Проверяем условие (например, ограничение прав пользователя)
        Если НЕ РольДоступна("ПолныеПрава") Тогда
            
            // Указываем полный путь к форме, созданной в расширении
            ВыбраннаяФорма = "Документ.ПриходнаяНакладная.Форма.Расш1_ФормаЗапрет";
            СтандартнаяОбработка = Ложь;
            Возврат;
            
        КонецЕсли;
        
    КонецЕсли;

    // Для остальных случаев вызываем стандартную логику
    ВызватьИсключениеЗащищенныйКод(); // Или ВызовСтандартнойОбработки в зависимости от аннотации
КонецПроцедуры

При таком подходе платформа сразу получит нужную форму и не будет тратить ресурсы на создание стандартного окна.

Способ 2. Статическая подмена формы через свойства метаданных

Если альтернативная форма должна открываться для всех пользователей без дополнительных условий, прописывать код в программах не требуется вовсе.

Разберем порядок действий:

  1. Заимствуйте объект метаданных в расширение.
  2. Создайте в расширении новую форму (например, ФормаЗапрет).
  3. В свойствах заимствованного объекта в расширении найдите поле Основная форма объекта (или Основная форма списка) и выберите в нем созданную форму из расширения.

Платформа автоматическая заменит основную форму объекта на форму из расширения во всех сценариях вызова.

Способ 3. Отмена открытия в форме и вызов "ОткрытьФорму"

Если условия открытия зависят от данных, доступных только в контексте самой формы, и их невозможно определить в модуле менеджера, используйте отмену создания формы на сервере и последующий вызов глобального метода ОткрытьФорму() на клиенте.

Посмотрим на пример реализации:


&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    Если НЕ ОтветственныйЗаЗаполнение(Параметры.Ключ) Тогда
        // Отменяем создание текущей формы на сервере
        Отказ = Истина;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
&После("ПриОткрытии")
Процедура Расш1_ПриОткрытииПосле(Отказ)
    Если Отказ Тогда
        // Открываем нужную форму на клиенте с помощью глобального метода
        ОткрытьФорму("Документ.ПриходнаяНакладная.Форма.Расш1_ФормаЗапрет");
    КонецЕсли;
КонецПроцедуры

Выясним преимущества такого подхода: форма-источник отменяет свое создание еще на сервере через параметр Отказ = Истина, а клиентский метод ОткрытьФорму() безопасно вызывается в соответствующем клиентском контексте.

← На главную