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

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

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

Анализ проблемы: почему Таблица значений пустая?

Разберем типичную ситуацию. Программист выполняет запрос во внешней базе через COM-соединение, выгружает результат в переменную и пытается присвоить эту переменную свойству Значение табличного поля на форме. Код выглядит примерно так:


РезультатЗапроса = COMСоединение.NewObject("Запрос");
РезультатЗапроса.Текст = "ВЫБРАТЬ Номер, Дата ИЗ Документ.ПоступлениеТоваровИУслуг";
ТЗ_Внешняя = РезультатЗапроса.Выполнить().Выгрузить();

ЭлементыФормы.ТабличноеПоле1.Значение = ТЗ_Внешняя;
ЭлементыФормы.ТабличноеПоле1.СоздатьКолонки();

Проанализируем, что происходит «под капотом». В 1С версии 8 переменная ТЗ_Внешняя в данном случае не является объектом типа ТаблицаЗначений текущей информационной базы. Это объект типа COMObject. Несмотря на то что у него есть методы и свойства, похожие на методы таблицы значений (например, можно обращаться к строкам и колонкам), для платформы 1С это «чужеродная» структура.

Метод СоздатьКолонки(), доступный для элемента формы ТабличноеПоле, жестко ожидает, что в связанном с ним значении находится именно локальный объект ТаблицаЗначений. Поскольку типы не совпадают, визуальный компонент не может автоматически считать метаданные колонок из COM-объекта и построить интерфейс. Выясним, как обойти это ограничение.

Решение №1: Ручное построение локальной таблицы (универсальный метод)

Наиболее надежный, хотя и трудоемкий способ — это создание пустой локальной ТаблицыЗначений, программное добавление в нее колонок и последующее заполнение данными из COM-объекта в цикле. Посмотрим на пример реализации:


// 1. Создаем локальную таблицу
ТЗ_Локальная = Новый ТаблицаЗначений;
ТЗ_Локальная.Колонки.Добавить("Номер");
ТЗ_Локальная.Колонки.Добавить("Дата");
ТЗ_Локальная.Колонки.Добавить("Контрагент");

// 2. Получаем данные из COM
ТЗ_Внешняя = ЗапросИзБП.Выполнить().Выгрузить();

// 3. Переносим данные
Для Каждого СтрокаВнешняя Из ТЗ_Внешняя Цикл
    НоваяСтрока = ТЗ_Локальная.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаВнешняя);
    
    // Важно: ссылочные типы (Контрагенты, Номенклатура) 
    // придут как COMObject. Их нужно найти в текущей базе!
    НоваяСтрока.Контрагент = НайтиКонтрагентаПоИНН(СтрокаВнешняя.ИНН_Контрагента);
КонецЦикла;

// 4. Связываем с формой
ЭлементыФормы.ТЗ_НаФорме.Значение = ТЗ_Локальная;
ЭлементыФормы.ТЗ_НаФорме.СоздатьКолонки();

Рассмотрим важный нюанс: при передаче данных через COM-соединение все ссылочные типы (документы, справочники) передаются как ссылки внешней базы. В вашей текущей базе этих ссылок не существует, и попытка напрямую присвоить их приведет к тому, что в таблице будет отображаться надпись «COM объект». Поэтому поиск объектов (по ИНН, КПП или Уникальному Идентификатору) является обязательным этапом.

Решение №2: Использование XML-сериализации (высокая производительность)

Если во внешней таблице сотни колонок и тысячи строк, перебор в цикле будет работать крайне медленно из-за постоянных обращений к COM-интерфейсу для каждой ячейки. Проанализируем более продвинутый способ — передачу всей структуры таблицы через XML-строку.

Суть метода заключается в том, чтобы на стороне внешней базы превратить таблицу в строку, передать эту строку в текущую базу и «развернуть» обратно. В этом случае 1С автоматически создаст локальную таблицу значений с правильной структурой колонок.


// На стороне текущей базы (вызываем контекст внешней базы)
СтрокаXML = COMСоединение.ЗначениеВТекстВнутр(ТЗ_Внешняя);

// Разворачиваем строку обратно в локальный объект
ТЗ_Локальная = ЗначениеИзТекстаВнутр(СтрокаXML);

// Теперь ТЗ_Локальная — это полноценная ТаблицаЗначений вашей базы
ЭлементыФормы.ТЗ_НаФорме.Значение = ТЗ_Локальная;
ЭлементыФормы.ТЗ_НаФорме.СоздатьКолонки();

Внимание: метод ЗначениеВТекстВнутр сработает только в том случае, если в таблице содержатся примитивные типы данных (числа, строки, даты, булево). Если в таблице есть ссылки на справочники, этот метод не поможет синхронизировать их с объектами вашей базы, так как ГУИДы объектов в разных базах, скорее всего, различаются.

Различие между Табличным Полем и Таблицей Значений

Часто новички путают эти два понятия. Разберем их различия, чтобы понимать, к каким методам обращаться:

  1. ТаблицаЗначений — это объект данных в памяти. У нее есть колонки, индексы и строки. Она не умеет «показывать» себя пользователю сама по себе.
  2. ТабличноеПоле — это визуальный элемент управления на форме. Он служит «окном» для отображения данных.

Когда вы пишете ЭлементыФормы.ТЗ.СоздатьКолонки(), вы даете команду визуальному элементу: «Посмотри на то, что лежит в твоем свойстве Значение, и создай визуальные столбцы, соответствующие структуре этого объекта». Если в Значение лежит COMObject, визуальный элемент не понимает его структуру и ничего не создает.

Практические советы по оптимизации поиска ссылок

Выясним, как сделать процесс заполнения таблицы максимально быстрым, если нам нужно искать ссылки (например, Контрагентов) в текущей базе:

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

← На главную