При переносе интеграционных алгоритмов и механизмов сверки данных между версиями платформы часто возникает задача заменить привычный для 1С 7.7 код работы с регистрами на современные механизмы платформы 1С 8. В семерке получение остатков строилось на методах объекта Регистры (таких как ВременныйРасчет(), РассчитатьРегистрыНа() и фильтрах измерений), тогда как в восьмерке этот функционал полностью перенесен в механизм запросов к виртуальным таблицам регистров накопления.
Разберем по шагам, как правильно составить запрос к остаткам в 1С 8, как вызвать его из внешней базы 1С 7.7 по COM-технологии и как избежать типичных синтаксических ошибок платформы 7.7.
Выясним причину, почему в платформе 8 нельзя использовать функции прямого временного расчета: архитектура регистров накопления v8 опирается на хранение итогов и автоматическое построение срезов на уровне СУБД. Для получения свернутых остатков номенклатуры на заданную дату с отбором по складу используется виртуальная таблица Остатки регистра накопления.
Посмотрим на пример базового запроса, который выбирает остатки в 1С 8:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТовОстатки.Номенклатура КАК Номенклатура,
| ТовОстатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ТекДата, Склад = &ВыбСклад) КАК ТовОстатки";
Запрос.УстановитьПараметр("ТекДата", ТекущаяДата());
Запрос.УстановитьПараметр("ВыбСклад", СкладСсылка);
Результат = Запрос.Выполнить();
Обратите внимание на важные детали при построении такого запроса:
СГРУППИРОВАТЬ ПО здесь не требуется, так как виртуальная таблица Остатки по умолчанию возвращает данные, свернутые по всем указанным измерениям.КоличествоОстаток вместо Количество).Остатки(&Дата, ...), а не через блок ГДЕ, чтобы СУБД фильтровала записи до расчета итогов.Когда мы переносим выполнение этого запроса в модуль 1С 7.7 через COM-соединение, разработчики часто сталкиваются с ошибкой «Переменная не определена». Проанализируем причины этой проблемы и различия в синтаксисе платформ:
Новый: В синтаксисе встроенного языка 1С 7.7 оператор Новый отсутствует. Любые типы данных базы-источника 1С 8 (включая Запрос, ОписаниеТипов, Массив) необходимо создавать через метод COM-соединения: БазаИсточник.NewObject("ИмяТипа").Перем: В 1С 7.7 директива объявления локальных переменных Перем обязана располагаться строго в первой строке процедуры или функции до любых исполняемых команд. Синтаксические ошибки выше по коду приводят к сбою парсера и сообщениям о неопределенности переменных.ТаблицаЗначений, созданный в 1С 8 через NewObject, не является родным для 1С 7.7. Попытка вызвать у него методы семерки приведет к исключению. Правильный путь — создать локальную таблицу 1С 7.7 через СоздатьОбъект("ТаблицаЗначений") и заполнить ее данными в цикле обхода выборки.V83.COMConnector вместо V83.Application, так как он не инициализирует тяжелый графический интерфейс клиента. Подключение выполняется методом Connect().Рассмотрим законченный пример функции для 1С 7.7, демонстрирующий корректное подключение, выполнение запроса и перегрузку остатков в локальную таблицу значений:
Функция ПолучитьОстаткиИзБазы8(ПутьКБазе, Пользователь, Пароль, ДатаОстатков)
Перем База8, Соединение, Запрос8, Выборка8, ТЗРезультат, СтрокаПодключения;
ТЗРезультат = СоздатьОбъект("ТаблицаЗначений");
ТЗРезультат.НоваяКолонка("Товар", "Строка");
ТЗРезультат.НоваяКолонка("ОстатокТовара", "Число", 15, 3);
Попытка
База8 = СоздатьОбъект("V83.COMConnector");
Исключение
Сообщить("Не удалось создать объект V83.COMConnector. Проверьте регистрацию comcntr.dll", "!");
Возврат ТЗРезультат;
КонецПопытки;
СтрокаПодключения = "File=""" + СокрЛП(ПутьКБазе) + """;Usr=""" + СокрЛП(Пользователь) + """;Pwd=""" + СокрЛП(Пароль) + """;";
Попытка
Соединение = База8.Connect(СтрокаПодключения);
Исключение
Сообщить("Ошибка подключения к базе 1С 8: " + ОписаниеОшибки(), "!");
Возврат ТЗРезультат;
КонецПопытки;
Запрос8 = Соединение.NewObject("Запрос");
Запрос8.Текст =
"ВЫБРАТЬ
| ТовОстатки.Номенклатура.Наименование КАК ТоварНаименование,
| ТовОстатки.КоличествоОстаток КАК ОстатокТовара
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков, ) КАК ТовОстатки";
// Передаем дату с учетом времени или текущую дату базы-источника
Запрос8.УстановитьПараметр("ДатаОстатков", Соединение.ТекущаяДата());
Выборка8 = Запрос8.Выполнить().Выбрать();
Пока Выборка8.Следующий() = 1 Цикл
ТЗРезультат.НоваяСтрока();
// Считываем примитивные типы (строки, числа) для снижения сетевых вызовов COM
ТЗРезультат.Товар = Выборка8.ТоварНаименование;
ТЗРезультат.ОстатокТовара = Выборка8.ОстатокТовара;
КонецЦикла;
// Обязательно освобождаем память COM-соединения
Соединение = 0;
База8 = 0;
Возврат ТЗРезультат;
КонецФункции
Разберем практические нюансы, которые влияют на надежность работы такой интеграции:
Номенклатура.Наименование), код или артикул. Если обращаться к полям ссылки в цикле 7.7 (например, Выборка8.Номенклатура.Наименование), каждое обращение порождает межпроцессный COM-вызов, что в сотни раз замедляет чтение данных.V83.COMConnector в операционной системе обязательно должна быть зарегистрирована 32-битная библиотека comcntr.dll. Если база 1С 8 развернута на 64-разрядном сервере без 32-битного клиента, прямое подключение вызовет системную ошибку интерфейса.Соединение = 0), иначе процесс фонового подключения продолжает занимать оперативную память и клиентскую лицензию платформы 8.