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

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

Перенос данных между «семеркой» и «восьмеркой» через COM-соединение — задача классическая, но полная подводных камней. Часто программисты сталкиваются с тем, что привычные методы передачи объектов не работают, а серверная версия 1С 8.3 наотрез отказывается видеть 32-битную библиотеку 7.7. В этой статье мы подробно разберем, как получить данные из таблицы значений 7.7, почему нельзя использовать внутренние строки и как настроить сервер 1С для стабильной работы.

Проблема передачи таблицы значений через COM

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

Выясним причину: методы ValueToStringInternal в 7.7 и 8.3 формируют строки в абсолютно разных внутренних форматах. Они несовместимы. Поскольку ТЗ является сложным (непримитивным) типом данных, она передается через COM не как копия данных, а как ссылка на объект в памяти «семерки».

Решение 1: Обход таблицы значений в цикле

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


// 1. Создаем соединение
V77 = Новый COMОбъект("V77.Application");
Открыто = V77.Initialize(V77.RMTrade, "/d""C:\Base77"" /nAdmin", "NO_SPLASH_SHOW");

Если Открыто Тогда
    // 2. Вызываем функцию из глобального модуля 7.7, возвращающую ТЗ
    тзИзКлюшек = V77.глПолучитьРезультатЗапросаДля83();
    
    // 3. Создаем пустую таблицу значений на стороне 8.3
    Таблица83 = Новый ТаблицаЗначений;
    Таблица83.Колонки.Добавить("НоменклатураНаименование");
    Таблица83.Колонки.Добавить("Количество");

    // 4. Используем методы 7.7 для обхода строк
    тзИзКлюшек.ВыбратьСтроки();
    Пока тзИзКлюшек.ПолучитьСтроку() = 1 Цикл
        НоваяСтрока = Таблица83.Добавить();
        
        // Важно: получаем примитивные значения (строки, числа)
        // Если обратиться к тзИзКлюшек.Номенклатура, получим COMОбъект (ссылку)
        НоваяСтрока.НоменклатураНаименование = тзИзКлюшек.Номенклатура.Наименование;
        НоваяСтрока.Количество = тзИзКлюшек.Количество;
    КонецЦикла;
КонецЕсли;

Проанализируем этот код: мы используем методы ВыбратьСтроки() и ПолучитьСтроку(), которые принадлежат объекту 1С 7.7. Это позволяет нам итерироваться по данным, не пытаясь конвертировать всю таблицу целиком.

Оптимизация: работа со ссылочными типами

Как мы заметили, обращение через точку к реквизитам справочников (например, тзИзКлюшек.Номенклатура.Наименование) на стороне 8.3 порождает дополнительный COM-вызов. Если в таблице тысячи строк, производительность упадет в десятки раз.

Рекомендуемая стратегия: разыменовывайте данные на стороне 7.7. Подготовьте таблицу значений в «семерке» так, чтобы в ее колонках уже лежали готовые строки, числа и даты. Вместо объекта «Номенклатура» запишите в колонку сразу Номенклатура.Наименование или Номенклатура.Код.

Решение 2: Передача данных через XML (высокая скорость)

Если данных очень много, перебор строк через COM станет узким местом. В этом случае лучше сериализовать таблицу в строку. Рассмотрим вариант с использованием XML:

  1. На стороне 7.7 с помощью компоненты v7plus.dll или простым перебором сформируйте XML-строку из данных ТЗ.
  2. Передайте эту строку в 8.3 как обычный тип Строка.
  3. В 8.3 используйте объект ЧтениеXML для моментальной загрузки данных в локальную таблицу значений.

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

Настройка 64-битного сервера: COM+ и разрядность

Часто разработка ведется на файловой базе (32-битный клиент), где код Новый COMОбъект("V77.Application") работает идеально. Но при переносе на клиент-серверный вариант (64-битный сервер 1С) возникает ошибка или пустой результат.

Причина ситуации: 1С 7.7 — это 32-битное приложение. 64-битный процесс сервера 1С не может напрямую загрузить 32-битную DLL «семерки».

Чтобы побороть эту проблему, необходимо использовать «Службы компонентов» Windows (COM+):

  1. Откройте «Панель управления» -> «Администрирование» -> «Службы компонентов».
  2. Перейдите в «Компьютеры» -> «Мой компьютер» -> «Приложения COM+».
  3. Создайте новое приложение (пустое), назовите его, например, 1C77_COM.
  4. В свойствах приложения на вкладке «Активация» выберите «Процесс сервера».
  5. На вкладке «Удостоверение» укажите пользователя (желательно того, от имени которого работает сервер 1С, и у которого есть права на папку с базой 7.7).
  6. В ветке созданного приложения перейдите в «Компоненты» и добавьте новый компонент. Выберите «Импорт уже зарегистрированных компонентов» и найдите в списке V77.Application.

После этой настройки Windows будет запускать 1С 7.7 в отдельном процессе dllhost.exe, который послужит мостом между 64-битным сервером и 32-битным COM-объектом.

Ошибки метода Initialize

Если выполнение кода падает на строке V77.Initialize(...), проанализируем следующие моменты:

Важный совет по очистке памяти: После завершения работы с COM-объектом обязательно уничтожайте соединение. В «восьмерке» это делается присвоением переменной значения Неопределено:


V77 = Неопределено;
// Желательно также вызвать принудительный сбор мусора
СредстваПлатформы.ВызватьСборМусора();

Это предотвратит накопление «зависших» процессов 1cv77.exe в памяти сервера, которые могут привести к утечке ресурсов и нестабильной работе всей системы.

← На главную