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

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

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

Анализ причины ошибки: контекст выполнения

Разберем ситуацию, которая возникла у автора темы. Код в 1С 8.3 ищет элемент справочника через объект в7 (COM-соединение), получает ссылку на него в переменную Авто, а затем пытается выполнить текстовый запрос. Ошибка Запрос[14] : Ошибка в выражении 'Авто' возникает потому, что встроенный язык запросов 1С 7.7 не является объектно-ориентированным в том смысле, к которому мы привыкли в 8.3.

Когда мы передаем строку запроса в метод выполнить(), «движок» запросов 1С 7.7 пытается разрешить имена переменных, указанных в секции Условие. Однако переменная Авто существует только в оперативной памяти процесса 1С 8.3 (как COM-объект) или в локальном контексте программного кода, но она абсолютно невидима для внутреннего парсера запросов 7.7. Запрос "не знает", что такое Авто, так как эта переменная не является реквизитом документа, переменной глобального модуля или атрибутом формы в контексте базы 7.7.

Способ 1. Использование глобальных переменных базы 7.7

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

Для реализации этого метода выполним следующие шаги:

  1. В конфигураторе базы 1С 7.7 откроем Глобальный модуль.
  2. В самой верхней части модуля (до начала процедур и функций) добавим объявление переменной:

Перем глПараметрЗапроса Экспорт;

  1. Теперь в коде 1С 8.3 перед вызовом запроса присвоим этой переменной наш объект:

// Находим объект в 7.7
АвтомобильСОМ = в7.CreateObject("Справочник.Номенклатура");
Если АвтомобильСОМ.НайтиПоРеквизиту("ВИН", Автомобиль.VIN, 1) = 1 Тогда
    Объект77 = АвтомобильСОМ.ТекущийЭлемент();
    
    // Передаем объект в глобальную переменную базы 7.7
    в7.глПараметрЗапроса = Объект77;
    
    // Теперь в тексте запроса используем ИМЯ глобальной переменной
    ТекстЗапроса = "
    |//{{ЗАПРОС(Сформировать)
    |...
    |Условие(Автомобиль = глПараметрЗапроса);
    |... ";
    
    Запрос = в7.CreateObject("Запрос");
    Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
        // Обработка результатов
    КонецЕсли;
КонецЕсли;

Способ 2. Подстановка строковых представлений (Код или VIN)

Если вносить изменения в конфигурацию 7.7 (править Глобальный модуль) нельзя, воспользуемся методом динамического формирования текста запроса. Вместо передачи самого объекта как ссылки, мы можем внедрить в текст условия конкретное строковое или числовое значение. Выясним, как это сделать на примере реквизита ВИН или Код.

Посмотрим на пример формирования строки в 1С 8.3:


// ВАЖНО: В 7.7 строковые литералы в запросе должны быть в кавычках.
// Чтобы в 8.3 получить кавычку внутри строки, используем двойные или тройные кавычки.
ЗначениеВИН = Автомобиль.VIN; 
ТекстЗапроса = ТекстЗапроса + "|Условие(Автомобиль.ВИН = """ + ЗначениеВИН + """);";

Важный нюанс: Чтобы условие Автомобиль.ВИН сработало, реквизит ВИН должен быть определен в самом запросе. Рассмотрим исправленный текст запроса целиком:


текстзап = "
|ОбрабатыватьДокументы все;
|Без итогов;
|ЗаказНаряд = Документ.ЗаказНаряд.ТекущийДокумент;
|Автомобиль = Документ.ЗаказНаряд.Автомобиль;
|ВИН_Авто = Документ.ЗаказНаряд.Автомобиль.ВИН; // Вытаскиваем реквизит для условия
|Группировка ЗаказНаряд;
|Условие(ВИН_Авто = """ + Автомобиль.VIN + """);"; 

Обратите внимание, что обращение Автомобиль.ВИН в секции Условие может работать медленно, если ВИН не является индексированным реквизитом. Также помните, что в 1С 7.7 в запросах нельзя обращаться к периодическим реквизитам через точку напрямую.

Способ 3. Сравнение через внутренний идентификатор (ID)

Проанализируем еще один подход, который не требует правки конфигурации 7.7. Каждая ссылка в 1С 7.7 имеет уникальное внутреннее строковое представление. Мы можем получить его в 8.3 и сравнить внутри запроса, используя встроенную функцию ЗначениеВСтрокуВнутр.

Разберем пример реализации:


// Получаем внутренний ID найденного автомобиля
СтрID = в7.EvalExpr("ЗначениеВСтрокуВнутр(глПараметрЗапроса)"); 
// Или напрямую из объекта, если он получен
СтрID = в7.ЗначениеВСтрокуВнутр(Авто);

// В тексте запроса используем функцию преобразования
текстзап = текстзап + "|Условие(ЗначениеВСтрокуВнутр(Автомобиль) = """ + СтрID + """);";

Этот метод универсален, так как он работает со ссылками на объекты напрямую, не полагаясь на уникальность кодов или артикулов. Однако он может быть менее производительным на огромных выборках документов.

Особенности работы с типами данных COM

Выясним еще несколько важных моментов, которые помогут избежать ошибок при интеграции:

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

← На главную