При интеграции баз 1С через COM-соединение разработчики нередко сталкиваются с ошибкой «Ошибка обработки представления РегистрБухгалтерии... Несоответствие типов (Параметр номер 1)». Ошибка возникает при попытке выполнить запрос к виртуальной таблице остатков или оборотов, куда в качестве параметра передается дата. Разберем причины возникновения этой неполадки и подробно рассмотрим практические способы ее устранения.
Посмотрим на типичный пример исходного кода, вызывающего сбой:
ЗапросСОМ = БазаСОМ.NewObject("Запрос");
ЗапросСОМ.Текст = "ВЫБРАТЬ
| ХозрасчетныйОстатки.Субконто3.Код КАК Склад,
| ХозрасчетныйОстатки.Субконто2.Код КАК ВидТоплива,
| ХозрасчетныйОстатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОтчета, Счет = &Счет, , ) КАК ХозрасчетныйОстатки";
Счет_004_01_5 = БазаСОМ.ПланыСчетов.Хозрасчетный.НайтиПоКоду("004.01.5");
ЗапросСОМ.УстановитьПараметр("Счет", Счет_004_01_5);
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ТекущаяДата());
РезультатПоСОМ = ЗапросСОМ.Выполнить();
Проанализируем механику работы COM-соединения и платформы 1С при передаче параметров:
НастройкиКомпоновки.ПараметрыДанных.Элементы[0].Значение, значение может иметь составной тип или являться объектом СтандартныйПериод. При передаче через COM-маршалер такой объект не распознается как примитивная дата, из-за чего виртуальная таблица запроса возвращает ошибку несоответствия типов.VT_DATE. Если результат вычисляется непосредственно внутри вызова метода или содержит контекст глобальной функции текущей базы, механизм маршалинга может передать значение как объект VT_DISPATCH или строку VT_BSTR, которые запрос на принимающей стороне не может привести к дате.Самое простое и эффективное решение — принудительно привести значение к примитивному типу Дата и сохранить его в отдельную локальную переменную перед передачей в метод УстановитьПараметр.
Рассмотрим, как скорректировать код:
// Извлекаем значение из настроек СКД или внешнего источника
ЗначениеПараметра = НастройкиКомпоновки.ПараметрыДанных.Элементы[0].Значение;
// Выполняем явное приведение к базовому типу Дата
ДатаОтчета = Дата(ЗначениеПараметра);
// Передаем переменную в COM-запрос
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ДатаОтчета);
Если требуется передать текущую дату, также сначала сохраняем ее в локальную переменную:
ТекДата = ТекущаяДата();
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ТекДата);
Для корректного получения бухгалтерских или регистровых остатков на определенный момент времени часто требуется учитывать движения, сделанные в ту же секунду. В этом случае правильнее создать объект Граница непосредственно в контексте подключаемой базы через COM.
Посмотрим на пример реализации:
ДатаОтчета = КонецДня(ТекущаяДата());
// Создаем объект Граница в удаленной базе через COM
ГраницаСОМ = БазаСОМ.NewObject("Граница", ДатаОтчета, БазаСОМ.ВидГраницы.Включая);
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ГраницаСОМ);
РезультатПоСОМ = ЗапросСОМ.Выполнить();
Если между базами возникают проблемы несовместимости платформ или специфические сбои COM-маршалера, можно воспользоваться стандартным XML-преобразованием. Это гарантирует создание объекта даты в целевом контексте:
ДатаВФорматеXML = XMLСтрока(ТекущаяДата());
ДатаСОМ = БазаСОМ.XMLЗначение(БазаСОМ.Тип("Дата"), ДатаВФорматеXML);
ЗапросСОМ.УстановитьПараметр("ДатаОтчета", ДатаСОМ);
Чтобы избежать проблем с передачей типов и повысить стабильность интеграции, рекомендуем придерживаться следующих правил:
comcntr.dll работает только в операционных системах Windows, а ее разрядность (32 или 64 бит) должна строго совпадать с разрядностью клиентского или серверного процесса 1С.