Как по COM-соединению из 1С 8.3 получить остаток из регистра 1С 7.7 на определенную дату?

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

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

Проблема прямого обхода итогов регистра

Проанализируем базовый подход, который часто используют разработчики при попытке получить данные из 1С 7.7:


РегТовары = База.CreateObject("Регистр.ОстаткиТМЦ");
РегТовары.ВыбратьИтоги();

Пока РегТовары.ПолучитьИтог() = 1 Цикл
    Код = РегТовары.Номенклатура.Код;
КонецЦикла;

Данный код обращается к текущим итогам регистра. Метод ВыбратьИтоги() без предварительной настройки рассчитывает данные на текущую точку актуальности базы 1С 7.7. Получить остаток на произвольную дату таким способом без дополнительных команд нельзя.

Способ 1. Использование объекта Запрос в 1С 7.7

Для получения срезных данных на дату в 1С 7.7 используется механизм запросов. Однако при вызове метода CreateObject("Запрос") через COM-соединение нужно учитывать важную особенность языка запросов 1С 7.7: переменные контекста 1С 8.3 не видны внутри текста запроса 1С 7.7.

Выясним причину ошибки, с которой часто сталкиваются разработчики:


ДатаНач = Дата(2017, 11, 25); 
ДатаКон = Дата(2017, 11, 30);
Запрос = База.CreateObject("Запрос");

// Ошибка! 1С 7.7 не знает про переменные ДатаНач и ДатаКон из 1С 8.3
ТекстЗапроса = "
|Период С ДатаНач По ДатаКон;
|Номенклатура = Регистр.ОстаткиТМЦ.Номенклатура;
|Количество = Регистр.ОстаткиТМЦ.Количество; 
|Группировка Номенклатура;
|Функция ОстатокНоменклатура = КонОст(Количество);
|";

Запрос.Выполнить(ТекстЗапроса); 

При выполнении этого кода система выдаст ошибку: Ошибка в выражении 'ДатаНач'. В языке запросов 1С 7.7 даты должны передаваться строго как строковые литералы в одинарных кавычках в формате 'ДД.ММ.ГГГГ'.

Сформируем запрос правильно, динамически подставляя дату из 1С 8.3:


ИскомаяДата = Дата(2017, 11, 30);
СтрДата = Формат(ИскомаяДата, "ДФ=dd.MM.yyyy");

Запрос = База.CreateObject("Запрос");

ТекстЗапроса = "
|Период С '" + СтрДата + "' По '" + СтрДата + "';
|Номенклатура = Регистр.ОстаткиТМЦ.Номенклатура;
|Количество = Регистр.ОстаткиТМЦ.Количество; 
|Группировка Номенклатура без групп;
|Функция ОстатокНоменклатура = КонОст(Количество);
|";

Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
    Пока Запрос.Группировка("Номенклатура") = 1 Цикл
        Сообщить(Строка(Запрос.Номенклатура.Наименование) + ": " + Запрос.ОстатокНоменклатура);
    КонецЦикла;
КонецЕсли;

Выгрузить результат работы запроса можно не только итерационным обходом группировок, но и в таблицу значений с помощью метода Запрос.Выгрузить(Таблица).

Способ 2. Временный расчет регистров (без запроса)

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

Разберем по шагам, как выполнить временный расчет:

  1. Включаем режим временного расчета вызовом метода ВременныйРасчет(1) для объекта регистра.
  2. Вызываем метод РассчитатьРегистрыПо(ИскомаяДата) (для расчета на конец дня) или РассчитатьРегистрыНа(ИскомаяДата) (на начало дня) у главного объекта базы.
  3. Используем стандартный выбор итогов — теперь методы СводныйОстаток() и ПолучитьИтог() будут возвращать рассчитанные данные на указанный момент времени.

Посмотрим на пример реализации временного расчета через COM:


ИскомаяДата = Дата(2017, 11, 30);

// Инициализируем объект регистра
РегТовары = База.CreateObject("Регистр.ОстаткиТМЦ");

// Включаем режим временного расчета
РегТовары.ВременныйРасчет(1);

// Выполняем расчет регистров на конец указанной даты
База.РассчитатьРегистрыПо(ИскомаяДата);

// Выбираем итоги на рассчитанную дату
РегТовары.ВыбратьИтоги();
Пока РегТовары.ПолучитьИтог() = 1 Цикл
    КодТовара = РегТовары.Номенклатура.Код;
    Остаток = РегТовары.Количество;
КонецЦикла;

Особенности производительности и разрядности

При интеграции 1С 8.3 и 1С 7.7 необходимо учитывать следующие технические ограничения:

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

2. Разрядность процессов (32 bit / 64 bit): COM-сервер 1С 7.7 является исключительно 32-разрядным (V77.Application или V77S.Application). Если сервер 1С 8.3 запущен в 64-битном режиме, прямое подключение вызвать ошибку. В таком случае COM-соединение следует выполнять либо на клиентском 32-битном сеансе, либо настраивать запуск 32-битного COM-сервера в Windows через приложение DllHost (служба компонент COM+).

← На главную