Как создать и записать документ в 1С через COM-соединение: подробное руководство по решению проблем

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

Интеграция нескольких баз данных «1С:Предприятие» — одна из самых частых задач, с которыми сталкиваются разработчики. Использование технологии COM-соединения (Component Object Model) позволяет напрямую подключаться к внешней базе данных, считывать информацию, а также создавать новые объекты программным путем. Однако этот процесс таит в себе множество подводных камней: от несовместимости типов данных до зависания сеансов и трудностей с отладкой кода.

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

Шаг 1. Инициализация COM-соединения и выбор версии платформы

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

Рассмотрим пример кода, который решает эту задачу:


Функция ПолучитьCOMОбъектПоВерсииПлатформы() Экспорт
    ИмяComОбъекта = "";
    Инфо = Новый СистемнаяИнформация;
    
    Если Найти(Инфо.ВерсияПриложения, "8.3") > 0 Тогда
        ИмяComОбъекта = "V83.COMConnector";
    ИначеЕсли Найти(Инфо.ВерсияПриложения, "8.2") > 0 Тогда
        ИмяComОбъекта = "V82.COMConnector";
    Иначе
        ВызватьИсключение "Не удалось определить версию платформы для создания COM-соединения";
    КонецЕсли;
    
    Попытка
        Возврат Новый COMОбъект(ИмяComОбъекта);
    Исключение
        ЗаписьЖурналаРегистрации("Интеграция.COM", УровеньЖурналаРегистрации.Ошибка, , , 
            "Ошибка инициализации COM-объекта: " + ОписаниеОшибки());
        ВызватьИсключение "Не удалось инициализировать COM-объект " + ИмяComОбъекта;
    КонецПопытки;
КонецФункции

После получения коннектора мы выполняем подключение к базе. Строка подключения зависит от типа базы данных (файловая или клиент-серверная). Обратите внимание на обработку исключений — это обязательное условие стабильной работы интеграции:


СтрокаПодключения = "file='\\Server\1C_Bases\Accounting\'; usr='Администратор'; pwd='Пароль';";
COMConnector = ПолучитьCOMОбъектПоВерсииПлатформы();

Попытка
    ComConnection = COMConnector.Connect(СтрокаПодключения);
Исключение
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "Ошибка подключения к базе-приемнику: " + ОписаниеОшибки();
    Сообщение.Сообщить();
    Возврат;
КонецПопытки;

Шаг 2. Создание нового документа и заполнение реквизитов

Когда соединение успешно установлено, мы получаем доступ к метаданным внешней базы через переменную ComConnection. Создание нового документа происходит через менеджер соответствующего класса объектов.

Рассмотрим пример создания документа «Реализация товаров и услуг»:


МенеджерДокумента = ComConnection.Документы.РеализацияТоваровУслуг;
НовыйДокумент = МенеджерДокумента.СоздатьДокумент();

// Заполняем базовые реквизиты
НовыйДокумент.Дата = ТекущаяДата();
// Платформа автоматически сгенерирует номер при записи, но мы можем задать префикс или номер вручную:
НовыйДокумент.УстановитьНовыйНомер("РТ");

Шаг 3. Решение проблемы несовместимости типов (Различие контекстов)

Одна из главных логических ошибок начинающих разработчиков — попытка присвоить реквизитам COM-объекта значения ссылочных типов из текущей (локальной) базы. Например, следующая конструкция приведет к ошибке «Несоответствие типов»:


// ОШИБКА! Строка.Номенклатура — это ссылка текущей базы. Внешняя база её не поймет.
НоваяСтрокаТабЧасти.Номенклатура = Строка.Номенклатура; 

Дело в том, что COM-база работает в собственном адресном пространстве памяти. Ей ничего неизвестно о внутренних идентификаторах (GUID) локальной базы, даже если конфигурации абсолютно идентичны. Чтобы передать ссылку, нам необходимо найти аналогичный объект в контексте внешней базы.

Способ 1. Поиск по реквизиту (код, наименование, артикул)

Этот способ прост, но менее надежен, так как коды или наименования могут дублироваться или изменяться пользователями:


КодНоменклатуры = Строка.Номенклатура.Код;
СсылкаВнешняя = ComConnection.Справочники.Номенклатура.НайтиПоКоду(КодНоменклатуры);

Если Не СсылкаВнешняя.Пустая() Тогда
    НоваяСтрокаТабЧасти.Номенклатура = СсылкаВнешняя;
КонецЕсли;

Способ 2. Синхронизация по Уникальному Идентификатору (GUID) — Рекомендуемый метод

Этот метод гарантирует стопроцентное совпадение объектов, поскольку уникальный идентификатор GUID неизменен. Мы получаем строковое представление GUID из локальной базы, инициализируем объект УникальныйИдентификатор внутри COM-соединения и находим ссылку:


ЛокальныйGUID = Строка(Строка.Номенклатура.УникальныйИдентификатор());

// Создаем объект GUID в контексте внешней базы
ВнешнийGUID = ComConnection.NewObject("УникальныйИдентификатор", ЛокальныйGUID);

// Получаем ссылку во внешней базе
СсылкаВнешняя = ComConnection.Справочники.Номенклатура.ПолучитьСсылка(ВнешнийGUID);

// Проверяем, существует ли этот объект во внешней базе
Если СсылкаВнешняя.ПолучитьОбъект() = Неопределено Тогда
    // Объект не найден. Здесь можно прописать логику его создания или выгрузки
Иначе
    НоваяСтрокаТабЧасти.Номенклатура = СсылкаВнешняя;
КонецЕсли;

Шаг 4. Работа с системными и прикладными перечислениями

Аналогично ссылкам справочников, системные перечисления платформы и перечисления самой конфигурации нельзя передавать напрямую. Обращаться к ним нужно строго через объект подключения ComConnection.

Пример работы с системным перечислением (Режим записи документа):


// НЕПРАВИЛЬНО: Использовать локальное перечисление РежимЗаписиДокумента
// ПРАВИЛЬНО: Обратиться через COM-соединение
РежимПроведения = ComConnection.РежимЗаписиДокумента.Проведение;
НовыйДокумент.Записать(РежимПроведения);

Пример работы с прикладным перечислением конфигурации (например, «Вид операции»):


НовыйДокумент.ВидОперации = ComConnection.Перечисления.ВидыОперацийРеализацииТоваров.ПродажаКомиссия;

Шаг 5. Использование свойства «ОбменДанными.Загрузка» для обхода проверок

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

Чтобы записать документ в «сыром» виде, минуя прикладные проверки конфигурации, используем свойство ОбменДанными.Загрузка. Установим его значение в Истина:


// Обратите внимание на правильный синтаксис обращения к свойству
НовыйДокумент.ОбменДанными.Загрузка = Истина;

// Теперь документ запишется без вызова лишних транзакционных проверок
НовыйДокумент.Записать(ComConnection.РежимЗаписиДокумента.Запись);

Важно: Если вам требуется именно провести документ с формированием движений по регистрам, то отключать проверки с помощью режима загрузки не рекомендуется, иначе вы рискуете получить некорректные или пустые регистры учета.

Шаг 6. Настройка отладки COM-соединений в Конфигураторе

Часто возникает ситуация: код выполняется без видимых ошибок, но документ не проводится или заполняется некорректно из-за скрытых отказов внутри процедур внешней базы. В таком случае нам необходима сквозная отладка.

Для того чтобы иметь возможность заходить отладчиком в код базы-приемника при вызовах через COM-соединение, выполним следующие шаги:

  1. Убедимся, что сервер 1С базы-приемника запущен в режиме отладки (в параметрах службы сервера должен присутствовать ключ -debug).
  2. Запустим конфигуратор базы-приемника.
  3. В главном меню перейдем в раздел Отладка -> Подключение...
  4. В открывшемся окне нажмем кнопку Настройка автоматического подключения.
  5. Установим флажок напротив пункта Клиентские и внешние соединения на сервере.
  6. Теперь при выполнении кода в локальной базе отладчик в конфигураторе базы-приемника будет автоматически перехватывать точки останова внутри процедур внешнего соединения.

Шаг 7. Обеспечение транзакционности обмена

При создании документов и заполнении их табличных частей (например, товаров, услуг, акцизов) сбой может произойти на любом этапе. Чтобы база данных не оставалась в промежуточном («битом») состоянии, весь процесс создания документов необходимо оборачивать в транзакцию на стороне внешней базы:


ComConnection.НачатьТранзакцию();

Попытка
    Менеджер = ComConnection.Документы.РеализацияТоваровУслуг;
    ДокОбъект = Менеджер.СоздатьДокумент();
    
    // Заполнение шапки и табличной части...
    
    ДокОбъект.Записать(ComConnection.РежимЗаписиДокумента.Проведение);
    
    // Если все операции прошли успешно, фиксируем изменения в базе данных
    ComConnection.ЗафиксироватьТранзакцию();
Исключение
    // В случае любой непредвиденной ошибки откатываем все изменения назад
    ComConnection.ОтменитьТранзакцию();
    
    ЗаписьЖурналаРегистрации("Интеграция.COM", УровеньЖурналаРегистрации.Ошибка, , , 
        "Транзакция отменена. Ошибка: " + ОписаниеОшибки());
КонецПопытки;

Шаг 8. Освобождение ресурсов оперативной памяти

Каждое открытое COM-соединение потребляет оперативную память сервера приложений 1С и занимает одну полноценную клиентскую лицензию. Если не уничтожать объекты принудительно, сеансы будут оставаться активными ("зависать"), что со временем приведет к нехватке лицензий и перегрузке сервера.

В конце выполнения процедуры интеграции всегда явно очищайте ссылки на COM-объекты:


// Освобождаем память сервера и закрываем сеанс в базе-приемнике
ComConnection = Неопределено;
COMConnector = Неопределено;

Современная альтернатива: Почему стоит отказываться в пользу HTTP-сервисов

Хотя технология COM остается популярной и простой в реализации для внутренних обменов Windows-инфраструктуры, современные стандарты разработки в среде 1С рекомендуют уходить от этого подхода по следующим причинам:

  1. Платформозависимость: Технология COM является проприетарным решением Microsoft Windows. Если ваши сервера 1С будут мигрировать на операционные системы семейства Linux, COM-соединения полностью перестанут работать.
  2. Лицензирование: COM-сессия расходует дефицитные клиентские лицензии в режиме реального времени на протяжении всего сеанса работы.
  3. Безопасность: База-источник получает слишком глубокий доступ к метаданным приемника, что нарушает концепцию сервисно-ориентированной архитектуры (SOA).

Вместо COM-соединений для современных интеграционных задач рекомендуется разрабатывать **HTTP-сервисы (REST API)** внутри базы-приемника. В таком сценарии база-источник просто отправляет легкий структурированный JSON-пакет данных, а база-приемник на своей стороне самостоятельно и безопасно обрабатывает запрос, проверяет заполнение полей и создает документ стандартными средствами платформы.

← На главную