Как программно открыть форму существующего документа во вкладке, а не в отдельном окне?

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

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

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

Выясняем причину: баг платформы и асинхронные вызовы

Давайте проанализируем ситуацию, описанную разработчиками. Проблема проявляется при следующей последовательности действий: на форме документа (например, Заказ покупателя) располагается кнопка. При ее нажатии выполняется алгоритм, который программно изменяет реквизит типа ДокументСсылка (например, статус связанного документа), после чего вызывается метод ОткрытьФорму для отображения измененного документа пользователю. Вместо того чтобы аккуратно открыться в новой вкладке текущего сеанса, форма открывается в виде отдельного «модального» или независимого окна Windows/Linux.

Первопричина кроется в официальном баге платформы 1С:Предприятие 8.3. Данная ошибка воспроизводится в релизе 8.3.15.1778, а также в некоторых ранних сборках ветки 8.3.16 (например, 8.3.16.869).

Суть технического сбоя заключается в некорректной работе контекста выполнения при использовании асинхронных вызовов (механизма работы с немодальными окнами через объект ОписаниеОповещения). Если метод ОткрытьФорму вызывается внутри процедуры-обработчика оповещения (например, после вызова диалогов ПоказатьВводСтроки, ПоказатьВопрос, ПоказатьВводЗначения или при обработке интерактивного выбора файла), платформа временно «теряет» связь с активным окном-владельцем. Из-за этого открываемая форма игнорирует настройки интерфейса «Такси» и принудительно выводится на экран как независимое окно операционной системы.

Решение 1: Обновление платформы (Официальный путь)

Если в вашей организации или у клиента используется проблемный релиз платформы, самым простым и правильным решением будет обновление технологической платформы 1С. Разработчики фирмы «1С» оперативно исправили данный сбой:

  1. Корректное поведение контекста окон при асинхронных вызовах было полностью восстановлено в релизе 8.3.15.1830.
  2. В последующих стабильных версиях веток 8.3.16, 8.3.17, 8.3.18 и более новых релизах эта ошибка полностью устранена.

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

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

Что делать, если оперативно обновить платформу 1С невозможно (например, из-за жестких регламентов администрирования или облачного хостинга)? В этом случае нам поможет проверенный программный костыль — подключение однократного обработчика ожидания.

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

Рассмотрим по шагам, как реализовать этот алгоритм в модуле управляемой формы:

1. В процедуре, которая выступает обработчиком оповещения (куда возвращается управление после интерактивного диалога), мы сохраняем ссылку на открываемый документ во временную переменную (реквизит формы) и подключаем обработчик ожидания с минимальной задержкой в 0.1 секунды:


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

2. Создаем экспортную процедуру на клиенте, которая будет вызвана платформой по истечении 0.1 секунды. В ней мы выполняем стандартное открытие формы:


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

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

Решение 3: Проверка и изменение режима совместимости конфигурации

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

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

Решение 4: Использование метода ПоказатьЗначение()

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

Давайте посмотрим на пример использования этого метода:


&НаКлиенте
Процедура ОткрытьДокументЧерезПоказатьЗначение(СсылкаНаДокумент)
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияФормыДокумента", ЭтотОбъект);
    
    // Платформа сама определит основную форму для переданной ссылки и откроет её
    ПоказатьЗначение(ОписаниеОповещения, СсылкаНаДокумент);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияФормыДокумента(ДополнительныеПараметры) Экспорт
    // Код, выполняемый после того, как пользователь закроет открытый документ
КонецПроцедуры

Использование метода ПоказатьЗначение позволяет избежать явного указания пути к форме (например, Документ.ЗаказПокупателя.Форма.ФормаДокумента), что делает код более универсальным и устойчивым к изменениям структуры метаданных.

Решение 5: Явное указание владельца формы

Еще один способ локализовать проблему — принудительно передать контекст окна-владельца при вызове метода ОткрытьФорму. Хотя в сбойных релизах (таких как 8.3.15.1778) платформа может игнорировать этот параметр из-за нарушения внутренней логики, на более стабильных сборках это помогает зафиксировать положение окна:


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

Использование ЭтотОбъект (текущая форма) в качестве третьего параметра функции ОткрытьФорму явно связывает жизненный цикл новой формы с формой-родителем, гарантируя открытие в том же рабочем пространстве.

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

Мы детально изучили проблему некорректного программного открытия форм документов в 1С:Предприятии 8.3. Подводя итог, выделим ключевые рекомендации для разработчика:

← На главную