Переход с платформы 1С 8.х на 1С 7.7 часто вызывает у разработчиков трудности, связанные с кардинально иным подходом к написанию запросов. В седьмой версии используется так называемый «Черный запрос», имеющий свой специфический синтаксис и логику выполнения. В этой статье мы подробно разберем, как правильно извлекать данные из документов, настраивать фильтрацию по справочникам и решать проблемы, возникающие при обращении к базе 1С 7.7 из внешних приложений через OLE.
В отличие от 1С 8.x, где запрос пишется на языке, близком к SQL, запрос в 1С 7.7 — это текстовое описание выборки, которое обрабатывается внутренним движком платформы. Рассмотрим структуру типичного запроса. Проанализируем ситуацию: нам нужно найти все документы СправкаСчет, в которых фигурирует определенный автомобиль.
Первая и самая частая ошибка новичков — попытка выполнить запрос до того, как определены параметры для условия. Выясним причину: в 1С 7.7 текст запроса компилируется в момент вызова метода Выполнить(). Если переменная, используемая в Условие(), не определена или не содержит нужного объекта на этот момент, запрос вернет пустой результат.
Разберем правильный алгоритм действий на примере:
Процедура Сформировать()
Перем Запрос, ТекстЗапроса, СпрАвто, ТекАвто;
// Сначала находим объект, который будет параметром фильтрации
СпрАвто = СоздатьОбъект("Справочник.Автомобили");
Если СпрАвто.НайтиПоКоду("XTT316300J1017380") = 0 Тогда
Сообщить("Автомобиль не найден по указанному коду!");
Возврат;
КонецЕсли;
// Получаем конкретный элемент справочника
ТекАвто = СпрАвто.ТекущийЭлемент();
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с '01.01.2017' по '31.12.2018';
|Док = Документ.СправкаСчет.ТекущийДокумент;
|Авто = Документ.СправкаСчет.Автомобиль;
|Группировка Док;
|Условие(Авто = ТекАвто);
|"//}}ЗАПРОС
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;
КонецПроцедуры
В 1С 7.7 метод Запрос.Группировка() выполняет роль, аналогичную методу Выборка.Следующий() в 1С 8. Однако здесь есть критический нюанс. Если мы хотим получить список документов, мы обязаны указать группировку по самому документу. Рассмотрим подробнее: если вы укажете Группировка Автомобиль;, запрос «схлопнет» все найденные документы в одну строку для каждого автомобиля. В итоге в цикле вы увидите только первый попавшийся документ из выборки.
Важные правила группировки:
|Группировка Док; (где Док — это ссылка на ТекущийДокумент).Пока Запрос.Группировка("Док") = 1 Цикл.без групп.Ситуация усложняется, когда мы пишем код в 1С 8.3, подключаемся к 1С 7.7 через COM-соединение и пытаемся выполнить там запрос. Основная проблема заключается в передаче параметров. Рассмотрим пример: переменная ТекАвто, созданная в контексте 1С 8, абсолютно неизвестна внутреннему обработчику запросов 1С 7.7. Попытка написать Условие(Автомобиль = ТекАвто) внутри строки текста запроса приведет к ошибке «Ошибка в выражении ТекАвто».
Проанализируем два способа решения этой задачи:
Способ 1: Использование строковых идентификаторов (VIN, Код, Артикул). Это самый надежный метод. Мы не передаем ссылку на объект, а передаем строку, которую запрос 1С 7.7 может сравнить самостоятельно.
// Код в 1С 8.3
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с '01.01.2017' по '31.12.2018';
|Док = Документ.СправкаСчет.ТекущийДокумент;
|ВинКод = Документ.СправкаСчет.Автомобиль.Код;
|Группировка Док;
|Условие(СокрЛП(ВинКод) = """ + СокрЛП(НужныйВин) + """);
|""//}}ЗАПРОС
;
Обратите внимание на использование функции СокрЛП внутри запроса. Это позволяет избежать проблем с лишними пробелами, которые часто встречаются в строковых реквизитах 1С 7.7.
Способ 2: Передача через глобальные переменные OLE-базы. Если необходимо фильтровать именно по ссылке, можно предварительно найти объект в базе 7.7 и присвоить его какой-либо переменной, доступной в глобальном контексте (например, в заголовке какой-нибудь открытой формы или через специальные функции в Глобальном модуле), но это гораздо сложнее в реализации.
Разберем еще несколько важных моментов, которые помогут вам при работе с запросами в 1С 7.7:
Запрос.Выполнить().Выгрузить(), то в 1С 7.7 метод Выгрузить() требует заранее созданный объект. Например: ТЗ = СоздатьОбъект("ТаблицаЗначений"); Запрос.Выгрузить(ТЗ);.СокрЛП() или Найти() внутри Условие() в SQL-версии 1С 7.7 может привести к существенному замедлению, так как фильтрация будет происходить на стороне клиента, а не сервера. По возможности старайтесь сравнивать прямые значения.ТекущийДокумент. Это гарантирует получение ссылки на объект, а не просто доступ к его реквизитам.Подведем итог. Для успешного получения данных из 1С 7.7 запросом необходимо строго соблюдать последовательность: поиск объектов-фильтров, определение текста запроса с обязательной группировкой по нужным разрезам (документам) и корректный обход результатов через Группировка(). При работе через OLE отдавайте предпочтение строковым фильтрам (кодам), внедряя их значения прямо в текст запроса с помощью конкатенации.