Как всегда после определения топологии и архитектуры КИС, не важно основанной на 1С:Предприятие или нет, возникают вопросы связанные с интеграцией и взаимодействием компонентов системы, в нашем случае меж платформенное взаимодействие.
Одним из простых методов организации обмена между информационными базами, является COM-интерфейс, о нем и пойдет речь в данной статье. Идеология платформы 1С:Предприятие 8.x позволила построить практически универсальный COM-интерфейс, ибо идентификаторы типов и объектов в информационной базе базируются на GUID-идентификаторах, а у платформе 1С:Предприятие 7.7 идентификатор составной.
При работе через COM-интерфейс с платформой 1С:Предприятие 7.7 в режиме получения данных, проблем не возникает, но при решении задачи записи объектов мы рано или поздно натыкаемся на глюки платформы Итак, рассмотрим частный случай, из платформы 1С:Предприятие 8.x подключаемся к базе на платформе 1С:Предприятие 7.7 например для записи справочника [Материалы]. Справочник [Материалы] имеет реквизит [СчетУчета] типа [Счет.Основной] и соответственно план счетов [Основной].
Подключаемся к платформе 1С:Предприятие 7.7 через COM-интерфейс:
Перем мПерефирийнаяБаза Экспорт; //Создает подключение к ИБ на платформе 1С:Предприятие 7.7 через COM-интерфейс //При удачном подключении к ИБ устанавливает переменую мПерефирийнаяБаза значением COM-объект //ВхПараметрыПодключения - Тип:[Структура] содержит путь к ИБ, логин и пароль //ВхПроверкаПодключения - Тип:[Булево] флаг проферки подключения, после попытки подключения отключается от ИБ Функция v77_ПодключитьИБ(ВхПараметрыПодключения, ВхПроверкаПодключения = Ложь) ВрмВозврат = Ложь; ВрмСтрокаПодключения = "" + "/D" + ВхПараметрыПодключения["БазаПуть"] + " " + "/N" + ВхПараметрыПодключения["БазаПользователь"] + " " + "/P" + ВхПараметрыПодключения["БазаПароль"]; Попытка мПерефирийнаяБаза = Новый COMОбъект("V77.Application"); Если Число(мПерефирийнаяБаза.Initialize(мПерефирийнаяБаза.RMTrade, ВрмСтрокаПодключения, "NO_SPLASH_SHOW")) = 0 Тогда v77_ОтключитьИБ(); ВызватьИсключение "Неудачная попытка инициализации соединения с перефирийной ИБ!"; Иначе ВрмВозврат = Истина; КонецЕсли; Исключение Сообщить(ОписаниеОшибки()); Возврат ВрмВозврат; КонецПопытки; Если ВхПроверкаПодключения Тогда v77_ОтключитьИБ(); КонецЕсли; Возврат ВрмВозврат; КонецФункции //Освобождает ссылки на COM-объект Процедура v77_ОтключитьИБ() мПерефирийнаяБаза = Неопределено; КонецПроцедуры
//Определяет тип переданного значения //Параметр: ВхОбъект - COM-объект 1С:Предприятие 7.7 //Возвращаемое значение: Строка типа переданного значения в формате 1С:Предприятие 7.7 Функция v77_ТипЗначенияСтр(ВхОбъект) Возврат мПерефирийнаяБаза.EvalExpr("ТипЗначенияСтр(ЗначениеИзСтрокиВнутр("""+ СтрЗаменить(мПерефирийнаяБаза.ЗначениеВСтрокуВнутр(ВхОбъект), """", """""")+ """))"); КонецФункции //Проверяет является ли переданное значение пустым //Параметр: ВхОбъект - COM-объект 1С:Предприятие 7.7 //Возвращаемое значение: 0 - Заполненно, 1 - Пустое значение Функция v77_ПустоеЗначение(ВхОбъект) Возврат мПерефирийнаяБаза.EvalExpr("ПустоеЗначение(ЗначениеИзСтрокиВнутр("""+ СтрЗаменить(мПерефирийнаяБаза.ЗначениеВСтрокуВнутр(ВхОбъект), """", """""")+ """))"); КонецФункции //Получает пустое значение заданного типа //Параметр: ВхТип - Строка типа в формате 1С:Предприятие 7.7 //Возвращаемое значение: COM-объект 1С:Предприятие 7.7 Функция v77_ПолучитьПустоеЗначение(ВхТип) Возврат мПерефирийнаяБаза.EvalExpr("ПолучитьПустоеЗначение(""" + ВхТип + """)"); КонецФункции //Создает объект заданного типа //Параметр: ВхТип - Строка типа в формате 1С:Предприятие 7.7 //Возвращаемое значение: COM-объект 1С:Предприятие 7.7 Функция v77_СоздатьОбъект(ВхТип) Возврат мПерефирийнаяБаза.EvalExpr("СоздатьОбъект(""" + ВхТип + """)"); КонецФункции
Пробуем найти/создать элемент справочника в ИБ на платформе 1С:Предприятие 7.7 через COM-интерфейс:
//Устанавливает объекту значение реквизита //Параметр: ВхОбъект - Объект //Параметр: ВхИмяРеквизита - Имя реквизита //Параметр: ВхЗначение - Значение реквизита //Возвращаемое значение: Булево: Истина - реквизит установлен, Ложь -не установлен Функция v77_УстановитьАтрибут(ВхОбъект, ВхИмяРеквизита, ВхЗначение) ВрмЗначениеСтарое = ВхОбъект.ПолучитьАтрибут(ВхИмяРеквизита); ВхОбъект.УстановитьАтрибут(ВхИмяРеквизита, ВхЗначение); ВрмЗначение = ВхОбъект.ПолучитьАтрибут(ВхИмяРеквизита); Возврат (ВрмЗначениеСтарое = ВхЗначение); КонецФункции Процедура ВыполнитьОбмен() Экспорт ВрмНастройки = v77_ПолучитьНастройки("OLE"); Если Не v77_ПодключитьИБ(ВрмНастройки) Тогда Возврат; КонецЕсли; ВрмКод = "010101"; ВрмСправочник = v77_СоздатьОбъект("Справочник.Материалы"); //Ищем элемент справочника по коду. Если не найден - создаем Если ВрмСправочник.НайтиПоКоду(ВрмКод) = 0 Тогда ВрмСправочник.Новый(); ВрмСправочник.Код = ВрмКод; Иначе ВрмСправочник.ТекущийЭлемент(); КонецЕсли; //Получаем объект типа ПланСчетов ВрмПланСчетов = мПерефирийнаяБаза.ПланыСчетов.ЗначениеПоИдентификатору("Основной"); //Получаем объект типа Счет ВрмСчет = v77_СоздатьОбъект("Счет"); //Устанавливаем счету план счетов ВрмСчет.ИспользоватьПланСчетов(ВрмПланСчетов); //Ищем счет ВрмСчет.НайтиПоКоду("10.5"); ВрмЗначение = ВрмСчет.ТекущийСчет(); //Устанавливаем значение реквизита в v77_УстановитьАтрибут(ВрмСправочник, "СчетУчета", ВрмЗначение); ВрмСправочник.Записать(); v77_ОтключитьИБ(); КонецПроцедуры
Запускаем процедуру ВыполнитьОбмен(), ждем завершения и проверяем в ИБ 7.7 результат работы... Элемент создан, код элементу присвоился, а реквизит [СчетУчета] остался пустым.
Необходимо в глобальном модуле конфигурации ИБ на платформе 1С:Предприятие 7.7 объявить функцию:
Процедура OLE_УстановитьАтрибутИзСтрокиВнутр(ВхОбъект, ВхИмяРеквизита, ВхСтрокаВнутр) Экспорт ВхОбъект.УстановитьАтрибут(ВхИмяРеквизита, ЗначениеИзСтрокиВнутр(ВхСтрокаВнутр)); КонецПроцедуры
И вызывать в 8.x следующим образом:
Функция v77_МассивИзСтрокиВнутр(ВхСтрокаВнутр) ВрмВозврат = Новый Массив; ВрмСтрока = ""; ВрмДлина = СтрДлина(ВхСтрокаВнутр); Для ВрмПозиция = 1 По ВрмДлина Цикл ВрмСимвол = Сред(ВхСтрокаВнутр, ВрмПозиция, 1); Если ВрмСимвол = "{" Тогда ИначеЕсли ВрмСимвол = "," Или ВрмСимвол = "}" Тогда ВрмВозврат.Добавить(ВрмСтрока); ВрмСтрока = ""; Иначе ВрмСтрока = ВрмСтрока + ВрмСимвол; КонецЕсли; КонецЦикла; Возврат ВрмВозврат; КонецФункции Функция v77_МассивВСтрокуВнутр(ВхМассив) ВрмВозврат = ""; Для Каждого ВхЭлемент Из ВхМассив Цикл Если ВрмВозврат <> "" Тогда ВрмВозврат = ВрмВозврат + "," КонецЕсли; ВрмВозврат = ВрмВозврат + ВхЭлемент; КонецЦикла; Возврат "{" + ВрмВозврат + "}"; КонецФункции Функция v77_НазначитьТипВСтрокуВнутр(ВхБаза77, ВхОбъектИсточник, ВхОбъектПриемник) ВрмМассивИсточник = v77_МассивИзСтрокиВнутр(ВхБаза77.ЗначениеВСтрокуВнутр(ВхОбъектИсточник)); ВрмМассивПриемник = v77_МассивИзСтрокиВнутр(ВхБаза77.ЗначениеВСтрокуВнутр(ВхОбъектПриемник)); ВрмТипИсточник = СтрЗаменить(ВрмМассивИсточник[6], """", ""); ВрмТипПриемник = СтрЗаменить(ВрмМассивПриемник[6], """", ""); ВрмМассивПриемник[6] = """" + Лев(ВрмТипИсточник, 10) + Прав(ВрмТипПриемник, 13) + """"; Возврат v77_МассивВСтрокуВнутр(ВрмМассивПриемник); КонецФункции
Исправляем нашу функцию:
Процедура ВыполнитьОбмен() Экспорт ВрмНастройки = v77_ПолучитьНастройки("OLE"); Если Не v77_ПодключитьИБ(ВрмНастройки) Тогда Возврат; КонецЕсли; ВрмКод = "010101"; ВрмСправочник = v77_СоздатьОбъект("Справочник.Материалы"); //Ищем элемент справочника по коду. Если не найден - создаем Если ВрмСправочник.НайтиПоКоду(ВрмКод) = 0 Тогда ВрмСправочник.Новый(); ВрмСправочник.Код = ВрмКод; Иначе ВрмСправочник.ТекущийЭлемент(); КонецЕсли; //Получаем объект типа ПланСчетов ВрмПланСчетов = мПерефирийнаяБаза.ПланыСчетов.ЗначениеПоИдентификатору("Основной"); //Получаем объект типа Счет ВрмСчет = v77_СоздатьОбъект("Счет"); //Устанавливаем счету план счетов ВрмСчет.ИспользоватьПланСчетов(ВрмПланСчетов); //Ищем счет ВрмСчет.НайтиПоКоду("10.5"); ВрмЗначение = ВрмСчет.ТекущийСчет(); //Преобразуем в строку внутр и явно устанавливаем тип плана счетов ВрмЗначениеСтр = v77_НазначитьТипВСтрокуВнутр(мПерефирийнаяБаза, ВрмПланСчетов, ВрмЗначение); //Устанавливаем значение реквизита вызывая процедуру глобального модуля мПерефирийнаяБаза.OLE_УстановитьАтрибутИзСтрокиВнутр(ВрмСправочник, "СчетУчета", ВрмЗначениеСтр); ВрмСправочник.Записать(); v77_ОтключитьИБ(); КонецПроцедуры
Теперь все работает!