Почему возникает ошибка «отсутствует отображение для типа ComОбъект» в управляемых формах и как ее исправить?

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

При разработке обработок загрузки данных или интеграций между базами 1С в режиме управляемого приложения разработчики часто сталкиваются с ошибкой: «отсутствует отображение для типа ComОбъект». Ошибка возникает в момент вызова серверной процедуры или функции из клиентского контекста.

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

Причина возникновения ошибки

В архитектуре клиент-серверной работы 1С Предприятия управляемые формы строго разделяют выполнение кода на директивы &НаКлиенте и &НаСервере. Вся передача параметров между клиентом и сервером выполняется через механизм XDTO-сериализации.

Объект типа COMОбъект (включая выборки, менеджеры и ссылки, полученные из внешнего соединения) не является сериализуемым типом платформы 1С. Платформа попросту не умеет трансформировать COM-указатель операционной системы Windows в сетевой пакет для передачи на серверную сторону. Попытка передать COM-объект или выборку из COM в качестве параметра процедуры с директивой &НаСервере неизбежно приводит к аварийному завершению с сообщением: «отсутствует отображение для типа ComОбъект».

Посмотрим на типичный ошибочный пример:


&НаКлиенте
Процедура Запустить(Команда)
    Соединение = Новый COMОбъект("V83.Application");
    Соединение.Connect("File=C:\Base;Usr=User;Pwd=123;");
    
    Выборка = Соединение.Документы.РеализацияТоваровУслуг.Выбрать();
    Пока Выборка.Следующий() Цикл
        // ОШИБКА: Выборка является COM-объектом и не может быть передана на сервер
        СоздатьДокументНаСервере(Выборка);
    КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура СоздатьДокументНаСервере(ДокументCOM)
    // Сервер падает еще до входа в тело процедуры
    НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
    НовыйДок.Записать();
КонецПроцедуры

Способ 1. Перенос всей логики интеграции на сторону сервера

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

Разберем по шагам реализацию единой процедуры на сервере:

  1. На клиенте объявляем обработчик команды формы &НаКлиенте, который просто вызывает серверную процедуру без параметров.
  2. На сервере инициализируем подключение к базе-источнику через COMОбъект.
  3. Выполняем выборку и сразу создаем нужные объекты в текущей базе с помощью методов прикладных объектов (например, СоздатьДокумент()).

Посмотрим на пример правильного серверного кода:


&НаКлиенте
Процедура ЗапуститьОбработку(Команда)
    ВыполнитьЗагрузкуНаСервере();
КонецПроцедуры

&НаСервере
Процедура ВыполнитьЗагрузкуНаСервере()
    Попытка
        // Для оптимизации рекомендуется использовать V83.COMConnector вместо V83.Application
        COMСоединитель = Новый COMОбъект("V83.COMConnector");
        СтрокаПодключения = "File=""C:\1c-star-baza""; Usr=""Репнин Александр""; Pwd=""9985"";";
        ВнешняяБаза = COMСоединитель.Connect(СтрокаПодключения);
    Исключение
        ВызватьИсключение "Не удалось подключиться к базе: " + ОписаниеОшибки();
    КонецПопытки;
    
    Выборка = ВнешняяБаза.Документы.РеализацияТоваровУслуг.Выбрать('20130101', '20140110');
    
    Пока Выборка.Следующий() Цикл
        НовРеал = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
        НовРеал.Дата = ТекущаяДата();
        
        // Получаем наименование контрагента в виде обычной строки
        ИмяКонтрагента = Строка(Выборка.Контрагент.Наименование);
        НайденныйКонтрагент = Справочники.Контрагенты.НайтиПоНаименованию(ИмяКонтрагента);
        
        Если ЗначениеЗаполнено(НайденныйКонтрагент) Тогда
            НовРеал.Контрагент = НайденныйКонтрагент;
        КонецЕсли;
        
        НовРеал.Организация = Справочники.Организации.НайтиПоНаименованию("Медресурс");
        НовРеал.Записать();
    КонецЦикла;
    
    // Освобождаем память COM-объекта
    ВнешняяБаза = Неопределено;
    COMСоединитель = Неопределено;
КонецПроцедуры

Способ 2. Выгрузка данных в сериализуемые коллекции на клиенте

Если сервер 1С работает под управлением 64-битной версии или ОС Linux (где COM-соединения могут быть недоступны), подключение создается на стороне клиента Windows. Чтобы передать информацию на сервер, данные из COM-объекта предварительно извлекаются в примитивные типы (Строка, Число, Дата, Булево) и помещаются в сериализуемую структуру или массив.

Рассмотрим пример правильной передачи данных через Массив и Структура:


&НаКлиенте
Процедура ЗапуститьНаКлиенте(Команда)
    Соединитель = Новый COMОбъект("V83.COMConnector");
    База = Соединитель.Connect("File=""C:\1c-star-baza""; Usr=""Admin""; Pwd=""123"";");
    
    СписокДокументов = Новый Массив;
    
    Выборка = База.Документы.РеализацияТоваровУслуг.Выбрать('20130101', '20140110');
    Пока Выборка.Следующий() Цикл
        ДанныеДокумента = Новый Структура;
        ДанныеДокумента.Вставить("Дата", Выборка.Дата);
        ДанныеДокумента.Вставить("КонтрагентНаименование", Строка(Выборка.Контрагент.Наименование));
        ДанныеДокумента.Вставить("ОрганизацияНаименование", Строка(Выборка.Организация.Наименование));
        
        СписокДокументов.Добавить(ДанныеДокумента);
    КонецЦикла;
    
    // Массив структур со строками и датами успешно сериализуется и передается на сервер
    СоздатьДокументыПоСпискуНаСервере(СписокДокументов);
    
    База = Неопределено;
    Соединитель = Неопределено;
КонецПроцедуры

&НаСервере
Процедура СоздатьДокументыПоСпискуНаСервере(СписокДокументов)
    Для Каждого СтрДанных Из СписокДокументов Цикл
        НовРеал = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
        НовРеал.Дата = СтрДанных.Дата;
        НовРеал.Контрагент = Справочники.Контрагенты.НайтиПоНаименованию(СтрДанных.КонтрагентНаименование);
        НовРеал.Организация = Справочники.Организации.НайтиПоНаименованию(СтрДанных.ОрганизацияНаименование);
        НовРеал.Записать();
    КонецЦикла;
КонецПроцедуры

Важные рекомендации при работе с COM-соединениями

  1. Выбор коннектора: Для интеграций всегда предпочтительнее использовать V83.COMConnector вместо V83.Application. Коннектор работает значительно быстрее и не запускает полный графический интерфейс толстого клиента.
  2. Освобождение памяти: По завершении работы с COM-объектом обязательно присваивайте переменным соединения значение Неопределено, чтобы процесс внешней базы не зависал в оперативной памяти сервера или клиента.
  3. Разрядность приложений: Если подключение выполняется на сервере 1С 64-bit, в операционной системе Windows должна быть зарегистрирована соответствующая библиотека comcntr.dll разрядности x64.
← На главную