Разработка и Конфигурация · 12 мин
Как получить значение COM-объекта в 1С
Как подключиться к базе 1С через COM-connector и получить значение объекта: свойства, реквизиты, табличные части, запросы. Примеры кода, ошибки и FAQ.
COM-соединение — один из основных способов обмена данными между базами 1С и внешними приложениями. Через объект V83.COMConnector (или V82 для старых платформ) можно подключиться к другой информационной базе, получить ссылку на документ или справочник и прочитать значения его реквизитов так, будто вы работаете внутри самой базы. При этом у разработчиков чаще всего возникают вопросы именно на этапе извлечения значений: как обратиться к реквизиту, как прочитать табличную часть, как получить примитивное значение вместо COM-объекта.
Ключевая особенность работы через COM — типы данных. Числа, строки, даты и булево передаются между базами напрямую, а вот ссылки, перечисления, объекты и табличные части приходят как COM-объекты, с которыми нужно обращаться через методы соединения. Если этого не учитывать, код либо падает с ошибкой, либо возвращает неперевариваемые значения.
Материал рассчитан на разработчиков и администраторов, которые настраивают интеграцию между базами 1С или выгрузку данных во внешние системы. Разберём подключение, получение значений разных типов, работу с запросами через COM и типичные ошибки.
Как устроено получение данных через COM в 1С
Механизм строится на технологии OLE Automation. Одна база 1С (или внешнее приложение) выступает клиентом, другая — сервером автоматизации. Клиент создаёт COM-объект коннектора, открывает соединение и через него обращается к менеджерам объектов: Справочники, Документы, Перечисления и так далее.
Когда вы читаете реквизит объекта через COM, результат зависит от типа реквизита. Строка, число, дата и булево возвращаются как обычные значения, с которыми можно сразу работать. Ссылочные типы (другой справочник, документ, перечисление) возвращаются как новые COM-объекты. Попытка вывести такое значение в строку даст либо служебное описание, либо ошибку преобразования.
Отсюда главное правило: любое ссылочное значение, полученное через COM, нужно «разворачивать» до примитивов — читать его Наименование, Код, УникальныйИдентификатор или другие примитивные реквизиты, либо передавать в запрос на стороне базы-источника.
Как установить COM-соединение с базой 1С
Прежде чем получать значения, нужно открыть соединение. Для файловой базы строка подключения выглядит как путь к каталогу, для клиент-серверной — как указание сервера и имени базы. Код подключения в типовом виде:
Коннектор = Новый COMОбъект("V83.COMConnector");
СтрокаПодключения = "File=""D:\Bases\Trade""; Usr=""Администратор""; Pwd=""12345"";";
Соединение = Коннектор.Connect(СтрокаПодключения);
Для серверной базы строка меняется: Srvr="Server1";Ref="Trade";Usr="...";Pwd="...";. Имя класса зависит от версии платформы: V83 для платформы 8.3, V82 для 8.2. Если на машине установлено несколько версий, регистрируется коннектор той версии, которая нужна базе-источнику — иначе получите ошибку несовместимости версий.
После успешного Connect() переменная Соединение становится аналогом глобального контекста удалённой базы: через неё доступны Соединение.Справочники, Соединение.Документы, Соединение.NewObject() и другие привычные конструкции.
- 1Создайте COMОбъект V83.COMConnector на стороне клиента
- 2Сформируйте строку подключения с путем к базе, пользователем и паролем
- 3Выполните Connect() и убедитесь, что соединение не равно Неопределено
- 4Получите ссылку через менеджер объекта (НайтиПоКоду, НайтиПоНаименованию, ПолучитьСсылку)
- 5Прочитайте нужные реквизиты, разворачивая ссылочные значения до примитивов
- 6Закройте соединение, обнулив переменные (Соединение = Неопределено)
Как получить ссылку на объект через COM
Любое чтение начинается с получения ссылки. Способов несколько: поиск по коду, по наименованию, по уникальному идентификатору или выборка всех элементов. Примеры:
// По коду
Контрагент = Соединение.Справочники.Контрагенты.НайтиПоКоду("000000123");
// По наименованию
Номенклатура = Соединение.Справочники.Номенклатура.НайтиПоНаименованию("Кирпич М-150");
// По GUID — самый надёжный способ при регулярном обмене
УИД = Соединение.NewObject("УникальныйИдентификатор", "a1b2c3d4-...");
Ссылка = Соединение.Документы.РеализацияТоваровУслуг.ПолучитьСсылку(УИД);
Если элемент не найден, методы поиска вернут пустую ссылку, а не Неопределено — это частая ловушка. Проверяйте результат через Ссылка.Пустая() перед обращением к реквизитам, иначе получите либо пустые значения, либо ошибку.
Для регулярных интеграций предпочтителен поиск по GUID: коды и наименования могут меняться или дублироваться, а уникальный идентификатор стабилен. Идентификатор удобно хранить в базе-приёмнике в служебном регистре соответствий.
Как прочитать реквизиты и развернуть ссылочные значения
Примитивные реквизиты читаются прямым обращением по имени:
Наименование = Контрагент.Наименование; // строка
ИНН = Контрагент.ИНН; // строка
ДатаДокумента = Документ.Дата; // дата
Сумма = Документ.СуммаДокумента; // число
Ссылочные реквизиты требуют разворачивания. Например, реквизит «Организация» документа — это COM-объект ссылки. Чтобы получить её название, обращайтесь к примитивному реквизиту вложенного объекта:
ОрганизацияСсылка = Документ.Организация; // COM-объект
НазваниеОрганизации = ОрганизацияСсылка.Наименование; // строка
ГУИДОрганизации = Соединение.String(ОрганизацияСсылка.УникальныйИдентификатор());
Обратите внимание на метод Соединение.String() — он преобразует значение в строку на стороне удалённой базы и возвращает обычную строку, а не COM-объект. Аналогично работают Boolean(), Number(), Date(). Для перечислений через COM нельзя сравнивать значение напрямую с локальным перечислением — получайте его имя через метаданные или индекс и сопоставляйте по строке.
Как получить значения табличной части и результаты запроса
Табличная часть документа через COM — это коллекция строк, каждая из которых тоже COM-объект. Обход выполняется циклом:
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
Товар = СтрокаТЧ.Номенклатура.Наименование; // разворачиваем ссылку
Количество = СтрокаТЧ.Количество; // примитив
Цена = СтрокаТЧ.Цена;
КонецЦикла;
Такой перебор медленный на больших объёмах. Производительная альтернатива — выполнить запрос целиком на стороне удалённой базы и забрать выгрузку:
Запрос = Соединение.NewObject("Запрос");
Запрос.Текст = "ВЫБРАТЬ Номенклатура.Наименование КАК Товар, СУММА(Количество) КАК Кол
|ИЗ Документ.РеализацияТоваровУслуг.Товары
|ГДЕ Ссылка.Дата МЕЖДУ &Нач И &Кон
|СГРУППИРОВАТЬ ПО Номенклатура";
Запрос.УстановитьПараметр("Нач", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("Кон", КонецМесяца(ТекущаяДата()));
Результат = Запрос.Выполнить().Выгрузить();
Таблица значений, полученная через Выгрузить(), остаётся COM-объектом, но обход её строк через Выбор() или Выгрузить() с последующим циклом всё равно быстрее, чем тысячи точечных чтений реквизитов. В тексте запроса сразу выбирайте примитивные представления ссылок (Наименование, Код), чтобы не разворачивать их на клиенте.
Если нужно передать большую таблицу значений из удалённой базы, сериализуйте её на стороне источника в строку (например, через ЗначениеВСтрокуВнутр или JSON) и передайте одним строковым значением — это на порядок быстрее построчного чтения через COM.
Типичные ошибки при получении значений через COM
Первая группа ошибок связана с подключением. «Ошибка при создании объекта V83.COMConnector» означает, что на машине не зарегистрирован коннектор нужной версии — лечится регистрацией comcntr.dll из каталога нужной платформы командой regsvr32. «Несовместимость версий» возникает, когда коннектор одной версии пытается открыть базу другой.
Вторая группа — ошибки типов. Попытка присвоить COM-ссылку локальной переменной ссылочного типа, сравнение COM-перечисления со строкой, передача локального объекта (например, таблицы значений) в метод удалённой базы — всё это вызывает ошибки преобразования. Правило простое: через границу COM передавайте только примитивы и строки, а объекты создавайте через Соединение.NewObject() на той стороне, где они будут использоваться.
Третья группа — права и блокировки. Пользователь из строки подключения должен иметь права на чтение нужных объектов в базе-источнике, иначе реквизиты будут пустыми или чтение упадёт с ошибкой доступа. Также COM-соединение создаёт сеанс в базе: открытые и незакрытые соединения накапливаются и могут мешать регламентным операциям.
Как проверить результат и когда COM лучше заменить
После получения значений проверьте их полноту: количество обработанных записей, контрольные суммы по ключевым документам, отсутствие пустых ссылок там, где они недопустимы. Для отладки полезно выводить полученные примитивы в журнал регистрации или файл лога — так видно, на каком объекте обрывается чтение.
COM-соединение оправдано для периодических обменов между базами 1С в одной сети, когда нужна полная объектная модель удалённой базы. Но у него есть ограничения: работает только на Windows, требует установленной платформы на клиенте, чувствителен к версиям и держит лицензионный сеанс. Для новых интеграций, особенно с внешними системами, рассмотрите HTTP-сервисы, веб-сервисы или шину данных — они не привязаны к платформе и легче масштабируются.
Способы получить данные из другой базы 1С
Полный доступ к объектной модели, простой код. Только Windows, сеанс в базе, зависимость от версии платформы
Кроссплатформенно, не держит постоянный сеанс, подходит внешним системам. Требует разработки и публикации сервиса
Строгий контракт через WSDL, поддержка сторонних систем. Более тяжёлая настройка и формат
Работает без прямой связи между базами, устойчив к разрывам. Нет мгновенного доступа к актуальным данным
Как проверить результат
Connect() вернул объект без исключения
Ошибка создания COMОбъекта или несовместимости версий
Ссылка.Пустая() возвращает Ложь
Пустая ссылка — реквизиты будут пустыми
Примитивы содержат ожидаемые строки, числа, даты
COM-объект вместо значения — нужно развернуть ссылку
После обмена переменные обнулены, сеанс закрыт
В консоли кластера висят активные сеансы COM
Частые вопросы
Почему вместо значения реквизита я получаю «COMОбъект»?
Реквизит имеет ссылочный тип: справочник, документ или перечисление. Через COM он передаётся как объект, а не как примитив. Обратитесь к его примитивному свойству — например, Реквизит.Наименование — или преобразуйте через Соединение.String().
Как передать уникальный идентификатор между базами?
Получите GUID вызовом Ссылка.УникальныйИдентификатор() на стороне источника и преобразуйте в строку через Соединение.String(). На приёмнике создайте идентификатор из строки конструктором Новый УникальныйИдентификатор(СтрокаГУИД) и найдите ссылку через ПолучитьСсылку().
Можно ли через COM записывать данные, а не только читать?
Да. Получите объект через Ссылка.ПолучитьОбъект() или создайте новый через Соединение.Документы.ИмяДокумента.СоздатьДокумент(), заполните реквизиты и вызовите Записать(). Ссылочные реквизиты при этом должны быть COM-ссылками той же удалённой базы.
Почему обмен через COM работает очень медленно?
Каждое обращение к свойству COM-объекта — отдельный межпроцессный вызов. Тысячи таких обращений в цикле дают основную задержку. Перенесите логику в запрос на стороне источника, выбирайте сразу примитивные представления и передавайте большие объёмы сериализованной строкой.
Работает ли COM-соединение на Linux или через веб-клиент?
Нет. Технология COM доступна только на Windows. На Linux-серверах и в веб-клиенте используйте HTTP-сервисы, веб-сервисы или файловый обмен.
Что делать с ошибкой «Класс не зарегистрирован» при создании V83.COMConnector?
На машине, где выполняется код, не зарегистрирована библиотека comcntr.dll. Найдите её в каталоге bin нужной версии платформы и зарегистрируйте командой regsvr32 с правами администратора. Версия библиотеки должна совпадать с версией платформы базы-источника.
Что важно запомнить
Получение значения COM-объекта 1С сводится к трём шагам: установить соединение через V83.COMConnector, найти ссылку и прочитать реквизиты. Примитивы приходят напрямую, ссылки разворачивайте до примитивов, большие объёмы забирайте запросом. Всегда проверяйте пустые ссылки, совпадение версий коннектора и закрывайте сеанс после обмена.