Как открыть форму документа из другой базы 1С через COM/OLE?

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

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

В этой статье мы подробно разберем, как решить задачу визуального открытия формы документа из другой информационной базы. Мы проанализируем классический подход через OLE/COM-соединение, рассмотрим реальный пример кода из типовой конфигурации «1С:Консолидация», обсудим проблему активации фонового окна и изучим современные, более производительные альтернативы без использования COM-соединений.

COMConnector против Application: принципиальное различие

Первое, с чем сталкиваются разработчики при попытке открыть форму через COM — это отсутствие какого-либо видимого результата при использовании объекта V83.COMConnector. Давайте разберем причину этого поведения.

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

  1. V83.COMConnector (Внутрипроцессный COM-сервер) — предназначен для быстрой и легковесной работы с данными. Он выполняется в рамках процесса вызывающего приложения, работает быстрее, но принципиально не имеет графического интерфейса (UI). Попытка вызвать метод получения формы через такое соединение вызовет ошибку либо не приведет к какому-либо визуальному результату.
  2. V83.Application (Внепроцессный OLE-сервер) — запускает полноценный сеанс 1С (толстый или тонкий клиент). Этот способ работает медленнее и требует больше ресурсов системы, однако он поддерживает работу с интерфейсом, интерактивными формами и диалогами.

Таким образом, если наша цель — показать пользователю форму документа, мы обязаны использовать подключение через V83.Application и явно управлять видимостью окна приемника.

Реализация через V83.Application: пример из 1С:Консолидация

Рассмотрим проверенный временем и практикой метод открытия формы внешнего объекта. Ниже приведен адаптированный алгоритм, используемый в типовом решении «1С:Консолидация». Этот код позволяет по уникальному идентификатору (UUID) получить ссылку на объект во внешней базе и модально открыть его форму. Если уникальные идентификаторы элементов в базах различаются, при переносе данных используется настройка сопоставления объектов по произвольным полям поиска для исключения появления дубликатов.

Проанализируем этот код:


&НаСервере
Функция ОткрытьФормуОбъектаВИБ(Расшифровка)
    // 1. Устанавливаем OLE-соединение с внешней информационной базой
    #Если Клиент ИЛИ ВнешнееСоединение Тогда
        ТекСоединениеВИБ = ОбщегоНазначения.ПолучитьСоединение(глТаблицаПодключений, Отчет.ИспользуемаяИБ, 0);
    #ИначеЕсли Сервер Тогда
        ТекСоединениеВИБ = УправлениеСоединениямиВИБ.ПолучитьСоединение(Отчет.ИспользуемаяИБ, 1);
    #Иначе
        ТекСоединениеВИБ = Неопределено;
    #КонецЕсли;

    Если ТекСоединениеВИБ = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;

    // 2. Создаем UUID объекта во внешней базе на основании имеющегося идентификатора
    ТекUUID = ТекСоединениеВИБ.NewObject("UUID", Расшифровка.Ссылка);

    // 3. Получаем ссылку на объект в зависимости от его метаданных
    Если Расшифровка.ТипОбъектаМетаданных = "Документ" Тогда
        ОбъектСсылкаВИБ = ТекСоединениеВИБ.Документы[Расшифровка.ИмяОбъектаМетаданных].GetRef(ТекUUID);
    ИначеЕсли Расшифровка.ТипОбъектаМетаданных = "Справочник" Тогда
        ОбъектСсылкаВИБ = ТекСоединениеВИБ.Справочники[Расшифровка.ИмяОбъектаМетаданных].GetRef(ТекUUID);
    ИначеЕсли Расшифровка.ТипОбъектаМетаданных = "Перечисление" Тогда
        ОбъектСсылкаВИБ = ТекСоединениеВИБ.Перечисления[Расшифровка.ИмяОбъектаМетаданных].GetRef(ТекUUID);
    КонецЕсли;

    // 4. Открываем форму в контексте толстого клиента
    #Если ТолстыйКлиентОбычноеПриложение ИЛИ ТолстыйКлиентУправляемоеПриложение Тогда
        ФормаОбъекта = ОбъектСсылкаВИБ.GetForm();
        ФормаОбъекта.DoModal(); // Открываем форму модально
        Возврат Неопределено;
    #Иначе
        // Для тонкого клиента передаем описание объекта для последующей обработки
        ТипЗначения = ТекСоединениеВИБ.XMLТипЗнч(ОбъектСсылкаВИБ).TypeName;
        СтруктураОбъекта = Новый Структура("ТипЗначения, Значение", ТипЗначения, ТекСоединениеВИБ.XMLСтрока(ОбъектСсылкаВИБ));
        Возврат СтруктураОбъекта;
    #КонецЕсли;
КонецФункции

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

БазаПриемник.Visible = Истина;

Решение проблемы фонового режима (активация окна через Alt+Tab)

При использовании OLE-соединения часто возникает неприятная особенность: операционная система Windows считает процесс второй базы фоновым. В результате открытая форма не появляется поверх всех окон, а начинает мигать оранжевым цветом на панели задач. Пользователю приходится нажимать комбинацию клавиш Alt+Tab, чтобы найти скрытое окно.

Чтобы принудительно вывести окно внешней базы 1С на передний план, мы можем использовать объект операционной системы WScript.Shell и его метод AppActivate. Рассмотрим пример решения этой проблемы:


// После открытия формы во внешней базе программно активируем ее окно
ЗаголовокОкна = "Управление производственным предприятием"; // Точный заголовок окна внешней базы
WshShell = Новый COMОбъект("WScript.Shell");
WshShell.AppActivate(ЗаголовокОкна);

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

Современная альтернатива без COM: Навигационные ссылки

Работа через COM/OLE имеет ряд существенных недостатков: высокое потребление оперативной памяти на клиенте, медленная скорость инициализации соединения и строгая зависимость от разрядности (32/64-бит) клиента и сервера 1С. Кроме того, при обновлении платформы (например, при переходе с версии 8.3.10 на 8.3.14) зарегистрированные классы COM-соединения часто начинают конфликтовать.

Рассмотрим более современный и надежный способ открытия документов в другой базе — использование внешних навигационных ссылок. Этот метод полностью заменяет OLE-соединения и работает мгновенно. Для быстрого получения идентификаторов нужных данных можно использовать инструмент для отображения GUID объектов в формах и списках.

Алгоритм действий выглядит следующим образом:

  1. В текущей базе мы формируем строку внешней навигационной ссылки на нужный документ. Формат ссылки для клиент-серверного варианта выглядит так:

    e1c://server/ИмяСервера/ИмяБазы#e1cib/data/Документ.ИмяДокумента?ref=ИдентификаторДокумента

  2. Для файловой базы формат строки будет следующим:

    e1c://file/ПутьКБазе#e1cib/data/Документ.ИмяДокумента?ref=ИдентификаторДокумента

  3. Вызываем стандартную команду платформы для открытия этой ссылки.

Посмотрим на пример кода формирования и запуска навигационной ссылки:


// Формируем уникальный идентификатор документа
ИдентификаторСтрока = СтрЗаменить(Строка(ДокументСсылка.УникальныйИдентификатор()), "-", "");

// Собираем внешнюю навигационную ссылку для целевой базы
ПутьКБазе = "server/SQL-SERVER/Production_UPP";
ИмяМетаданных = "Документ.РеализацияТоваровУслуг";
НавигационнаяСсылка = "e1c://" + ПутьКБазе + "#e1cib/data/" + ИмяМетаданных + "?ref=" + ИдентификаторСтрока;

// Запускаем переход по ссылке в операционной системе
ЗапуститьПриложение(НавигационнаяСсылка);

Почему это решение работает лучше, чем OLE?

Альтернатива: Использование параметра запуска /C

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

Разберем этот вариант по шагам:

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


// Формируем строку запуска с передачей команды в параметре /C
СтрокаЗапуска = """C:\Program Files\1cv8\common\1cestart.exe"" ENTERPRISE /S""SQL-SERVER\Production_UPP"" /C""ОткрытьДокумент;РеализацияТоваровУслуг;8a5c37b4-3c1d-11e9-80e2-00155d011203""";
ЗапуститьПриложение(СтрокаЗапуска);

Шаг 2. В базе-приемнике (в модуле управляемого приложения) в процедуре ПриНачалеРаботыСистемы пишем обработчик этого параметра:


Процедура ПриНачалеРаботыСистемы()
    Если ЗначениеЗаполнено(ПараметрЗапуска) Тогда
        // Разбираем строку параметров, разделенную точкой с запятой
        МассивПараметров = СтрРазделить(ПараметрЗапуска, ";");
        
        Если МассивПараметров.Количество() = 3 И МассивПараметров[0] = "ОткрытьДокумент" Тогда
            ИмяДокумента = МассивПараметров[1];
            UIDСтрока = МассивПараметров[2];
            
            // Ищем документ по UUID и открываем его форму
            СсылкаНаДокумент = Документы[ИмяДокумента].ПолучитьСсылку(Новый УникальныйИдентификатор(UIDСтрока));
            Если Не СсылкаНаДокумент.Пустая() Тогда
                ПараметрыФормы = Новый Структура("Ключ", СсылкаНаДокумент);
                ОткрытьФорму("Документ." + ИмяДокумента + ".ФормаОбъекта", ПараметрыФормы);
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

← На главную