Почему не выполняется запрос по документам в 1С 7.7 при подключении через OLE?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Анализ проблемы: почему запрос падает через OLE

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

Выясним причину на примере типичного некорректного кода:


ТекстЗапроса = 
"//{{ЗАПРОС(Сформировать)
|Период с ВыбНачПериода по ВыбКонПериода;
|ОбрабатыватьДокументы все;
|Док = Документ.РасходнаяНакладная.ТекущийДокумент;
|Группировка Док без групп;
|Условие(Док.ВыгрузитьВ83 = 1);
|"//}}ЗАПРОС
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Возврат \"Ошибка запроса\";
КонецЕсли;

Шаг 1: Использование агрегатных функций

В платформе 1С 7.7 существует критически важная особенность: если в запросе используется группировка (Grouping), но не указана ни одна агрегатная функция (Сумма, Счетчик, Минимум и т.д.), движок запросов может не инициализировать выборку корректно. При работе через OLE это практически всегда приводит к ошибке Выполнить() = 0.

Разберем, как это исправить. Нам необходимо добавить техническую функцию, которая не повлияет на логику, но «заставит» запрос работать. Оптимальным вариантом является функция Счетчик.

Правильный вариант текста запроса:


|Док = Документ.РасходнаяНакладная.ТекущийДокумент;
|Функция КолДок = Счетчик(); // Обязательная добавка для стабильности
|Группировка Док;

Шаг 2: Переход на английскую нотацию

Проанализируем влияние языковых настроек. При вызове 1С 7.7 как OLE-сервера, интерпретатор команд может некорректно обрабатывать русские ключевые слова в тексте запроса (такие как Период, Условие, Группировка), если региональные настройки вызывающей и вызываемой системы различаются. Использование английских аналогов гарантирует понимание команды на уровне ядра системы.

Рекомендуем заменить ключевые слова на следующие:

  1. Period вместо Период
  2. Condition вместо Условие
  3. Grouping вместо Группировка
  4. All вместо Все

Шаг 3: Проблема локальных переменных и дат

В обычном модуле 1С 7.7 запрос легко «видит» переменные ВыбНачПериода и ВыбКонПериода. Однако в OLE-контексте связь с областью видимости локальных переменных часто теряется. Рассмотрим способ решения этой проблемы — вклеивание значений дат непосредственно в строку запроса.

Вместо передачи имени переменной, используем функцию Формат() для преобразования даты в строку вида ДД.ММ.ГГГГ (или формат, принятый в вашей базе), чтобы запрос получил готовое значение.

Пример формирования текста:


ТекстЗапроса = "
|Period from " + Формат(ВыбНачПериода, "Д ДДММГГГГ") + " to " + Формат(ВыбКонПериода, "Д ДДММГГГГ") + ";
|ОбрабатыватьДокументы все;
|Док = Документ.РасходнаяНакладная.ТекущийДокумент;
|Grouping Док;
|Condition(Док.ВыгрузитьВ83 = 1);";

Шаг 4: Уникальность имен переменных в запросе

Посмотрим на ситуацию, описанную в сообщениях форума: если вы выполняете несколько запросов последовательно, используя одни и те же имена переменных внутри текста (например, Док), 1С 7.7 может кэшировать структуру запроса некорректно. Это приводит к тому, что первый запрос проходит, а второй — падает с ошибкой.

Рекомендация: Для каждого типа документа в разных функциях используйте уникальные имена переменных внутри текста запроса. Например, ДокРН для расходных накладных и ДокПН для приходных. Также перед созданием нового объекта Запрос желательно явно обнулять переменную: Запрос = 0; Запрос = СоздатьОбъект("Запрос");.

Шаг 5: Правильный возврат данных (Критично для OLE)

Рассмотрим самую серьезную архитектурную ошибку: возврат самого объекта Запрос из функции через OLE (как показано в сообщении №11 форума). Объект Запрос в 1С 7.7 является сложным внутренним объектом, который плохо сериализуется для передачи во внешние системы.

При попытке вызвать методы Группировка() или ПолучитьПараметр() у такого объекта на стороне 1С 8.3, вы с большой вероятностью получите ошибку доступа к памяти или разрыв соединения.

Единственно верный способ передачи данных:

  1. Выполнить запрос внутри 7.7.
  2. Создать объект ТаблицаЗначений.
  3. Выгрузить результат запроса в эту таблицу методом Запрос.Выгрузить(ТЗ, 0, 0);.
  4. Возвращать именно объект ТаблицаЗначений.

Таблицы значений 7.7 прекрасно передаются через COM-интерфейс и позволяют легко перебирать строки во внешней системе.

Итоговый пример стабильной функции

Проанализируем и соберем все рекомендации в один надежный пример кода, который будет вызываться из 1С 8.3:


Функция глПолучитьДанныеДокументов(ДатаНач, ДатаКон) Экспорт
    Перем Запрос, ТекстЗапроса, ТЗРезультат;
    
    Запрос = СоздатьОбъект("Запрос");
    
    // Используем английскую нотацию и вклеиваем даты
    ТекстЗапроса = "
    |Period from " + Формат(ДатаНач, "Д ДДММГГГГ") + " to " + Формат(ДатаКон, "Д ДДММГГГГ") + ";
    |ОбрабатыватьДокументы все;
    |ДокРН = Документ.РасходнаяНакладная.ТекущийДокумент;
    |СтатусВыгрузки = Документ.РасходнаяНакладная.ВыгрузитьВ83;
    |Функция СчетчикДок = Счетчик(ДокРН);
    |Grouping ДокРН;
    |Condition(СтатусВыгрузки = 1);";
    
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
        // Записываем лог или выводим предупреждение
        Возврат "Ошибка"; 
    КонецЕсли;
    
    // Выгружаем в таблицу значений перед возвратом
    ТЗРезультат = СоздатьОбъект("ТаблицаЗначений");
    Запрос.Выгрузить(ТЗРезультат, 0, 0);
    
    Возврат ТЗРезультат;
КонецФункции

Соблюдение этих правил — агрегатные функции, английская нотация, уникальные имена переменных и возврат через Таблицу Значений — позволит вам забыть о «мистических» ошибках запросов в 1С 7.7 при интеграции с современными системами.

← На главную