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

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

В процессе разработки на платформе 1С:Предприятие 8.3 мы часто сталкиваемся с необходимостью взаимодействия с внешними обработками — для этого пригодится инструментарий разработчика 1С с консолью кода и анализом метаданных. Одна из таких задач — открытие формы внешней обработки, особенно когда у нее отсутствует основная форма, и мы хотим инициировать это открытие непосредственно из ее модуля объекта. Мы подробно рассмотрим, как решить эту проблему, анализируя различные сценарии и предоставляя практические примеры кода, чтобы вы могли уверенно реализовать это в своих решениях 1С.

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

Открытие формы из объекта обработки

Когда внешняя обработка уже загружена в информационную базу как объект (например, получена из справочника "Дополнительные отчеты и обработки" или создана динамически), мы можем получить доступ к ее формам через сам объект. Для этого мы используем метод ПолучитьФорму(), передавая в него строковое имя нужной формы.


// Предположим, что ОбъектОбработки - это уже существующий экземпляр внешней обработки
Перем ОбъектОбработки; 
// ... код по получению или созданию ОбъектОбработки, например:
// ОбъектОбработки = ВнешниеОбработки.Создать("C:\ПутьКФайлу\МояОбработка.epf");
// Или если обработка уже загружена как объект в конфигурации:
// ОбъектОбработки = РеквизитФормыВЗначение("Объект"); // Если код выполняется в модуле формы, связанной с обработкой

// Получаем объект формы по ее имени
Форма = ОбъектОбработки.ПолучитьФорму("ИмяФормы");

// Открываем форму для пользователя
Форма.Открыть();

Здесь "ИмяФормы" — это строковое имя формы, которое вы задали в конфигураторе для конкретной формы вашей внешней обработки (например, "Форма1", "ФормаНастроек" и т.д.). После получения объекта формы с помощью ПолучитьФорму(), мы вызываем метод Открыть() для ее отображения пользователю. Важно отметить, что метод ПолучитьФорму() выполняется на сервере, но возвращает объект формы, который затем должен быть открыт на клиенте.

Открытие формы внешней обработки в управляемом приложении

В современных конфигурациях, основанных на управляемых формах (УФ), которые являются стандартом в 1С v8.3, подход к открытию форм имеет свои особенности. Мы чаще всего используем метод ОткрытьФорму(), который позволяет открыть форму по ее полному имени в метаданных.

  1. Открытие формы по пути к файлу внешней обработки

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

    
    // Предположим, что АдресФайла - это полный путь к файлу внешней обработки (.epf)
    АдресФайла = "C:\МоиОбработки\МояВнешняяОбработка.epf";
    ИмяКонкретнойФормы = "ФормаНастроек"; // Имя формы в конфигураторе
    
    Попытка
        // Получаем объект формы из файла обработки
        Форма = ВнешниеОбработки.ПолучитьФорму(АдресФайла, ИмяКонкретнойФормы);
        // Открываем форму
        Форма.Открыть();
    Исключение
        Сообщить("Не удалось открыть форму внешней обработки из файла. Причина: " + ОписаниеОшибки());
    КонецПопытки;
    

    Метод ВнешниеОбработки.ПолучитьФорму() используется для получения форм внешних отчетов и обработок, которые еще не были загружены как объекты в ИБ. Он позволяет динамически обращаться к обработкам, расположенным на диске.

  2. Открытие формы из другой обработки или объекта конфигурации

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

    
    // Этот код выполняется на клиенте, например, в модуле команды формы
            
    // ИмяВнешнейОбработки - это имя, под которым обработка зарегистрирована в конфигурации
    // или ее идентификатор, если она динамически загружена и мы знаем ее имя.
    ИмяВнешнейОбработки = "МояТестоваяОбработка"; 
    ИмяОткрываемойФормы = "Форма1"; // Имя конкретной формы в обработке
    
    // Открываем форму, указывая ее полный путь
    ОткрытьФорму(
        "ВнешняяОбработка." + ИмяВнешнейОбработки + ".Форма." + ИмяОткрываемойФормы,
        ,,, // Пропускаем параметры, владельца и имя
        РежимОткрытияОкнаФормы.БлокироватьОкноВладельца // Блокируем окно-владелец
    );
    

    Метод ОткрытьФорму() является клиентским и предназначен для непосредственного отображения форм пользователю. Использование РежимОткрытияОкнаФормы.БлокироватьОкноВладельца полезно, когда нам нужно, чтобы пользователь завершил работу с открытой формой, прежде чем продолжить работу с предыдущей.

  3. Особый случай: Открытие формы из МодуляОбъекта через СведенияОВнешнейОбработке

    Исходный вопрос предполагал, что запуск происходит из МодуляОбъекта внешней обработки. Мы должны учитывать, что код в МодулеОбъекта обычно выполняется на сервере, тогда как открытие формы является клиентской операцией. Для корректного инициирования открытия формы из МодуляОбъекта, особенно если это происходит при вызове команды обработки из списка "Дополнительные отчеты и обработки", мы можем использовать механизм, предусмотренный платформой.

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

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

    При использовании ТипКомандыОткрытиеФормы() система ожидает, что будет открыта основная форма обработки. Если основной формы нет, или требуется открыть конкретную, неосновную форму, то, как мы выяснили, более гибким является использование ТипКомандыОбычнаяКоманда(). В этом случае, в обработчике команды (который может быть как на сервере, так и на клиенте) мы уже явно вызываем ОткрытьФорму() или ПолучитьФорму(), управляя процессом открытия формы самостоятельно.

Передача данных между формами внешней обработки

Одной из распространенных проблем при работе с несколькими формами одной и той же внешней обработки, особенно в управляемом приложении, является то, что вторая форма может открываться как новый экземпляр обработки. Это может привести к потере данных, введенных на первой форме, поскольку новый экземпляр не будет иметь доступа к состоянию предыдущего — для управления логикой работы есть модуль настройки контроля доступа и программных обработчиков форм 1С. Для решения этой проблемы мы рекомендуем передавать данные между формами явным образом. Мы можем использовать несколько подходов:

  1. Временное хранилище

    Сохраните необходимые данные с первой формы в

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

    
    // На первой форме, перед открытием второй:
    АдресДанных = ПоместитьВоВременноеХранилище(МоиДанныеДляПередачи, УникальныйИдентификаторФормы);
    ПараметрыОткрытия = Новый Структура("АдресДанных", АдресДанных);
    ОткрытьФорму("ВнешняяОбработка.МояОбработка.Форма.ВтораяФорма", ПараметрыОткрытия);
    
    // На второй форме, в ПриСозданииНаСервере:
    Если Параметры.Свойство("АдресДанных") Тогда
        МоиПолученныеДанные = ПолучитьИзВременногоХранилища(Параметры.АдресДанных);
    КонецЕсли;
    
  2. Параметры открытия формы

    Передавайте необходимые данные непосредственно через параметры при вызове

    
    ОткрытьФорму()
    
    . Вторая форма получит эти параметры в обработчике события
    
    ПриСозданииНаСервере
    
    или
    
    ПриОткрытии
    
    .

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

    При закрытии первой формы используйте механизм оповещений для передачи результатов ее работы второй форме или родительской форме. Это позволяет асинхронно обновлять данные.

    
    // На первой форме, перед закрытием:
    ОповеститьОВыборе(ВыбранныеДанные, "МояКомандаОповещения", ПараметрыФормыВладельца);
    
    // На форме-владельце, в обработчике Оповещение:
    Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник) Экспорт
        Если ИмяСобытия = "МояКомандаОповещения" Тогда
            // Обрабатываем Параметр, содержащий данные от закрывшейся формы
            Сообщить("Получены данные от формы: " + Строка(Параметр));
        КонецЕсли;
    КонецПроцедуры
    
  4. Получение объекта обработки из формы

    Если в форме внешней обработки используется реквизит формы, связанный с самим объектом внешней обработки (например, реквизит с типом "ВнешняяОбработкаОбъект"), вы можете получить сам объект обработки в клиентском коде формы с помощью

    
    РеквизитФормыВЗначение("Объект")
    
    . Затем вы можете вызывать экспортные процедуры или функции этого объекта, что позволяет централизованно управлять данными через единый экземпляр объекта обработки.

    
    // В модуле формы внешней обработки (на клиенте)
    Процедура МояКнопкаНажатие(Команда)
        ОбъектОбработки = РеквизитФормыВЗначение("Объект"); // Получаем объект обработки
        Если ОбъектОбработки <> Неопределено Тогда
            // Вызываем экспортную функцию или процедуру объекта обработки
            // Например, для получения общих данных
            Данные = ОбъектОбработки.ПолучитьОбщиеДанные(); 
            Сообщить("Общие данные: " + Строка(Данные));
        КонецЕсли;
    КонецПроцедуры
    

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

Заключение

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

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

← На главную