Как передать параметр типа Дата в запрос через COM-соединение в 1С

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

При интеграции баз 1С через COM-соединение разработчики нередко сталкиваются с ошибкой «Ошибка обработки представления РегистрБухгалтерии... Несоответствие типов (Параметр номер 1)». Ошибка возникает при попытке выполнить запрос к виртуальной таблице остатков или оборотов, куда в качестве параметра передается дата. Разберем причины возникновения этой неполадки и подробно рассмотрим практические способы ее устранения.

Посмотрим на типичный пример исходного кода, вызывающего сбой:


ЗапросСОМ = БазаСОМ.NewObject("Запрос");
ЗапросСОМ.Текст = "ВЫБРАТЬ
|    ХозрасчетныйОстатки.Субконто3.Код КАК Склад,
|    ХозрасчетныйОстатки.Субконто2.Код КАК ВидТоплива,
|    ХозрасчетныйОстатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
|    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОтчета, Счет = &Счет, , ) КАК ХозрасчетныйОстатки";

Счет_004_01_5 = БазаСОМ.ПланыСчетов.Хозрасчетный.НайтиПоКоду("004.01.5");
ЗапросСОМ.УстановитьПараметр("Счет", Счет_004_01_5);
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ТекущаяДата());

РезультатПоСОМ = ЗапросСОМ.Выполнить();

Выясним причины возникновения ошибки

Проанализируем механику работы COM-соединения и платформы 1С при передаче параметров:

  1. Непримитивный тип данных в настройках компоновки (СКД). Если значение даты извлекается из параметров СКД через НастройкиКомпоновки.ПараметрыДанных.Элементы[0].Значение, значение может иметь составной тип или являться объектом СтандартныйПериод. При передаче через COM-маршалер такой объект не распознается как примитивная дата, из-за чего виртуальная таблица запроса возвращает ошибку несоответствия типов.
  2. Особенности маршалинга типов OLE/COM. При вызове методов объекта внешнего соединения значение транслируется в системный OLE-тип VT_DATE. Если результат вычисляется непосредственно внутри вызова метода или содержит контекст глобальной функции текущей базы, механизм маршалинга может передать значение как объект VT_DISPATCH или строку VT_BSTR, которые запрос на принимающей стороне не может привести к дате.

Способ 1. Явное приведение типа и выделение локальной переменной

Самое простое и эффективное решение — принудительно привести значение к примитивному типу Дата и сохранить его в отдельную локальную переменную перед передачей в метод УстановитьПараметр.

Рассмотрим, как скорректировать код:


// Извлекаем значение из настроек СКД или внешнего источника
ЗначениеПараметра = НастройкиКомпоновки.ПараметрыДанных.Элементы[0].Значение;

// Выполняем явное приведение к базовому типу Дата
ДатаОтчета = Дата(ЗначениеПараметра);

// Передаем переменную в COM-запрос
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ДатаОтчета);

Если требуется передать текущую дату, также сначала сохраняем ее в локальную переменную:


ТекДата = ТекущаяДата();
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ТекДата);

Способ 2. Создание объекта Граница на стороне COM-базы

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

Посмотрим на пример реализации:


ДатаОтчета = КонецДня(ТекущаяДата());

// Создаем объект Граница в удаленной базе через COM
ГраницаСОМ = БазаСОМ.NewObject("Граница", ДатаОтчета, БазаСОМ.ВидГраницы.Включая);

ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ГраницаСОМ);
РезультатПоСОМ = ЗапросСОМ.Выполнить();

Способ 3. Сериализация даты через XML-формат

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


ДатаВФорматеXML = XMLСтрока(ТекущаяДата());
ДатаСОМ = БазаСОМ.XMLЗначение(БазаСОМ.Тип("Дата"), ДатаВФорматеXML);

ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ДатаСОМ);

Архитектурные рекомендации по работе с COM-соединением

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

  1. Перенос логики в целевую базу. Вместо динамического формирования текста запроса на стороне вызывающей базы создайте в подключаемой базе экспортную функцию общего модуля (с признаками «Сервер» и «Внешнее соединение»). Передавайте в нее простые типы (строку, число, дату), выполняйте запрос внутри базы и возвращайте готовую таблицу или массив структур.
  2. Контроль разрядности и ОС. Библиотека comcntr.dll работает только в операционных системах Windows, а ее разрядность (32 или 64 бит) должна строго совпадать с разрядностью клиентского или серверного процесса 1С.
  3. Переход на HTTP-сервисы. Для современных конфигураций предпочтительнее использовать HTTP-сервисы и обмен данными в формате JSON, что полностью исключает зависимость от COM-технологии и операционной системы.
← На главную