Как открыть одну управляемую форму внутри другой в 1С 8.3: обходные пути и рабочие решения

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

Разработчики при создании сложных и эргономичных интерфейсов в системе «1С:Предприятие 8.3» часто сталкиваются с задачей размещения одной формы внутри другой. Это может быть необходимо для создания дашбордов, многошаговых мастеров (визардов), сложных рабочих мест или интерактивных панелей управления. Однако стандартная архитектура управляемого приложения накладывает жесткие ограничения на такое поведение интерфейса. Разберем детально, почему возникает эта сложность и как её можно элегантно решить с помощью различных обходных технологий.

Анализ проблемы и ограничений платформы

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

ОткрытьФорму(ИмяФормы, Параметры, Владелец, Уникальность, Окно, ...)

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

Тем не менее, существует несколько проверенных способов решения этой задачи разного уровня сложности. Рассмотрим их по шагам.

Способ 1. Программное создание элементов на основе другой формы (Динамический конструктор)

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

Алгоритм реализации:

  1. Создаем в основной (материнской) форме реквизит, тип которого соответствует типу данных внедряемого объекта (например, СправочникОбъект.Номенклатура или произвольная таблица значений).
  2. Используя функцию ПолучитьФорму() на сервере (без её фактического открытия на клиенте), мы можем прочитать структуру элементов метаданных исходной формы.
  3. Программно обходим коллекцию элементов и через метод Элементы.Добавить() создаем аналогичные элементы в целевой группе основной формы.
  4. Связываем созданные элементы с данными через свойство ПутьКДанным.

Рассмотрим пример программного добавления реквизитов и элементов на сервере:


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

Этот способ требует написания дополнительного кода для синхронизации данных, но обеспечивает бесшовную интеграцию интерфейса.

Способ 2. Использование динамических групп и страниц (Рекомендуемый метод)

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

Для этого мы используем элементы типа Группа - Страницы или обычные группы с управляемой видимостью. Разберем этот процесс по шагам:

  1. В конфигураторе открываем основную форму и добавляем группу страниц (панель вкладок).
  2. Каждую «подформу» проектируем на отдельной странице этой группы.
  3. Отключаем отображение закладок у группы страниц, чтобы пользователь не мог переключать их вручную.
  4. В коде управляем видимостью нужной страницы в зависимости от действий пользователя.

Посмотрим на пример кода, переключающего подформы по нажатию кнопок:


&НаКлиенте
Процедура ПереключитьРазделИнтерфейса(ИмяРаздела)
    
    // Переключаем видимость страниц программно
    Если ИмяРаздела = "Продажи" Тогда
        Элементы.СтраницаПродажи.Видимость = Истина;
        Элементы.СтраницаЗакупки.Видимость = Ложь;
    ИначеЕсли ИмяРаздела = "Закупки" Тогда
        Элементы.СтраницаПродажи.Видимость = Ложь;
        Элементы.СтраницаЗакупки.Видимость = Истина;
    КонецЕсли;
    
КонецПроцедуры

Преимущество метода: Высокая скорость работы, отсутствие сложного программного кода генерации элементов, простота поддержки интерфейса в конфигураторе.

Способ 3. Интеграция через поле HTML-документа

Если требуется вывести сложный интерактивный интерфейс, веб-приложение или динамическую инфографику, лучшим решением будет использование элемента формы Поле HTML-документа.

Этот механизм позволяет транслировать сверстанный HTML-код непосредственно внутрь управляемой формы 1С. Мы можем организовать полноценный двусторонний обмен данными между платформой 1С и JavaScript-кодом внутри HTML-страницы.

Разберем пример инициализации HTML-поля:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Формируем простой HTML-интерфейс
    ТекстHTML = "
    |<html>
    |<head>
    |    <style>
    |        body { font-family: Arial, sans-serif; background-color: #f0f0f0; padding: 10px; }
    |        .card { background: white; padding: 15px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
    |    <s/tyle>
    |</head>
    |<body>
    |    <div class='card'>
    |        <h3>Информационная панель</h3>
    |        <p>Данные загружены из базы 1С.</p>
    |        <button onclick='window.external.OnClickButton(""НажатаКнопка"")'>Взаимодействие с 1С</button>
    |    </div>
    |</body>
    |</html>";
    
    ЭтаФорма.СодержимоеHTML = ТекстHTML;
    
КонецПроцедуры

Для обработки кликов по кнопкам внутри HTML-документа используем событие ПриНажатии у элемента формы ПолеHTMLДокумента. В обработчике мы можем получить переданные параметры и выполнить необходимый код на стороне 1С.

Способ 4. Использование Информационных панелей (Дашбордов)

Начиная с версии платформы 8.3.15, разработчикам стал доступен встроенный механизм создания информационных панелей. Этот инструмент разработан специально для компоновки различных отчетов, графиков и списков в единой рабочей области.

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

Способ 5. Блокировка окна владельца

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

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


&НаКлиенте
ПроцедураОткрытьПодчиненнуюФорму()
    
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("Ключ", ТекущийДокумент);
    
    // Блокируем окно владельца для жесткой связи контекстов
    ОткрытьФорму(
        "Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента", 
        ПараметрыОткрытия, 
        ЭтаФорма, 
        Истина, 
        , 
        , 
        , 
        РежимОткрытияОкнаФормы.БлокироватьОкноВладельца
    );
    
КонецПроцедуры

Подведение итогов

Несмотря на то, что прямое открытие управляемой формы внутри другой формы заблокировано на уровне архитектуры платформы «1С:Предприятие 8.3», мы располагаем широким набором инструментов для обхода этого ограничения. Выбор конкретного метода зависит от архитектурных задач:

← На главную