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