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