Как задать типы колонок таблицы значений при передаче в запрос через COM-соединение в 1С?

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

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

Выясним причину ошибки при работе с ТЗ через COM

Основная проблема заключается в **разделении контекстов объектов**. Объект ТаблицаЗначений, её колонки и описывающие их объекты ОписаниеТипов должны быть созданы строго в контексте внешнего COM-соединения. Если попытаться передать локально созданный объект ОписаниеТипов во внешнюю базу, платформа выдаст ошибку несоответствия типов.

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

Способ 1. Создание типов колонок через NewObject внешней базы

Для корректного задания типа колонки используем метод NewObject внешнего соединения. Описание типов задается с помощью строки с наименованием типа данных на русском или английском языке.

Рассмотрим базовый пример создания таблицы значений и типизации её колонок во внешней базе:


// Подключаемся к внешней базе
БухБД = Новый COMОбъект("V83.COMConnector");
Соединение = БухБД.Connect("Srvr=""ServerName"";Ref=""BaseName"";");

// Создаем таблицу значений в контексте внешней базы
ТаблицаТоваров = Соединение.NewObject("ТаблицаЗначений");

// Добавляем колонку со строковым типом данных
ТаблицаТоваров.Колонки.Добавить("УпрГуид", Соединение.NewObject("ОписаниеТипов", "Строка"));

// Добавляем колонку с числовым типом данных
ТаблицаТоваров.Колонки.Добавить("Количество", Соединение.NewObject("ОписаниеТипов", "Число"));

Проанализируем этот код: вызов Соединение.NewObject("ОписаниеТипов", "Строка") инстанцирует объект описания типов внутри внешней базы, что полностью исключает конфликт контекстов.

Способ 2. Задание квалификаторов для примитивных типов и ссылок

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

Разберем по шагам, как задать типы с квалификаторами и ссылочные типы:

  1. Числовой тип с точностью: создаем КвалификаторыЧисла во внешней базе и передаем их в конструктор ОписаниеТипов.
  2. Строковый тип ограниченной длины: используем КвалификаторыСтроки.
  3. Ссылочные типы метаданных: передаем полное имя типа в виде строки, например "СправочникСсылка.Номенклатура".

Посмотрим на пример кода с квалификаторами и ссылками:


// Создание числовой колонки с длиной 15 и точностью 2
КвалифЧисла = Соединение.NewObject("КвалификаторыЧисла", 15, 2);
ТипЧисло = Соединение.NewObject("ОписаниеТипов", "Число", КвалифЧисла);
ТаблицаТоваров.Колонки.Добавить("Сумма", ТипЧисло);

// Создание ссылочной колонки на справочник внешней базы
ТипНоменклатура = Соединение.NewObject("ОписаниеТипов", "СправочникСсылка.Номенклатура");
ТаблицаТоваров.Колонки.Добавить("Номенклатура", ТипНоменклатура);

Использование сформированной ТЗ в запросе внешней базы

После того как таблица значений создана и правильно типизирована, её можно передать в параметр COM-запроса. Обратите внимание, что в тексте запроса внешнюю таблицу значений необходимо помещать во временную таблицу.


ЗапросCOM = Соединение.NewObject("Запрос");
ЗапросCOM.Текст = 
    "ВЫБРАТЬ
    |	ТЗ.УпрГуид КАК УпрГуид,
    |	ТЗ.Количество КАК Количество
    |ПОМЕСТИТЬ ВТ_Товары
    |ИЗ
    |	&ПараметрТЗ КАК ТЗ";

ЗапросCOM.УстановитьПараметр("ПараметрТЗ", ТаблицаТоваров);
РезультатЗапроса = ЗапросCOM.Выполнить();

Альтернативный вариант: Передача через сериализацию XML

Если таблица значений уже сформирована в текущей базе и содержит только примитивные типы данных (строки, числа, даты, булево), чтобы не пересоздавать её вручную через COM, можно применить сериализацию в XML:


// В текущей базе сериализуем ТЗ в строку XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ЛокальнаяТЗ);
СтрокаXML = ЗаписьXML.Закрыть();

// Во внешней базе прочитываем XML и получаем ТЗ в контексте COM
ВнешняяТЗ = Соединение.СериализаторXDTO.ПрочитатьXML(
    Соединение.ФабрикаXDTO.Создать(
        Соединение.СериализаторXDTO.ПрочитатьXML(
            Соединение.ЗаписьXML.УстановитьСтроку(СтрокаXML)
        )
    )
);

При сериализации тип каждой колонки сохраняется, а объект таблицы значений создается непосредственно в контексте приемника, что также позволяет передавать его в параметры COM-запросов.

← На главную