Работа с ComОбъектом 1С 8.2; 8.3

Определение типов и значений через COM соединение между конфигурациями.

При написании обработок обмена между конфигурациями 1С часто возникает необходимость определения типа принимаемых данных справочник, документ, ПланСчетов или т.д. Эта информация разбросана по интернету но я решил систематизировать и показать Вам.

Для подключения и работы с ком соединением рекомендуется объявить переменную к которой будет подствлено значение соединение и проверять на данное подключение в каждой процедуре, ниже приведен текст процедуры/функции и способы подключения в конфигурациях

СтруктураПодключения — эта переменная в которой имеется Строка соединения с СОМ объектом

Перем Коннект;

Процедура  ПолучитьИмяКонфигурацииИсточника()
Если Коннект = Неопределено Тогда Если Не ПодключитьИБ() Тогда Сообщить("Не удалось установить подключение к ИБ!!!"); Возврат ; КонецЕсли; КонецЕсли;
Если Коннект.Метаданные.DetailedInformation = "Бухгалтерия предприятия, редакция 2.0"
ИЛИ Коннект.Метаданные.DetailedInformation = "1С:Учет в управляющих компаниях ЖКХ, ТСЖ и ЖСК"
ИЛИ Коннект.Метаданные.DetailedInformation = "Бухгалтерия строительной организации, редакция 2.0" ТОгда
ИмяКонфигурацииИсточника = "БП20";
ИначеЕсли Коннект.Метаданные.DetailedInformation = "Комплексная автоматизация, редакция 1.1" ТОгда

ИмяКонфигурацииИсточника = "КА11";
Иначе
ИмяКонфигурацииИсточника = "БП30";
КонецЕсли;
КонецПроцедуры

Функция ПодключитьИБ(СтруктураПодключения = Неопределено) Экспорт
//Открыта = Ложь;
Если Не СтруктураПодключения = Неопределено Тогда
СтруктураНастроек = СтруктураПодключения;
Иначе
СтруктураНастроек = Новый Структура("COMАутентификацияОперационнойСистемы,COMВариантРаботыИнформационнойБазы,COMИмяИнформационнойБазыНаСервере1СПредприятия,COMИмяПользователя,COMИмяСервера1СПредприятия,COMКаталогИнформационнойБазы,COMПарольПользователя",COMАутентификацияОперационнойСистемы,COMВариантРаботыИнформационнойБазы,COMИмяИнформационнойБазыНаСервере1СПредприятия,COMИмяПользователя,COMИмяСервера1СПредприятия,COMКаталогИнформационнойБазы,COMПарольПользователя);
КонецЕсли;
Результат = УстановитьВнешнееСоединениеСБазойCOM(ЗаполнитьПараметрыПодключенияВнешнегоСоединения(СтруктураНастроек));
Коннект = Результат.Соединение;
Если Коннект = Неопределено Тогда
// Ошибка установки соединения.
Сообщить("" + Результат.КраткоеОписаниеОшибки + ". " + Результат.ПодробноеОписаниеОшибки);
Возврат Ложь;
Иначе
Если Не ЗначениеЗаполнено(ИмяКонфигурацииИсточника) Тогда
ПолучитьИмяКонфигурацииИсточника();
КонецЕсли;
Возврат Истина;
КонецЕсли;

//Возврат Открыта;
КонецФункции

// Возвращает шаблон структуры параметров для установки внешнего соединения.
// Параметрам необходимо задать требуемые значения и передать.
// В метод ОбщегоНазначения.УстановитьВнешнееСоединение().
//
Функция СтруктураПараметровДляУстановкиВнешнегоСоединения() Экспорт

СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("ВариантРаботыИнформационнойБазы", 0);
СтруктураПараметров.Вставить("КаталогИнформационнойБазы", "");
СтруктураПараметров.Вставить("ИмяСервера1СПредприятия", "");
СтруктураПараметров.Вставить("ИмяИнформационнойБазыНаСервере1СПредприятия", "");
СтруктураПараметров.Вставить("АутентификацияОперационнойСистемы", Ложь);
СтруктураПараметров.Вставить("ИмяПользователя", "");
СтруктураПараметров.Вставить("ПарольПользователя", "");

Возврат СтруктураПараметров;
КонецФункции

Функция ЗаполнитьПараметрыПодключенияВнешнегоСоединения(НастройкиТранспорта)

ПараметрыПодключения = СтруктураПараметровДляУстановкиВнешнегоСоединения();

ПараметрыПодключения.ВариантРаботыИнформационнойБазы             = НастройкиТранспорта.COMВариантРаботыИнформационнойБазы;
ПараметрыПодключения.КаталогИнформационнойБазы                   = НастройкиТранспорта.COMКаталогИнформационнойБазы;
ПараметрыПодключения.ИмяСервера1СПредприятия                     = НастройкиТранспорта.COMИмяСервера1СПредприятия;
ПараметрыПодключения.ИмяИнформационнойБазыНаСервере1СПредприятия = НастройкиТранспорта.COMИмяИнформационнойБазыНаСервере1СПредприятия;
ПараметрыПодключения.АутентификацияОперационнойСистемы           = НастройкиТранспорта.COMАутентификацияОперационнойСистемы;
ПараметрыПодключения.ИмяПользователя                             = НастройкиТранспорта.COMИмяПользователя;
ПараметрыПодключения.ПарольПользователя = НастройкиТранспорта.COMПарольПользователя;

Возврат ПараметрыПодключения;
КонецФункции

Функция ИмяCOMСоединителя()
Если ПодключенияВариант = Неопределено ТОгда
Какая8 = СтрЗаменить(COMПодключенияВариант, ".", "");
Иначе
Какая8 = СтрЗаменить(ПодключенияВариант, ".", "");
КонецЕсли;
Возврат "v" + Какая8 + ".COMConnector";
КонецФункции

// Устанавливает внешнее соединение с информационной базой по переданным параметрам подключения и возвращает указатель
// на это соединение.
//
// Параметры:
//  Параметры - Структура - параметры для установки внешнего соединения с информационной базой.
//                          Свойства см. в функции
//                          ОбщегоНазначенияКлиентСервер.СтруктураПараметровДляУстановкиВнешнегоСоединения):
//
//   * ВариантРаботыИнформационнойБазы             - Число  -  Вариант работы информационной базы: 0 - файловый; 1 -
//                                                            клиент-серверный;
//   * КаталогИнформационнойБазы                   - Строка - Каталог информационной базы для файлового режима работы;
//   * ИмяСервера1СПредприятия                     - Строка - Имя сервера1С:Предприятия;
//   * ИмяИнформационнойБазыНаСервере1СПредприятия - Строка - Имя информационной базы на сервере1С:Предприятия;
//   * АутентификацияОперационнойСистемы           - Булево - Признак аутентификации операционной системы при создании
//                                                            внешнего подключения к информационной базе;
//   * ИмяПользователя                             - Строка - Имя пользователя информационной базы;
//   * ПарольПользователя                          - Строка - Пароль пользователя информационной базы.
//
// Возвращаемое значение:
//  Структура -
//    * Соединение                  - COMОбъект, Неопределено - указатель на COM-объект соединения или Неопределено в
//                                    случае ошибки;
//    * КраткоеОписаниеОшибки       - Строка - краткое описание ошибки;
//    * ПодробноеОписаниеОшибки     - Строка - подробное описание ошибки;
//    * ОшибкаПодключенияКомпоненты - Булево - флаг ошибки подключения COM.
//
Функция УстановитьВнешнееСоединениеСБазойCOM(Параметры) Экспорт

Результат = Новый Структура;
Результат.Вставить("Соединение");
Результат.Вставить("КраткоеОписаниеОшибки", "");
Результат.Вставить("ПодробноеОписаниеОшибки", "");
Результат.Вставить("ОшибкаПодключенияКомпоненты", Ложь);

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
ЭтоLinux = ОбщегоНазначения.ЭтоLinuxСервер();
КраткоеОписаниеОшибки = НСтр("ru = 'Прямое подключение к информационной базе недоступно на сервере под управлением ОС Linux.'");
#Иначе
ЭтоLinux = ЭтоLinuxКлиент();
КраткоеОписаниеОшибки = НСтр("ru = 'Прямое подключение к информационной базе недоступно на клиенте под управлением ОС Linux.'");
#КонецЕсли

Если ЭтоLinux Тогда
Результат.Соединение = Неопределено;
Результат.КраткоеОписаниеОшибки = КраткоеОписаниеОшибки;
Результат.ПодробноеОписаниеОшибки = КраткоеОписаниеОшибки;
Возврат Результат;
КонецЕсли;

Попытка
COMConnector = Новый COMObject(ИмяCOMСоединителя()); // "V83.COMConnector"
Исключение
Информация = ИнформацияОбОшибке();
СтрокаСообщенияОбОшибке = НСтр("ru = 'Не удалось подключится к другой программе: %1'");

Результат.ОшибкаПодключенияКомпоненты = Истина;
Результат.ПодробноеОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщенияОбОшибке, ПодробноеПредставлениеОшибки(Информация));
Результат.КраткоеОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщенияОбОшибке, КраткоеПредставлениеОшибки(Информация));

Возврат Результат;
КонецПопытки;

ФайловыйВариантРаботы = Параметры.ВариантРаботыИнформационнойБазы = 0;

// Проверка корректности указания параметров.
ОшибкаПроверкиЗаполнения = Ложь;
Если ФайловыйВариантРаботы Тогда

Если ПустаяСтрока(Параметры.КаталогИнформационнойБазы) Тогда
СтрокаСообщенияОбОшибке = НСтр("ru = 'Не задано месторасположение каталога информационной базы.'");
ОшибкаПроверкиЗаполнения = Истина;
КонецЕсли;

Иначе

Если ПустаяСтрока(Параметры.ИмяСервера1СПредприятия) Или ПустаяСтрока(Параметры.ИмяИнформационнойБазыНаСервере1СПредприятия) Тогда
СтрокаСообщенияОбОшибке = НСтр("ru = 'Не заданы обязательные параметры подключения: ""Имя сервера""; ""Имя информационной базы на сервере"".'");
ОшибкаПроверкиЗаполнения = Истина;
КонецЕсли;

КонецЕсли;

Если ОшибкаПроверкиЗаполнения Тогда

Результат.ПодробноеОписаниеОшибки = СтрокаСообщенияОбОшибке;
Результат.КраткоеОписаниеОшибки   = СтрокаСообщенияОбОшибке;
Возврат Результат;

КонецЕсли;

// Формирование строки соединения.
ШаблонСтрокиСоединения = "[СтрокаБазы][СтрокаАутентификации]";

Если ФайловыйВариантРаботы Тогда
СтрокаБазы = "File = ""&КаталогИнформационнойБазы""";
СтрокаБазы = СтрЗаменить(СтрокаБазы, "&КаталогИнформационнойБазы", Параметры.КаталогИнформационнойБазы);
Иначе
СтрокаБазы = "Srvr = ""&ИмяСервера1СПредприятия""; Ref = ""&ИмяИнформационнойБазыНаСервере1СПредприятия""";
СтрокаБазы = СтрЗаменить(СтрокаБазы, "&ИмяСервера1СПредприятия",                     Параметры.ИмяСервера1СПредприятия);
СтрокаБазы = СтрЗаменить(СтрокаБазы, "&ИмяИнформационнойБазыНаСервере1СПредприятия", Параметры.ИмяИнформационнойБазыНаСервере1СПредприятия);
КонецЕсли;

Если Параметры.АутентификацияОперационнойСистемы Тогда
СтрокаАутентификации = "";
Иначе

Если СтрНайти(Параметры.ИмяПользователя, """") Тогда
Параметры.ИмяПользователя = СтрЗаменить(Параметры.ИмяПользователя, """", """""");
КонецЕсли;

Если СтрНайти(Параметры.ПарольПользователя, """") Тогда
Параметры.ПарольПользователя = СтрЗаменить(Параметры.ПарольПользователя, """", """""");
КонецЕсли;

СтрокаАутентификации = "; Usr = ""&ИмяПользователя""; Pwd = ""&ПарольПользователя""";
СтрокаАутентификации = СтрЗаменить(СтрокаАутентификации, "&ИмяПользователя",    Параметры.ИмяПользователя);
СтрокаАутентификации = СтрЗаменить(СтрокаАутентификации, "&ПарольПользователя", Параметры.ПарольПользователя);
КонецЕсли;

СтрокаСоединения = СтрЗаменить(ШаблонСтрокиСоединения, "[СтрокаБазы]", СтрокаБазы);
СтрокаСоединения = СтрЗаменить(СтрокаСоединения, "[СтрокаАутентификации]", СтрокаАутентификации);

Попытка
Результат.Соединение = COMConnector.Connect(СтрокаСоединения);
Исключение
Информация = ИнформацияОбОшибке();
СтрокаСообщенияОбОшибке = НСтр("ru = 'Не удалось подключиться к другой программе: %1'");

Результат.ОшибкаПодключенияКомпоненты = Истина;
Результат.ПодробноеОписаниеОшибки     = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщенияОбОшибке, ПодробноеПредставлениеОшибки(Информация));
Результат.КраткоеОписаниеОшибки       = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщенияОбОшибке, КраткоеПредставлениеОшибки(Информация));
КонецПопытки;

Возврат Результат;

КонецФункции


// Основная функция для использования внешнего соединения при обмене.
//
// Параметры:
//  СтруктураНастроек - структура настроек транспорта COM обмена.
//
Функция УстановитьВнешнееСоединениеСБазой(СтруктураНастроек) Экспорт

Результат = УстановитьВнешнееСоединениеСБазойCOM(ЗаполнитьПараметрыПодключенияВнешнегоСоединения(СтруктураНастроек));

ВнешнееСоединение = Результат.Соединение;
Если ВнешнееСоединение = Неопределено Тогда
// Ошибка установки соединения.
Возврат Результат;
КонецЕсли;

// Дополнительно проверяем возможность работы с внешней базой.

Попытка
НетПолныхПрав = Не ВнешнееСоединение.ОбменДаннымиВнешнееСоединение.РольДоступнаПолныеПрава();
Исключение
НетПолныхПрав = Истина;
КонецПопытки;

Если НетПолныхПрав Тогда
Результат.ПодробноеОписаниеОшибки = НСтр("ru = 'Пользователю, указанному для подключения к другой программе, должны быть назначены роли ""Администратор системы"" и ""Полные права""'");
Результат.КраткоеОписаниеОшибки   = Результат.ПодробноеОписаниеОшибки;
Результат.Соединение = Неопределено;
Иначе
Попытка
СостояниеНеДопустимо = ВнешнееСоединение.ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы();
Исключение
СостояниеНеДопустимо = Ложь
КонецПопытки;

Если СостояниеНеДопустимо Тогда
Результат.ПодробноеОписаниеОшибки = НСтр("ru = 'Другая программа находится в состоянии обновления.'");
Результат.КраткоеОписаниеОшибки   = Результат.ПодробноеОписаниеОшибки;
Результат.Соединение = Неопределено;
КонецЕсли;

КонецЕсли;

Возврат Результат;
КонецФункции

Часто возникает необходимость проверка наличия реквизита или свойства объекта, при этом понятия не имееш есть данный реквизит или нет

но использование Попытки .. Исключение .. КонецПопытки не желательно то в даном варианте можно использовать подстановку реквизита в структуру

и тем самым использовать следующую процедуру:

// Проверяет наличие реквизита или свойства у произвольного объекта без обращения к метаданным.
//
// Параметры:
//  Объект       - Произвольный - объект, у которого нужно проверить наличие реквизита или свойства;
//  ИмяРеквизита - Строка       - имя реквизита или свойства.
//
// Возвращаемое значение:
//  Булево.
//
Функция ЕстьРеквизитИлиСвойствоОбъекта(Объект, ИмяРеквизита) Экспорт

КлючУникальности   = Новый УникальныйИдентификатор;
СтруктураРеквизита = Новый Структура(ИмяРеквизита, КлючУникальности);
ЗаполнитьЗначенияСвойств(СтруктураРеквизита, Объект);

Возврат СтруктураРеквизита[ИмяРеквизита] <> КлючУникальности;

КонецФункции

Теперь вопрос который многих интересует: "Мы получили СОМ объект тоесть ТИП("СомОбъект"), какое значение и что с ним делать?

для этого приходят метаданные и мы можем получить любую информацию используя метаданные не только текущей конфигурации, но и конфигурации источника к примеру РеквCOM это реквизит который мы должны изучить:

_СтрокаXML = Коннект.XMLString(РеквCOM); // УникальныйИдентификатор объекта

УИД объекта имеет определенный формат даных поэтому для выяснения что мы имеем то необходимо доп проверка

т.к. _СтрокаXML  имеет формат "00000000-0000-0000-0000-000000000000" то актуальна проверка

Если СтрНайти(_СтрокаXML, "-", , , 4) = 24 Тогда //Всего скорее это  ГУИД

//***********

ИначеЕсли СтрДлина(_СтрокаXML) = 48 Тогда //Хранилище значения

//************

Иначе //Перечисление

//************

КонецЕсли;

Рассмотрим что можно получить от объекта если по нему есть УИД

_ПолныйТипОбъекта  = РеквCOM.GetObject().Metadata().FullName();
СтрокиТипа   = СтрЗаменить(_ПолныйТипОбъекта, ".", Символы.ПС);
_ТипОбъекта   = СтрПолучитьСтроку(СтрокиТипа, 1);
_ИдентификаторCOM  = СтрПолучитьСтроку(СтрокиТипа, 2);

//Для получения менеджера объекта нужно воспользоваться доп процедурой

_МенеджерОбъекта = ПолучитьМенеджерОбъекта(_ИдентификаторCOM);


Функция ПолучитьМенеджерОбъекта(СсылкаОб) Экспорт
Если ТипЗнч(СсылкаОб) = Тип("Строка") Тогда
СсылкаПоиска = _ПолучитьПустуюСсылкуПоИдентификаторуОбъекта(СсылкаОб);
Иначе
СсылкаПоиска = СсылкаОб;
КонецЕсли;
//Попытка
Если СсылкаПоиска <> Неопределено Тогда
ИмяОбъекта = СсылкаПоиска.Метаданные().Имя;
Иначе
Возврат Неопределено;
КонецЕсли;
//Исключение
// Возврат Неопределено;
//КонецПопытки;
ТипСсылки = ТипЗнч(СсылкаПоиска);
Если Справочники.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат Справочники[ИмяОбъекта];
ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат Документы[ИмяОбъекта];
ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат БизнесПроцессы[ИмяОбъекта];
ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат ПланыВидовХарактеристик[ИмяОбъекта];
ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат ПланыСчетов[ИмяОбъекта];
ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат ПланыВидовРасчета[ИмяОбъекта];
ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат Задачи[ИмяОбъекта];
ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат ПланыОбмена[ИмяОбъекта];
ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
Возврат Перечисления[ИмяОбъекта];
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции

Функция _ПолучитьПустуюСсылкуПоИдентификаторуОбъекта(ОбъектМетаданных) Экспорт
ТипМД = _ПолучитьТипПоИдентификатору(ОбъектМетаданных);
ПустаяСсылка = "";
Если ТипМД = "Справочник" Тогда
Команда1С = "ПустаяСсылка = Справочники."+ОбъектМетаданных+".ПустаяСсылка()";
ИначеЕсли ТипМД = "Документ" Тогда
Команда1С = "ПустаяСсылка = Документы."+ОбъектМетаданных+".ПустаяСсылка()";
ИначеЕсли ТипМД = "Перечисление" Тогда
Команда1С = "ПустаяСсылка = Перечисления."+ОбъектМетаданных+".ПустаяСсылка()";
ИначеЕсли ТипМД = "ПланВидовРасчета" Тогда
Команда1С = "ПустаяСсылка = ПланыВидовРасчета."+ОбъектМетаданных+".ПустаяСсылка()";
Иначе
Возврат Неопределено;
КонецЕсли;
Выполнить (Команда1С);
Возврат ПустаяСсылка;
КонецФункции

 

Имея данные объекта мы можем использовать их в конфигурациях переноса создав процедуру сопоставления объектов, здесь можно будет уже

развернуться как Вам больше нравится

В случае если наш объект является ХранилищеЗначений то для переноса данного объекта либо получение значения можно воспользоваться функцией

//*****************************
//рабочая процедура и в ней код обработки

ИначеЕсли _ТипОбъекта = "ХранилищеЗначения" Тогда
Возврат ПереносХранилища(РеквCOM);


//*****************************


Функция ПереносХранилища(РеквCOM)
Попытка
ДвоичныеДанные = РеквCOM.Get();
Исключение
Возврат Неопределено;
Конецпопытки;
Если "" + ДвоичныеДанные = "COMОбъект" Тогда
Попытка
ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанные.Write(ИмяВременногоФайла);
ДвоичныеДанныеВозврат  = Новый ДвоичныеДанные(ИмяВременногоФайла);
УдалитьФайлы(ИмяВременногоФайла);
Возврат Новый ХранилищеЗначения(ДвоичныеДанныеВозврат);
Исключение
Возврат Неопределено;
КонецПопытки;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции

Если объект является перечислением то вместо УИД кода будет выведено наименование перечисления

Также для получения списка реквизитов объекта СОМ используется обращение

 РеквCOM.Metadata().Attributes // Список реквизитов

РеквCOM.Metadata().Attributes.Find("Реквизит") // Поиск реквизита в объекте
// если реквизит не найден возвращает значение НЕОПРЕДЕЛЕНО

РеквCOM.Metadata().StandardAttributes // Список стандартных реквизитов

РеквCOM.Metadata().TabularSections // Список табличных частей

 

Для работы с удаленой базой через COM соединение также часто возникает необходимость получения функциональных опций объекта

для этих целей можно использовать функцию которая выведет список соответствий функциональных опций

// Доступность объектов метаданных по функциональным опциям.
Функция ДоступностьОбъектовПоОпциямCOM() Экспорт
Если Коннект = Неопределено Тогда Если Не ПодключитьИБ() Тогда Сообщить("Не удалось установить подключение к ИБ!!!"); Возврат Новый Соответствие КонецЕсли; КонецЕсли;
Параметры = Новый Структура;
ДоступностьОбъектов = Новый Соответствие;
Для Каждого ФункциональнаяОпция Из Коннект.Метаданные.ФункциональныеОпции Цикл
Значение = -1;
Для Каждого Элемент Из ФункциональнаяОпция.Состав Цикл
Если Значение = -1 Тогда
Значение = ПолучитьФункциональнуюОпцию(ФункциональнаяОпция.Имя, Параметры);
КонецЕсли;
Если Значение = Истина Тогда
ДоступностьОбъектов.Вставить(Элемент.Объект, Истина);
Иначе
Если ДоступностьОбъектов[Элемент.Объект] = Неопределено Тогда
ДоступностьОбъектов.Вставить(Элемент.Объект, Ложь);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат ДоступностьОбъектов;
КонецФункции


//Рабочая процедура
Функция ОбъектМетаданныхДоступенПоФункциональнымОпциямCOM(ОбъектМетаданныхCOM) Экспорт
Возврат ДоступностьОбъектовПоОпциямCOM()[ОбъектМетаданныхCOM] <> Ложь;
КонецФункции

Так же при работе с переносом документов возникает необходимость определения списка регистров движения данного документа

 

 МетаданныеДокументаCOM = ДокCom.MetaData();
Регистры = ЗаполнитьТаблицуРегистровCOM(МетаданныеДокументаCOM);
УстановитьПривилегированныйРежим(Истина);
РегистрыСДвижениями = ПолучитьМассивИспользуемыхРегистровCOM(ДокCom, МетаданныеДокументаCOM.Движения);


Функция ЗаполнитьТаблицуРегистровCOM(МетаданныеДокументаCOM)
Если Коннект = Неопределено Тогда Если Не ПодключитьИБ() Тогда Сообщить("Не удалось установить подключение к ИБ!!!"); Возврат Новый ТаблицаЗначений КонецЕсли; КонецЕсли;
МетаданныеРегистровНакопленияCOM = Коннект.Metadata.РегистрыНакопления;
МетаданныеРегистровСведенийCOM   = Коннект.Metadata.РегистрыСведений;
ВидРегистраОстаткиCOM            = Коннект.Metadata.СвойстваОбъектов.ВидРегистраНакопления.Остатки;

Регистры = Новый ТаблицаЗначений;
Регистры.Колонки.Добавить("ТипРегистра", ОбщегоНазначения.ОписаниеТипаСтрока(20));
Регистры.Колонки.Добавить("Имя", ОбщегоНазначения.ОписаниеТипаСтрока(100));
Регистры.Колонки.Добавить("Синоним", ОбщегоНазначения.ОписаниеТипаСтрока(100));
Регистры.Колонки.Добавить("ЕстьДвижения", Новый ОписаниеТипов("Булево"));
Регистры.Колонки.Добавить("РегистрОстатков", Новый ОписаниеТипов("Булево"));
Регистры.Колонки.Добавить("Записывать", Новый ОписаниеТипов("Булево"));
Для каждого МетаданныеРегистраCOM Из МетаданныеДокументаCOM.Движения Цикл
Если Лев(МетаданныеРегистраCOM.Имя, 7) = "Удалить" Тогда Продолжить КонецЕсли;
//Если Не ОбъектМетаданныхДоступенПоФункциональнымОпциямCOM(МетаданныеРегистраCOM) Тогда
// Продолжить;
//КонецЕсли;
СтрокаРегистра     = Регистры.Добавить();
СтрокаРегистра.Имя = МетаданныеРегистраCOM.Имя;
ПолноеИмя    = МетаданныеРегистраCOM.ПолноеИмя();
ПозицияТочки = Найти(ПолноеИмя, ".");
ТипРегистра  = Лев(ПолноеИмя, ПозицияТочки - 1);
СтрокаРегистра.ТипРегистра = ТипРегистра;
СтрокаРегистра.Синоним     = МетаданныеРегистраCOM.Синоним;
Если ТипРегистра = "РегистрНакопления" Тогда
СтрокаРегистра.РегистрОстатков = МетаданныеРегистраCOM.ВидРегистра = ВидРегистраОстаткиCOM;
КонецЕсли;
КонецЦикла;
// Сначала показывается регистр бухгалтерии, затем регистры накопления, затем - сведений
Регистры.Сортировать("ТипРегистра, Синоним");
Возврат Регистры;
КонецФункции

Функция ПолучитьМассивИспользуемыхРегистровCOM(Регистратор, Движения, МассивИсключаемыхРегистров = Неопределено) Экспорт
Если Коннект = Неопределено Тогда Если Не ПодключитьИБ() Тогда Сообщить("Не удалось установить подключение к ИБ!!!"); Возврат Новый ТаблицаЗначений КонецЕсли; КонецЕсли;
Запрос = Коннект.NewObject("Query");
Запрос.УстановитьПараметр("Регистратор", Регистратор);

Результат = Новый Массив;
МаксимумТаблицВЗапросе = 256;
СчетчикТаблиц   = 0;
СчетчикДвижений = 0;
ВсегоДвижений = Движения.Количество();
ТекстЗапроса  = "";
Для Каждого Движение Из Движения Цикл
СчетчикДвижений = СчетчикДвижений + 1;
ПропуститьРегистр = МассивИсключаемыхРегистров <> Неопределено
И МассивИсключаемыхРегистров.Найти(Движение.Имя) <> Неопределено;
Если Не ПропуститьРегистр Тогда
Если СчетчикТаблиц > 0 Тогда
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|";
КонецЕсли;
СчетчикТаблиц = СчетчикТаблиц + 1;
ТекстЗапроса = ТекстЗапроса +
"
|ВЫБРАТЬ ПЕРВЫЕ 1
|""" + Движение.Имя + """ КАК ИмяРегистра
|
|ИЗ " + Движение.ПолноеИмя() + "
|
|ГДЕ Регистратор = &Регистратор
|";
КонецЕсли;
Если СчетчикТаблиц = МаксимумТаблицВЗапросе Или СчетчикДвижений = ВсегоДвижений Тогда
Запрос.Текст  = ТекстЗапроса;
ТекстЗапроса  = "";
СчетчикТаблиц = 0;
Если Результат.Количество() = 0 Тогда

Результат = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ИмяРегистра");
Иначе
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Результат.Добавить(Выборка.ИмяРегистра);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;

Возврат Результат;

КонецФункции

Все процедуры, используемые в статье, являются работающими и готовы к использованию.

Надеюсь, кому-нибудь данная статья будет полезна!

Спасибо за внимание) !!!

12 Comments

  1. zeegin

    При копировании процедур из БСП следует указывать, что они из БСП.

    Attribution 4.0 International (CC BY 4.0)

    Ответы на типовые вопросы по лицензированию «1С:Предприятия 8»

    Reply
  2. ArchLord42

    Вот КД уже сколько лет существует, а люди все свои костылики пишут для обмена, да ещё и по ком, мде в общем..

    Reply
  3. SlavaKron
    ИначеЕсли СтрДлина(_СтрокаXML) = 48 Тогда //Хранилище значения

    Почему вы так решили? СтрокаXML от хранилища значения — это сырые данные (строка в формате base64). Её длина может быть какой угодно.

    Для определения типа КомОбъекта следует пользоваться процедурами и функциями работы с XML (XMLТип, XMLТипЗнч, ИзXMLТипа).

    _ПолныйТипОбъекта = РеквCOM.GetObject().Metadata().FullName();

    Чтобы получить метаданные, объект получать не обязательно. У любой ссылки есть метод Метаданные.

    Получить менеджер можно проще:

    Менеджер = Новый (СтрЗаменить(ПолноеИмяМетаданных, «.», «Менеджер.»));

    Получение пустой ссылки логичнее делать через менеджер.

    Хранилище значения переносится через XMLСтрока / XMLЗначение

    Reply
  4. vik070777

    (3) У любой ссылки есть Метаданные Вы правы но через COM соединение не все можно получить

    ИначеЕсли СтрДлина(_СтрокаXML) = 48 Тогда //Хранилище значения

    если рассматривать как просто отдельная строка то да сказать точно что это хранилище невозможно, но первое стоит проверка на наличие 4 дефисов что говорит о формате строки УИД, если не УИД то хранилище, иначе перечисление по другому я не сталкивался.

    Что касаемо определение Менеджера, то в Вашем примере Вы должны точно знать уже имя менеджера ссылки чтоб произвести замену

    в моем случае мы его знать не должны он определится автоматически.

    Что касаемо самой статьи то я много искал и изучал вопрос и сталкивался с проблемами которые порой не описаны в инете, поэтому и решил поделится информацией. Никто не спорит что коды совершенны и их дорабатывать нельзя)

    Reply
  5. Кадош

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

    Reply
  6. wowik

    Сложная статья для прочтения.

    Когда-то тоже писал про это — https://infostart.ru/public/164976/

    Как по мне, GetObject().Metadata().FullName() — здесь и в других аналогичных местах нужно использовать наименования на русском, глаз режет.

    Reply
  7. ArchLord42

    (5) Очень приятно 🙂 А Вы собственно кто будете? Большой и умный заядлый велосипидист, тот что делает «быстрые одноразовые» обмены ?:)

    К сожалению, повидал на своем маленьком веку такие штуки, надеюсь не скоро еще увижу.

    Reply
  8. acanta

    Ком-соединение для сравнения остатков и оборотов тоже требует и поиска и идентификации объектов, иногда по тем же правилам, которые описаны в конвертации данных.

    Ссылка с гуидом на данные не всегда сохраняется.

    Статья очень полезная, спасибо.

    Reply
  9. Кадош

    (7) абсолютно так. Написал быстренько обработку, загрузил нужные данные, помог заказчику, взял деньги, взял лесопед и пошел кататься. Все довольны — и я и заказчик. А вы сидите, отлаживайте днями ваши обмены, корпите значит. Видал я обмены таких корпунов, когда затирали данные в рабочей базе, надеюсь еще не скоро увижу.

    Reply
  10. ZloyProger

    (2), (5) ИМХО глупый спор коллеги, этому холивару (что лучше КД или Com) уж скоро *цать лет будет, это всё равно что спорить что лучше — микроволновка или холодильник) Разные инструменты, требующие вдумчивого применения есть плюсы и минусы у обоих, в каждом конкретном случае надо подумать что проще/быстрее/лучше/универсальнее применить. Статья хорошая, действительно всё вместе в одном месте собрано. По поводу (6) хотел тоже отметить что сталкивался в своей работе с ситуациями когда .Метаданные() — вызывает ошибку, а .Metadata() нет.. И с обратными тоже сталкивался (причём с обратными ситуациями чаще после 2-й точки.. блин как лучше сформулировать-то, ну типа например РеквCOM.Metadata().TabularSection() — вызывает ошибку, а РеквCOM.Metadata().ТабличныеЧасти() — нет, точно не помню уже ситуаций), в общем так и не понял от чего это зависит, приходится идти иногда на такой «зоопарк»( Если кто знает — поделитесь, буду рад получению новых знаний.

    Reply
  11. John_d

    com-соединения лучше не использовать вообще. (википедия Стандарт COM был разработан в 1993 году корпорацией Microsoft как основа для развития технологии OLE.) Технология 1993 года.

    Переходить на http-сервис

    https://infostart.ru/public/955078/

    Reply
  12. Yashazz

    Ё-моё… И вот за такое — столько плюсов? Мдя. Зря я сюда лет 10 назад все исходники свои не выложил, вот точно хит был бы…

    Пишешь про ком — так хотя б не баянь. Хотя бы интересные моменты опиши. А это, извините, из серии хелло ворлд.

    Холиварчик, кстати, демонстрирует, что опыта маловато у некоторых. Потому как, и это верно было замечено, случаи весьма разные, иногда ПКО накатать быстрее, а иногда ком воткнуть удобнее. И это ооочень разные случаи. Ну и потом, интеграцию с другими приложениями и ранее популярное обращение к служебкам самой 1С — их никто не отменял.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *