Как открыть форму существующего объекта в другой базе 1С через COM с передачей параметров

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

В практике интеграции систем на платформе 1С:Предприятие 8 часто возникает задача: находясь в одной информационной базе (например, учетной УПП или ERP), программно создать объект в другой базе (например, в «1С:Документообороте») и сразу же открыть его форму на экране пользователя для ручного дозаполнения. При этом в открываемую форму крайне важно передать дополнительные параметры (например, контекст создания, режим открытия или служебные флаги).

На первый взгляд задача кажется тривиальной и решается через OLE-соединение V83.Application и метод ОткрытьФорму(). Однако разработчики регулярно сталкиваются с неочевидными ошибками преобразования типов и проблемами совместимости версий платформы. В этой статье мы подробно разберем причины возникновения этих ошибок и рассмотрим три надежных способа их решения.

Почему стандартный код вызывает ошибку?

Рассмотрим типичный сценарий, который на первый взгляд кажется логичным, но приводит к ошибке выполнения в базе-источнике:


// Пример НЕРАБОЧЕГО кода
V83appl = Новый COMОбъект("V83.Application");
Если V83appl.Connect(мояСтрокаСоединения) Тогда
    
    // Создаем документ в базе-приемнике через COM
    НовыйДокумент = V83appl.Документы.ВнутреннийДокумент.СоздатьДокумент();
    НовыйДокумент.Наименование = "Служебная записка";
    НовыйДокумент.Записать();
    
    // Пытаемся передать параметры формы
    ПараметрыФормы = Новый Структура; // Создается в локальном контексте!
    ПараметрыФормы.Вставить("Ключ", НовыйДокумент.Ссылка);
    ПараметрыФормы.Вставить("ТолькоЧтоСозданныйДокумент", Истина);
    
    // Вызов приводит к ошибке преобразования типов!
    V83appl.ОткрытьФорму("Документ.ВнутреннийДокумент.Форма.ФормаДокумента", ПараметрыФормы);
    
КонецЕсли;

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

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

---

Способ 1. Создание объектов в контексте базы-приемника (COM-решение)

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

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


// Пример РАБОЧЕГО кода через COM-соединение
V83appl = Новый COMОбъект("V83.Application");
Если V83appl.Connect(мояСтрокаСоединения) Тогда
    
    // 1. Создаем и записываем документ в базе-приемнике
    НовыйДокумент = V83appl.Документы.ВнутреннийДокумент.СоздатьДокумент();
    НовыйДокумент.Наименование = "Интеграционный документ";
    НовыйДокумент.Записать();
    
    // Получаем ссылку на только что созданный документ в контексте приемника
    СсылкаНаДокумент = НовыйДокумент.Ссылка;
    
    // 2. Создаем структуру параметров формы непосредственно в удаленной базе!
    ПараметрыФормыПриемника = V83appl.NewObject("Структура");
    
    // Наполняем структуру параметрами
    ПараметрыФормыПриемника.Вставить("Ключ", СсылкаНаДокумент);
    ПараметрыФормыПриемника.Вставить("ТолькоЧтоСозданныйДокумент", Истина);
    ПараметрыФормыПриемника.Вставить("РежимЧтения", Ложь);
    
    // 3. Открываем форму, передавая "родную" структуру параметров базы-приемника
    V83appl.ОткрытьФорму("Документ.ВнутреннийДокумент.Форма.ФормаДокумента", ПараметрыФормыПриемника);
    
КонецЕсли;

В данном случае метод V83appl.NewObject("Структура") гарантирует, что коллекция параметров будет создана в оперативной памяти процесса базы-приемника. Передаваемая в ключ структура полностью совместима с интерфейсными механизмами удаленной базы, и форма успешно откроется на экране пользователя.

---

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

Работа через COM-соединение V83.Application имеет критический недостаток — она требует запуска полноценного тяжелого процесса GUI удаленной базы из-под вызывающего приложения. На терминальных серверах это часто приводит к зависаниям и конфликтам разрядности (например, когда источник работает на 32-битной платформе, а приемник требует 64-битного окружения). Более того, если версии платформ баз отличаются (например, 8.3.10 и 8.3.14), зарегистрированный в реестре Windows OLE-сервер вернет ошибку «Несоответствие версий клиента и сервера».

Чтобы обойти эти ограничения, мы можем применить технологию внешних навигационных ссылок. Этот способ работает невероятно быстро, надежно и не требует администрирования реестра или COM+.

Разберем данный алгоритм по шагам:

  1. Используя легковесный и быстрый V83.COMConnector, мы подключаемся к базе-приемнику исключительно для создания и записи объекта в базу данных (без отрисовки интерфейса).
  2. Получаем уникальный идентификатор (GUID) созданного объекта и формируем навигационную ссылку.
  3. Запускаем тонкий клиент базы-приемника через операционную систему с передачей этой ссылки. Платформа 1С на компьютере пользователя сама определит нужную версию платформы (через 1cestart.exe) и откроет форму нужного объекта.

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


// Используем быстрый COM-коннектор без интерфейса
Connector = Новый COMОбъект("V83.COMConnector");
БазаПриемник = Connector.Connect(мояСтрокаСоединения);

// Создаем и записываем документ
НовыйДок = БазаПриемник.Документы.ВнутреннийДокумент.СоздатьДокумент();
НовыйДок.Наименование = "Документ из внешней системы";
НовыйДок.Записать();

// Получаем строковое представление уникального идентификатора (GUID)
УИД_Строкой = БазаПриемник.String(НовыйДок.Ссылка.УникальныйИдентификатор());

// Формируем навигационную ссылку (для файлового или серверного варианта)
// Формат для сервера: e1c://server/ИмяСервера/ИмяБазы#e1cib/data/Документ.ВнутреннийДокумент?ref=УИД
СтрокаПодключения = мояСтрокаСоединения; // Например: "Srvr=""Server"";Ref=""Base"";"

// Парсим параметры строки подключения для формирования URL
ИмяСервера = "ServerName"; // Выделить программно из строки подключения
ИмяБазы = "BaseName";      // Выделить программно из строки подключения

НавигационнаяСсылка = "e1c://server/" + ИмяСервера + "/" + ИмяБазы 
                    + "#e1cib/data/Документ.ВнутреннийДокумент?ref=" + УИД_Строкой;

// Запускаем форму объекта в сеансе пользователя штатными средствами Windows
ЗапуститьПриложение(НавигационнаяСсылка);

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

---

Способ 3. Передача параметров через параметры запуска (командную строку)

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

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

Рассмотрим схему реализации:

  1. В базе-источнике формируем структуру параметров, сериализуем ее в строку JSON и записываем во временный текстовый файл или передаем напрямую в параметр запуска.
  2. Запускаем базу-приемник командной строкой:
    
    "C:\Program Files\1cv8\common\1cestart.exe" ENTERPRISE /S "Server\Base" /C "ИмяПараметраСхеме"
    
  3. В базе-приемнике в модуле управляемого приложения в обработчике ПриНачалеРаботыСистемы считываем ПараметрЗапуска, парсим параметры и открываем форму нужного нам объекта с переданными аргументами.

Посмотрим на пример кода парсинга параметров при старте системы базы-приемника:


Процедура ПриНачалеРаботыСистемы()
    
    Если ЗначениеЗаполнено(ПараметрЗапуска) Тогда
        // Предположим, параметры переданы в формате JSON: {"Action":"OpenDoc", "ID":"GUID_объекта", "Flag":true}
        ПараметрыСтруктура = ДесериализоватьСтрокуJSON(ПараметрЗапуска);
        
        Если ПараметрыСтруктура.Свойство("Action") И ПараметрыСтруктура.Action = "OpenDoc" Тогда
            СсылкаНаОбъект = Справочники.ВнутренниеДокументы.ПолучитьСсылка(Новый УникальныйИдентификатор(ПараметрыСтруктура.ID));
            
            ПараметрыФормы = Новый Структура;
            ПараметрыФормы.Вставить("Ключ", СсылкаНаОбъект);
            ПараметрыФормы.Вставить("ТолькоЧтоСозданныйДокумент", ПараметрыСтруктура.Flag);
            
            ОткрытьФорму("Справочник.ВнутренниеДокументы.Форма.ФормаЭлемента", ПараметрыФормы);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Использование этого подхода позволяет полностью отказаться от нестабильной технологии OLE (V83.Application) в пользу стабильного и безопасного запуска тонких клиентов, минимизируя нагрузку на сервер и упрощая обновление платформы 1С.

← На главную