Интеграция между различными информационными базами «1С:Предприятия» с использованием COM-соединения (компоненты V83.COMConnector) — классический способ настройки прямого обмена данными. Тем не менее, начинающие разработчики часто сталкиваются с неочевидным поведением платформы при попытке передать во внешнюю базу или создать внутри нее стандартные коллекции данных, такие как Структура, СписокЗначений, Массив или ТаблицаЗначений.
В этой статье мы подробно разберем, почему возникает ошибка несовместимости типов при работе с COM-объектами, как правильно инициализировать коллекции во внешней базе и наполнять их данными, а также проанализируем типичные ошибки разработчиков на конкретных примерах.
Рассмотрим классическую ошибку, с которой часто начинается работа над подобными задачами. Разработчик подключается к внешней базе через COM и пытается записать в свойство или передать в функцию локально созданный объект:
V83COMConnector = Новый COMОбъект("V83.COMConnector");
Base1С = V83COMConnector.Connect(ПараметрыПодключения);
// Ошибка! Попытка присвоить локальный список значений свойству во внешней базе
Base1С.ОрганизацииПриемника = Новый СписокЗначений;
При выполнении этого кода платформа выдаст ошибку. Дело в том, что такие типы данных, как Структура, СписокЗначений, ТаблицаЗначений и Массив, являются мутабельными (изменяемыми) объектами. Платформа 1С не умеет передавать мутабельные объекты через границу COM-соединения напрямую. Локальный объект, созданный с помощью оператора Новый, существует в памяти вашего текущего процесса. Внешняя база данных, подключенная через COM, работает в своем собственном адресном пространстве (даже если физически это происходит на одном компьютере). Попытка передать ссылку на область памяти текущего процесса во внешний процесс вызывает конфликт сериализации и приводит к ошибке «Несоответствие типов».
Золотое правило работы через COM-соединение: любой сложный объект или коллекция данных, которые должны обрабатываться на стороне внешней базы, должны быть физически созданы в контексте этой внешней базы.
Для создания любых объектов во внешней базе используется специальный метод COM-соединения — NewObject(). Этот метод является полным аналогом стандартного оператора Новый, но инициализирует объект непосредственно в контексте подключенной информационной базы.
Разберем по шагам правильный алгоритм создания и заполнения списка значений:
NewObject("СписокЗначений").Посмотрим на практический пример реализации этого алгоритма:
// 1. Подключение
V83COMConnector = Новый COMОбъект("V83.COMConnector");
Base1С = V83COMConnector.Connect(ПараметрыПодключения);
// 2. Инициализация списка значений во внешней базе
СписокОрганизаций = Base1С.NewObject("СписокЗначений");
// 3. Поиск элемента во внешней базе (Важно: поиск выполняется на стороне Base1C!)
СсылкаНаОрганизацию = Base1С.Справочники.Организации.НайтиПоНаименованию("Восток Сервис ООО");
// Проверяем, найден ли элемент во внешней базе перед добавлением
Если Не СсылкаНаОрганизацию.Пустая() Тогда
// 4. Добавляем элемент в созданный COM-список значений
СписокОрганизаций.Добавить(СсылкаНаОрганизацию);
Иначе
ЗаписатьЛогСобытий("Организация не найдена во внешней базе.");
КонецЕсли;
Обратите внимание на частую ошибку использования неверного метода. В исходном обсуждении на форуме разработчик пытался использовать метод Вставить() для добавления элемента в список значений. У объекта СписокЗначений нет метода Вставить() для добавления произвольных элементов (для этого служит метод Добавить()), из-за чего платформа закономерно возвращала ошибку. Всегда сверяйтесь со встроенной справкой по доступным методам конкретного класса объектов.
По аналогии со списком значений, объект Структура во внешней базе создается через метод NewObject. Платформа 1С позволяет инициализировать структуру двумя удобными способами.
Способ первый: последовательное добавление свойств. Сначала мы создаем пустую структуру во внешней базе, а затем наполняем ее ключами и значениями с помощью метода Вставить():
// Создаем пустую структуру в контексте COM-соединения
ВнешняяСтруктура = Base1С.NewObject("Структура");
// Заполняем структуру примитивными типами данных
ВнешняяСтруктура.Вставить("КодКлиента", "УТ-0000456");
ВнешняяСтруктура.Вставить("РазрешитьОтгрузку", Истина);
ВнешняяСтруктура.Вставить("ЛимитКредита", 150000);
Способ второй: создание структуры со свойствами в одну строку. Конструктор NewObject полностью повторяет поведение локального конструктора структуры и позволяет передать строку с именами полей через запятую, а затем — соответствующие им значения:
// Создание и заполнение структуры в одну строку через COM
ВнешняяСтруктура = Base1С.NewObject("Структура", "КодКлиента, РазрешитьОтгрузку, ЛимитКредита", "УТ-0000456", Истина, 150000);
Этот метод лаконичен и удобен, когда вам заранее известен весь набор ключей и значений, которые необходимо передать во внешнюю базу.
Если вам требуется передать сложный массив данных, например, табличную часть документа, лучшим выбором станет использование объекта ТаблицаЗначений. При работе с таблицами значений через COM-соединение возникает важный нюанс: колонки таблицы часто требуют явного указания типов данных. Объект ОписаниеТипов в данном случае также является системным объектом, который необходимо создавать на стороне внешней базы.
Проанализируем пример создания типизированной таблицы значений во внешней базе:
// Создаем таблицу значений во внешней базе
ТаблицаТоваров = Base1С.NewObject("ТаблицаЗначений");
// Для типизации колонок создаем объекты ОписаниеТипов во внешней базе
ТипСтрока = Base1С.NewObject("ОписаниеТипов", "Строка");
ТипЧисло = Base1С.NewObject("ОписаниеТипов", "Число");
// Добавляем колонки в таблицу значений
ТаблицаТоваров.Колонки.Добавить("Артикул", ТипСтрока);
ТаблицаТоваров.Колонки.Добавить("Количество", ТипЧисло);
// Наполняем таблицу строками
НоваяСтрока = ТаблицаТоваров.Добавить();
НоваяСтрока.Артикул = "ART-99212";
НоваяСтрока.Количество = 12;
При организации обмена данными через V83.COMConnector важно учитывать неочевидные особенности платформы, чтобы избежать трудноуловимых ошибок времени выполнения:
ОганизацииПремника (пропущена буква «р» в первом слове и буква «и» во втором). При написании кода для COM-соединений компилятор 1С не проверяет существование свойств внешних объектов на этапе компиляции. Любая опечатка проявит себя только непосредственно при выполнении кода пользователем в виде критической ошибки.comcntr.dll ровно той версии платформы, которая используется для работы с базами. Любое несовпадение релизов может приводить к сбоям подключения.В ходе обсуждения на форуме участники затронули тему использования HTTP-сервисов как альтернативы COM-соединению. Действительно, в современной разработке на платформе «1С:Предприятие 8» технология COM считается устаревшей и не рекомендуется для построения новых интеграционных решений по следующим причинам:
При использовании HTTP-сервисов отпадает необходимость создавать структуры или списки значений во внешней базе «на лету». Вместо этого отправитель сериализует локальную структуру данных в универсальный текстовый формат JSON или XML, отправляет её по протоколу HTTP, а база-получатель принимает строку и десериализует её обратно в свои внутренние объекты:
// Пример на стороне отправителя: упаковка локальной структуры в JSON
ДанныеДляОтправки = Новый Структура;
ДанныеДляОтправки.Вставить("Артикул", "ART-100");
ДанныеДляОтправки.Вставить("Количество", 5);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Далее СтрокаJSON отправляется через HTTPСоединение в базу-приемник,
// где она будет прочитана функцией ПрочитатьJSON() во внутреннюю структуру приемника.
Использование HTTP-сервисов делает интеграцию независимой от платформы, стабильной и легко масштабируемой, однако, если архитектура вашего решения жестко завязана на использование COM-соединений, описанные выше правила создания коллекций через NewObject остаются единственно верным и надежным инструментом.