При интеграции конфигураций 1С:Предприятия 7.7 и 8.x часто возникает задача: вызвать экспортную функцию в базе 1С 8 через COM-соединение (или OLE Automation) и получить результат в виде таблицы значений в коде 1С 7.7. Главное требование при этом — избежать сохранения данных во временные файлы на диске.
Разберем особенности взаимодействия двух платформ, выясним причины возможных сложностей и рассмотрим рабочие способы передачи табличных данных в оперативную память 1С 7.7.
Объект ТаблицаЗначений в 1С 8 и 1С 7.7 имеет принципиально разную внутреннюю структуру. Напрямую присвоить объект одной платформы переменной другой платформы невозможно. При вызове экспортной функции восьмерки база 1С 7.7 получает лишь ссылку на COMОбъект (или OLE-объект).
При работе с COM-объектами восьмерки из семерки необходимо учитывать следующие правила:
Для Каждого ... Из ... Цикл, а также обращение к строкам по квадратным скобкам (ТЗ[Индекс]). Обращение выполняется через методы объекта: Получить(Индекс) или Колонки.Получить(Индекс).Строка, Число, Дата или Булево.Рассмотрим стандартный вариант для небольших таблиц. В 1С 7.7 создаем локальный объект ТаблицаЗначений, считываем структуру колонок из COM-объекта восьмерки и в цикле переносим значения строк.
// В 1С 7.7 подключаемся к 1С 8 и вызываем функцию
База8 = СоздатьОбъект("V83.COMConnector");
Соединение8 = База8.Connect("Srvr=""Server1C"";Ref=""Base8"";Usr=""User"";Pwd=""Pass"";");
// Получаем COM-объект ТаблицаЗначений из экспортной функции
ТЗ8 = Соединение8.МойЭкспортныйМодуль.ПолучитьТаблицуДанных();
// Создаем локальную таблицу значений в 1С 7.7
ТЗ7 = СоздатьОбъект("ТаблицаЗначений");
// Переносим колонки (в 1С 8 индекс колонок начинается с 0)
КолКолонок = ТЗ8.Колонки.Количество();
Для к = 0 По КолКолонок - 1 Цикл
Колонка8 = ТЗ8.Колонки.Получить(к);
ТЗ7.НоваяКолонка(Колонка8.Имя);
КонецЦикла;
// Переносим строки
КолСтрок = ТЗ8.Количество();
Для с = 0 По КолСтрок - 1 Цикл
Строка8 = ТЗ8.Получить(с);
ТЗ7.НоваяСтрока();
Для к = 0 По КолКолонок - 1 Цикл
ИмяКолонки = ТЗ8.Колонки.Получить(к).Имя;
ЗначениеЯчейки = Строка8.Получить(к);
ТЗ7.УстановитьЗначение(ТЗ7.НомерСтроки, ИмяКолонки, ЗначениеЯчейки);
КонецЦикла;
КонецЦикла;
Если таблица содержит тысячи строк, прямой перебор COM-ячеек будет работать долго. Оптимальное решение без создания файлов — сформировать в функции 1С 8 одну текстовую строку с разделителями колонок (например, символ табуляции) и строк (символ перевода строки), передать ее в 1С 7.7 за один COM-вызов и разобрать в локальную таблицу значений.
Посмотрим на реализацию функции на стороне 1С 8:
// Экспортная функция в общем модуле 1С 8
Функция ПолучитьТаблицуТекстом() Экспорт
ТЗ = СформироватьДанные(); // Ваша таблица значений
ТекстовыйБуфер = "";
Для Каждого Стр Из ТЗ Цикл
СтрокаТекста = "";
Для Каждого Кол Из ТЗ.Колонки Цикл
СтрокаТекста = СтрокаТекста + ?(СтрокаТекста = "", "", Символы.Таб) + Строка(Стр[Кол.Имя]);
КонецЦикла;
ТекстовыйБуфер = ТекстовыйБуфер + ?(ТекстовыйБуфер = "", "", Символы.ПС) + СтрокаТекста;
КонецЦикла;
Возврат ТекстовыйБуфер;
КонецФункции
Теперь разберем, как быстро прочитать полученный текст в 1С 7.7:
// В 1С 7.7 принимаем строку
ТекстДанных = Соединение8.МойЭкспортныйМодуль.ПолучитьТаблицуТекстом();
ТЗ7 = СоздатьОбъект("ТаблицаЗначений");
ТЗ7.НоваяКолонка("Код");
ТЗ7.НоваяКолонка("Наименование");
ТЗ7.НоваяКолонка("Сумма");
ВсегоСтрок = СтрКоличествоСтрок(ТекстДанных);
Для Ном = 1 По ВсегоСтрок Цикл
ТекущаяСтрока = СтрПолучитьСтроку(ТекстДанных, Ном);
Если ПустаяСтрока(ТекущаяСтрока) = 0 Тогда
ТЗ7.НоваяСтрока();
// Разбираем строку по табуляции
СтрПозиция = Найти(ТекущаяСтрока, Симв(9));
ТЗ7.Код = Лев(ТекущаяСтрока, СтрПозиция - 1);
ТекущаяСтрока = Сред(ТекущаяСтрока, СтрПозиция + 1);
СтрПозиция = Найти(ТекущаяСтрока, Симв(9));
ТЗ7.Наименование = Лев(ТекущаяСтрока, СтрПозиция - 1);
ТЗ7.Сумма = Число(Сред(ТекущаяСтрока, СтрПозиция + 1));
КонецЕсли;
КонецЦикла;
Еще один способ — создание отсоединенного набора данных ADODB.Recordset. Обе платформы поддерживают работу с COM-объектами Windows Data Access Components (ADO).
Новый COMОбъект("ADODB.Recordset").Fields.Append описываются поля таблицы и заполняются строки.MoveNext().Для небольших таблиц значений (до нескольких сотен строк) достаточно использовать прямой перебор строк COM-объекта через методы Колонки.Получить(к) и Получить(с). Для больших объемов данных рекомендуется возвращать сериализованную строку (CSV/TSV или XML в памяти), что позволяет свести передачу данных к одному быстрому COM-обращению.