Обмен данными между разными поколениями платформ 1С — задача, с которой до сих пор сталкиваются многие разработчики. Использование протокола OLE (COM-соединение) является классическим способом, когда 1С 8 выступает инициатором («клиентом»), а 1С 7.7 — сервером автоматизации. Однако этот метод имеет свои подводные камни, связанные со скоростью работы и стабильностью соединения. Разберем подробно, как реализовать такой обмен, проанализируем примеры кода и выясним, как ускорить процесс в несколько раз.
Прежде чем переходить к коду, проанализируем ситуацию с технической стороны. В отличие от современных версий 1С 8, где есть облегченный COMConnector, платформа 1С 7.7 при OLE-запросе запускает полноценный экземпляр приложения (процесс 1cv7s.exe). Это означает, что при каждом вызове Initialize система выполняет инициализацию конфигурации, проверку прав и загрузку программной среды. Как показывают замеры производительности, подключение может занимать от 4 до 10 секунд, что составляет до 99% времени всего обмена, если объем передаваемых данных невелик.
Рассмотрим процедуру инициализации соединения. Важно правильно сформировать строку подключения и обработать возможные ошибки (например, если база открыта монопольно или неверно указан путь).
Процедура НачатьОбменИзмененнымиОбъектами() Экспорт
Попытка
// Создаем COM-объект версии 7.7
ОбъектV77 = Новый COMОбъект("v77.Application");
Исключение
Сообщить("Не удалось создать объект v77.Application. Проверьте регистрацию COM-компоненты.");
Возврат;
КонецПопытки;
// Формируем параметры запуска: путь к базе, имя пользователя и пароль
СтрокаПодключения = "/D""" + СокрЛП("C:\Base1C\77_Base\") + """ /N""" + СокрЛП("Admin") + """ /P""""";
// Инициализация. Флаг "NO_SPLASH_SHOW" скрывает заставку 7.7
РезультатПодключения = ОбъектV77.Initialize(ОбъектV77.RMTrade, СтрокаПодключения, "NO_SPLASH_SHOW");
Если Не РезультатПодключения Тогда
Сообщить("Ошибка авторизации или база занята монопольно.");
ОбъектV77 = Неопределено;
Возврат;
КонецЕсли;
// Далее следует логика обмена
КонецПроцедуры
Важный совет: Если ваша 1С 8 установлена на 64-битном сервере, прямой вызов 32-битной 1С 7.7 через COMОбъект выдаст ошибку. В этом случае необходимо настроить 32-битное приложение в COM+ Services на сервере, чтобы обеспечить межпроцессное взаимодействие.
Чтобы не перегружать систему полной выгрузкой, целесообразно использовать в 1С 7.7 вспомогательный справочник (например, ИзмененныеОбъекты), куда записываются ссылки на объекты при их проведении или записи. Проанализируем, как эффективно прочитать этот справочник из 1С 8.
Рассмотрим распространенную ошибку: двойной проход по справочнику. Сначала разработчики часто помечают объекты флагом «Начат обмен», а вторым циклом их читают. Это замедляет работу. Выясним, как это сделать оптимальнее: объединим установку флага и чтение данных в один цикл либо используем удаление записей сразу после обработки.
ИзмененныеОбъектыОЛЕ = ОбъектV77.CreateObject("Справочник.ИзмененныеОбъекты");
ИзмененныеОбъектыОЛЕ.ВыбратьЭлементы();
Пока ИзмененныеОбъектыОЛЕ.ПолучитьЭлемент() = 1 Цикл
// Читаем тип и значение объекта
ТипОбъекта = СокрЛП(ИзмененныеОбъектыОЛЕ.ТипОбъекта);
ВидОбъекта = СокрЛП(ИзмененныеОбъектыОЛЕ.ВидОбъекта);
СсылкаНаОбъект = ИзмененныеОбъектыОЛЕ.ОбъектЗначение;
Если ТипОбъекта = "Справочник" И ВидОбъекта = "Номенклатура" Тогда
ОбработатьНоменклатуру(СсылкаНаОбъект, ОбъектV77);
КонецЕсли;
// Удаляем запись об изменении, чтобы не обрабатывать её повторно в следующий раз
ИзмененныеОбъектыОЛЕ.Удалить(1);
КонецЦикла;
При передаче объектов справочников крайне важно сопоставлять их правильно. Поиск по наименованию или артикулу ненадежен. Лучше использовать внутренний идентификатор 1С 7.7.
Посмотрим на функцию получения уникального ID из 7.7 через метод ЗначениеВСтрокуВнутр. Этот метод возвращает строку, содержащую тип и внутренний идентификатор. Нам нужно извлечь из неё последние символы.
Функция ПолучитьВнутреннийИД(ОбъектV77, ЭлементОЛЕ)
// Получаем внутреннее представление объекта
СтрВнутр = ОбъектV77.EvalExpr("ЗначениеВСтрокуВнутр(ТекущийОбъект)");
// Обычно ID в 7.7 — это 13-символьный код в конце строки ЗначениеВСтрокуВнутр
// Для надежности можно использовать встроенный метод _GetID() через EvalExpr
Возврат ОбъектV77.EvalExpr("_GetID(ТекущийЭлемент)");
КонецФункции
В 1С 8 рекомендуется создать дополнительный реквизит УИД_77 в справочнике Номенклатура и индексировать его. Тогда поиск будет мгновенным:
НайденнаяСсылка = Справочники.Номенклатура.НайтиПоРеквизиту("УИД_77", ИдентификаторИз77);
Если НайденнаяСсылка.Пустая() Тогда
// Создаем новый элемент
КонецЕсли;
Для получения данных по остаткам в 1С 7.7 удобно использовать объект БухгалтерскиеИтоги. Проанализируем пример кода, который запрашивает сальдо по счету 41.
БИ = ОбъектV77.CreateObject("БухгалтерскиеИтоги");
// Фильтр по номенклатуре (передается объект ОЛЕ)
БИ.ИспользоватьСубконто(ОбъектV77.EvalExpr("ВидыСубконто.Номенклатура"), НоменклатураОЛЕ, 1);
// Выполняем запрос на текущую дату
БИ.ВыполнитьЗапрос(ТекущаяДата(), ТекущаяДата(), "41.1");
Остаток = БИ.СКД("К"); // Сальдо конечное дебетовое по количеству
Важный момент оптимизации: Каждое обращение к БИ.СКД() через OLE — это вызов удаленной процедуры. Если позиций много, это будет работать медленно. Выясним причину: задержки сетевого интерфейса. Чтобы ускорить процесс, лучше написать в 7.7 функцию, которая соберет все остатки в таблицу значений, преобразует её в строку через ЗначениеВСтрокуВнутр и вернет один раз. В 1С 8 вы получите одну большую строку, которую быстро расшифруете.
Полученные остатки и цены нужно записать в регистры 1С 8. Использовать стандартные документы (например, ОприходованиеТоваров) не всегда удобно из-за автоматических проверок. Проанализируем более гибкий способ — использование документа КорректировкаЗаписейРегистров.
Рассмотрим пример установки цен номенклатуры:
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
// Устанавливаем отбор по регистратору (предварительно созданному документу корректировки)
НаборЗаписей.Отбор.Регистратор.Установить(ДокументКорректировка.Ссылка);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.Номенклатура = СсылкаНаТовар;
НоваяЗапись.ТипЦен = Справочники.ТипыЦенНоменклатуры.НайтиПоКоду("001");
НоваяЗапись.Цена = ЦенаИз77;
НоваяЗапись.Валюта = Справочники.Валюты.НайтиПоКоду("643");
НаборЗаписей.Записать();
Объект.Свойство1.Свойство2 используйте локальные переменные в 7.7 или метод EvalExpr() для получения всех данных за один раз.v77.Application открытым в глобальной переменной или кэше. Повторное подключение — самая долгая часть.ADOConnection будет в десятки раз быстрее, чем через OLE. Вы сможете получать остатки напрямую из таблиц _1SENTRY или _1SBKTTL.ЗаписатьСобытиеВЖурналРегистрации для логирования хода обмена вместо Сообщить.Таким образом, мы проанализировали основные этапы создания обмена между 1С 7.7 и 8.x. Главный секрет успеха здесь — это надежная идентификация объектов через внутренние ID и минимизация сетевых вызовов за счет агрегации данных на стороне «сервера» (1С 7.7). Правильно настроенный обмен позволит вам незаметно для пользователей синхронизировать данные между старыми и новыми информационными системами.