Получение значений перечислений через внешнее соединение или Automation сервер

Раздел содержит описание особенностей получения и использования значений перечислений 1С:Предприятия через внешнее соединение или Automation сервер 1С:Предприятия.

Системные перечисления и их элементы

Системные перечисления предназначены для определения некоторого набора предопределенных значений и используются в качестве значений параметров некоторых методов, а также в качестве значений некоторых свойств объектов 1С:Педприятия. Доступ к системным перечислениям осуществляется как к свойствам глобального контекста. Значения элементов системных перечислений указываются через точку от имени системного перечисления. Например:

Копировать в буфер обмена
ОбъектДокумент.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный);

В качестве значений параметров метода Записать() заданы два значения элементов системных перечислений: элемент "Проведение" системного перечисления "РежимЗаписиДокумента" и элемент "Оперативный" системного перечисления "РежимПроведенияДокумента".

И системные перечисления, и значения их элементов являются объектами, и могут быть переданы в другие приложения через COM посредством интерфейса IDispatch. При этом любое системное перечисление имеет набор свойств, каждое из которых позволяет получить соответствующее значение элемента данного системного перечисления. Элемент системного перечисления также является объектом и доступен через интерфейс IDispatch, однако ни свойств, ни методов он не имеет.

По этой причине анализ полученных значений системных перечислений возможен только посредством их сравнения со значениями системных перечислений, полученными через свойства глобального контекста. Например, на встроенном языке 1С:Предприятия проверка значений системных перечислений, полученных через внешнее соединение, может быть выполнена так:

Копировать в буфер обмена
// Элемент системного перечисления как собственный объект 1С:Предприятия
ЭлементПеречисления = Метаданные.Справочники.Справочник1.ВидИерархии;
Сообщить(ЭлементПеречисления);

// Элемент системного перечисления, полученный через COM.
Соединитель = Новый COMОбъект("V8.COMConnector");
Соединение = Соединитель.connect("File=c:\InfoBaseDirectory");
ЭлементПеречисления = Соединение.Метаданные.Справочники.Справочник1.ВидИерархии;
// Здесь будет выведено "COMОбъект".
Сообщить(ЭлементПеречисления);
// Образцы значений элементов системного перечисления для сравнения нужно получить
// из того же COM соединения.
Образцы = Соединение.Метаданные.СвойстваОбъектов.ВидИерархии;
Если ЭлементПеречисления = Образцы.ИерархияГруппИЭлементов Тогда
    Сообщить("ИерархияГруппИЭлементов");
ИначеЕсли ЭлементПеречисления = Образцы.ИерархияЭлементов Тогда
    Сообщить("ИерархияЭлементов");
КонецЕсли;

Важно иметь в виду, что значения одних и тех же системных перечислений, полученные из разных экземпляров клиентского приложения или внешнего соединения 1С:Предприятия, являются разными объектами и между собой несравнимы.

Перечисления, определенные в конфигурации

В отличие от системных перечислений, определенные в конфигурации перечисления являются объектами базы данных. Элемент такого перечисления является ссылкой на объект базы данных. Например, если в конфигурации определено перечисление "Перечисление1" с элементами "ЗначениеПеречисления1" и "ЗначениеПеречисления2", а реквизит "Реквизит1" справочника "Справочник1" имеет тип "ПеречислениеСсылка.Перечисление1", то следующий код на встроенном языке 1С:Предприятия:

Копировать в буфер обмена
ЭлементПеречисления1 = Перечисления.Перечисление1.ЗначениеПеречисления1;
Сообщить(ЭлементПеречисления1);
ЭлементПеречисления2 = Справочники.Справочник1.НайтиПоКоду(1).Реквизит1;
Сообщить(ЭлементПеречисления2);
Если ЭлементПеречисления1 = ЭлементПеречисления2 Тогда
    Сообщить("Равно");
Иначе
    Сообщить("Не равно");
КонецЕсли;

выведет "Равно", если значением реквизита "Реквизит1" является "ЗначениеПеречисления1" и "Не равно" в противном случае.

Однако если значение элемента перечисления получить через внешнее соединение, то оно будет являться COM объектом, и подобное сравнение будет всегда приводить к отрицательному результату. Например, следующий код на встроенном языке 1С:Предприятия:

Копировать в буфер обмена
Соединитель = Новый COMОбъект("V8.COMConnector");
Соединение = Соединитель.connect("File=c:\InfoBaseDirectory");
ЭлементПеречисления1 = Соединение.Перечисления.Перечисление1.ЗначениеПеречисления1;
Сообщить(ЭлементПеречисления1);
ЭлементПеречисления2 = Соединение.Справочники.Справочник1.НайтиПоКоду(1).Реквизит1;
Сообщить(ЭлементПеречисления2);
Если ЭлементПеречисления1 = ЭлементПеречисления2 Тогда
    Сообщить("Равно");
Иначе
    Сообщить("Не равно");
КонецЕсли;

будет всегда выводить "Не равно". Это происходит потому, что значение элемента перечисления является объектом типа ссылка на объект базы данных. Для объектов ссылок определена операция сравнения значений, которая может работать только для "своих" объектов 1С:Предприятия. Объекты, полученные через внешнее соединение "своими" не являются, поэтому операция их сравнения является проверкой идентичности. Поскольку для объектов ссылок идентичность не поддерживается, их сравнение может дать отрицательный результат, даже если значения ссылок, заключенные в этих объектах, одинаковые.

Для сравнения значений элементов перечислений, определенных в конфигурации, необходимо выполнить преобразование этих элементов к одному из примитивных типов, сравнение которых не вызывает трудности. Такими типами могут быть либо числовой, либо строковый тип. Преобразовать значение элемента перечисления к числовому типу можно так:

Копировать в буфер обмена
Соединитель = Новый COMОбъект("V8.COMConnector");
Соединение = Соединитель.connect("File=c:\InfoBaseDirectory");
ЭлементПеречисления = Соединение.Справочники.Справочник1.НайтиПоКоду(1).Реквизит1;
ВозможныеЗначения = ЭлементПеречисления.Метаданные().ЗначенияПеречисления;
НомерЭлементаПеречисления = ВозможныеЗначения.Индекс(ВозможныеЗначения.Найти(Соединение.XMLString(ЭлементПеречисления)));
Если НомерЭлементаПеречисления = 0 Тогда
    Сообщить("ЗначениеПеречисления1");
ИначеЕсли НомерЭлементаПеречисления = 1 Тогда
    Сообщить("ЗначениеПеречисления2");
КонецЕсли;

Если тип перечисления, значение которого может содежать переменная "ЭлементПеречисления", известен заранее, то приведенный выше пример может быть записан проще:

Копировать в буфер обмена
НомерЭлементаПеречисления = Соединение.Перечисления.Перечисление1.Индекс(ЭлементПеречисления);

Значение элемента перечисления может быть приведено к строковому типу, например, при помощи следующего фрагмента кода на встроенном языке 1С:Предприятия:

Копировать в буфер обмена
Соединитель = Новый COMОбъект("V8.COMConnector");
Соединение = Соединитель.connect("File=c:\InfoBaseDirectory");
ЭлементПеречисления = Соединение.Справочники.Справочник1.НайтиПоКоду(1).Реквизит1;
СтрокаЭлементПеречисления = ЭлементПеречисления.Метаданные().Имя;
СтрокаЭлементПеречисления = СтрокаЭлементПеречисления + "." + Соединение.XMLString(ЭлементПеречисления);
Сообщить(СтрокаЭлементПеречисления);