При интеграции различных конфигураций 1С часто возникает задача не просто передать данные, но и предоставить пользователю возможность посмотреть исходный документ в базе-источнике. Например, это может потребоваться для проверки движений по регистрам, анализа структуры подчиненности или оперативного контроля заполнения реквизитов непосредственно из интерфейса текущей (например, самописной) системы. При необходимости массово сопоставить и проверить результаты трансляции документов применяется автоматическая сверка бухгалтерских и налоговых проводок между информационными базами.
В этой статье мы подробно разберем, как решить задачу визуального открытия формы документа из другой информационной базы. Мы проанализируем классический подход через OLE/COM-соединение, рассмотрим реальный пример кода из типовой конфигурации «1С:Консолидация», обсудим проблему активации фонового окна и изучим современные, более производительные альтернативы без использования COM-соединений.
Первое, с чем сталкиваются разработчики при попытке открыть форму через COM — это отсутствие какого-либо видимого результата при использовании объекта V83.COMConnector. Давайте разберем причину этого поведения.
В платформе 1С реализовано два различных программных интерфейса для связи между базами:
V83.COMConnector (Внутрипроцессный COM-сервер) — предназначен для быстрой и легковесной работы с данными. Он выполняется в рамках процесса вызывающего приложения, работает быстрее, но принципиально не имеет графического интерфейса (UI). Попытка вызвать метод получения формы через такое соединение вызовет ошибку либо не приведет к какому-либо визуальному результату.V83.Application (Внепроцессный OLE-сервер) — запускает полноценный сеанс 1С (толстый или тонкий клиент). Этот способ работает медленнее и требует больше ресурсов системы, однако он поддерживает работу с интерфейсом, интерактивными формами и диалогами.Таким образом, если наша цель — показать пользователю форму документа, мы обязаны использовать подключение через V83.Application и явно управлять видимостью окна приемника.
Рассмотрим проверенный временем и практикой метод открытия формы внешнего объекта. Ниже приведен адаптированный алгоритм, используемый в типовом решении «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 = Истина;
При использовании OLE-соединения часто возникает неприятная особенность: операционная система Windows считает процесс второй базы фоновым. В результате открытая форма не появляется поверх всех окон, а начинает мигать оранжевым цветом на панели задач. Пользователю приходится нажимать комбинацию клавиш Alt+Tab, чтобы найти скрытое окно.
Чтобы принудительно вывести окно внешней базы 1С на передний план, мы можем использовать объект операционной системы WScript.Shell и его метод AppActivate. Рассмотрим пример решения этой проблемы:
// После открытия формы во внешней базе программно активируем ее окно
ЗаголовокОкна = "Управление производственным предприятием"; // Точный заголовок окна внешней базы
WshShell = Новый COMОбъект("WScript.Shell");
WshShell.AppActivate(ЗаголовокОкна);
Этот скрипт ищет окно с указанным заголовком в запущенных процессах операционной системы и принудительно передает ему фокус ввода.
Работа через COM/OLE имеет ряд существенных недостатков: высокое потребление оперативной памяти на клиенте, медленная скорость инициализации соединения и строгая зависимость от разрядности (32/64-бит) клиента и сервера 1С. Кроме того, при обновлении платформы (например, при переходе с версии 8.3.10 на 8.3.14) зарегистрированные классы COM-соединения часто начинают конфликтовать.
Рассмотрим более современный и надежный способ открытия документов в другой базе — использование внешних навигационных ссылок. Этот метод полностью заменяет OLE-соединения и работает мгновенно. Для быстрого получения идентификаторов нужных данных можно использовать инструмент для отображения GUID объектов в формах и списках.
Алгоритм действий выглядит следующим образом:
e1c://server/ИмяСервера/ИмяБазы#e1cib/data/Документ.ИмяДокумента?ref=ИдентификаторДокумента
e1c://file/ПутьКБазе#e1cib/data/Документ.ИмяДокумента?ref=ИдентификаторДокумента
Посмотрим на пример кода формирования и запуска навигационной ссылки:
// Формируем уникальный идентификатор документа
ИдентификаторСтрока = СтрЗаменить(Строка(ДокументСсылка.УникальныйИдентификатор()), "-", "");
// Собираем внешнюю навигационную ссылку для целевой базы
ПутьКБазе = "server/SQL-SERVER/Production_UPP";
ИмяМетаданных = "Документ.РеализацияТоваровУслуг";
НавигационнаяСсылка = "e1c://" + ПутьКБазе + "#e1cib/data/" + ИмяМетаданных + "?ref=" + ИдентификаторСтрока;
// Запускаем переход по ссылке в операционной системе
ЗапуститьПриложение(НавигационнаяСсылка);
Почему это решение работает лучше, чем OLE?
e1c.ЗапуститьПриложение, Windows сама передает управление исполняемому файлу платформы 1С.Если вам требуется передать во вторую базу дополнительные параметры при открытии (например, не просто открыть документ, а сразу сформировать по нему движения или заполнить сопутствующий отчет), можно воспользоваться механизмом параметра запуска /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Строка));
Если Не СсылкаНаДокумент.Пустая() Тогда
ПараметрыФормы = Новый Структура("Ключ", СсылкаНаДокумент);
ОткрытьФорму("Документ." + ИмяДокумента + ".ФормаОбъекта", ПараметрыФормы);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот подход гарантирует стабильное открытие целевого окна поверх всех остальных приложений и предоставляет гибкие возможности для кастомизации поведения конфигурации-приемника при внешнем вызове.