При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью получения уникального идентификатора (GUID) объекта — для этого есть утилита для работы с GUID предопределенных данных. Если для справочников или документов эта задача решается стандартными методами, то с перечислениями возникают определенные трудности. В данной статье мы подробно разберем, почему перечисления ведут себя иначе, и рассмотрим эффективные способы получения их идентификаторов — как для конкретных значений, так и для самих объектов метаданных.
Рассмотрим стандартную ситуацию: нам нужен строковый идентификатор ссылки. Для справочника мы бы использовали метод Ссылка.УникальныйИдентификатор() или функцию XMLСтрока(Ссылка). Однако в случае с перечислениями ситуация иная:
УникальныйИдентификатор() для перечислений в некоторых версиях платформы может возвращать пустой результат или вовсе быть недоступным, так как перечисления являются статичными объектами метаданных.XMLСтрока() применительно к перечислению возвращает не его GUID, а его имя (строковый идентификатор, заданный в конфигураторе).Для решения задачи нам придется обратиться к внутренним механизмам платформы и научиться работать с внутренним представлением объектов — в этом помогут инструменты разработчика для анализа структуры метаданных.
Одним из самых надежных способов «вытащить» идентификатор является использование системной функции ЗначениеВСтрокуВнутр(). Эта функция возвращает строковое представление объекта в специальном формате 1С, который содержит в себе идентификатор типа и идентификатор конкретной ссылки.
Проанализируем структуру строки, которую возвращает эта функция для значения перечисления. Она выглядит примерно так: {"#", <ID_Типа>, {<ID_Значения>}}. Если нам нужно проверить уникальность типа метаданных (самого перечисления), мы можем использовать менеджер перечисления.
Пример получения идентификатора менеджера (типа):
// Получаем внутреннюю строку для всего перечисления "ДниНедели"
ВнутренняяСтрока = ЗначениеВСтрокуВнутр(Перечисления.ДниНедели);
Сообщить(ВнутренняяСтрока);
Этот способ позволяет получить уникальный маркер типа данных, который можно использовать для сравнения или логгирования.
Если задача стоит сложнее — получить именно GUID конкретного значения (например, Перечисления.ДниНедели.Пятница) в стандартном формате (RFC 4122), нам потребуется написать небольшую функцию-парсер — удобнее через консоль для написания и отладки кода в Предприятии.
Выясним причину, по которой нельзя просто «вырезать» кусок строки из внутреннего представления. Дело в том, что в строке internal format байты GUID записаны в специфическом порядке, который отличается от общепринятого визуального представления идентификатора. Чтобы получить корректный GUID, который поймут внешние системы или SQL, байты нужно переставить.
Рассмотрим готовую функцию для решения этой задачи:
Функция ПолучитьGUIDИзПеречисления(Ссылка) Экспорт
// Получаем внутреннее представление ссылки
СтрокаВнутр = ЗначениеВСтрокуВнутр(Ссылка);
// Убираем лишние символы фигурных скобок
СтрокаБуфер = СтрЗаменить(СтрЗаменить(СтрокаВнутр, "}", ""), "{", "");
// Разбиваем строку по запятым.
// Обычно ID значения находится в третьем сегменте (индекс 2 в массиве)
ЧастиСтроки = СтрРазделить(СтрокаБуфер, ",");
Если ЧастиСтроки.Количество() < 3 Тогда
Возврат "";
КонецЕсли;
СтрокаИД = ЧастиСтроки[2];
// Извлекаем часть после двоеточия (непосредственно шестнадцатеричный код)
ПозицияДвоеточия = СтрНайти(СтрокаИД, ":");
Если ПозицияДвоеточия > 0 Тогда
СтрокаИД = Сред(СтрокаИД, ПозицияДвоеточия + 1);
КонецЕсли;
// Теперь выполняем перестановку байтов согласно логике хранения GUID в 1С
// Формат GUID: 8-4-4-4-12 символов
Результат = Прав(СтрокаИД, 8) + "-" +
Сред(СтрокаИД, 21, 4) + "-" +
Сред(СтрокаИД, 17, 4) + "-" +
Лев(СтрокаИД, 4) + "-" +
Сред(СтрокаИД, 5, 12);
Возврат Результат;
КонецФункции
Проанализируем работу этой функции: она берет «сырой» набор символов из внутреннего представления и переставляет блоки Прав, Сред и Лев так, чтобы на выходе получилась валидная строка идентификатора. Именно такой подход позволяет получить тот же результат, который мы видим при выгрузке базы в XML или в таблицах СУБД.
Разберем еще несколько важных технических аспектов, которые помогут в работе:
ЗаписьXML. При сериализации объекта перечисления в XML-файл, платформа записывает идентификаторы в явном виде._Enum<N>. Важно понимать, что в самих таблицах документов или справочников ссылки на перечисления часто хранятся не как полные GUID, а как порядковые номера (индексы). Однако в системной таблице DBSchema или Config описание перечисления содержит его настоящий uuid.Enums для каждого перечисления будет создан XML-файл, в начале которого в теге uuid указан искомый идентификатор.Важный совет: Помните, что использование ЗначениеВСтрокуВнутр и последующий парсинг — это «хак», основанный на знании внутреннего формата 1С. Несмотря на то, что этот формат не менялся десятилетиями, официально он не документирован. Используйте этот метод в тех случаях, когда другие средства (например, сопоставление по имени через XMLСтрока) не подходят по условиям задачи — для таких сценариев есть ETL-система для загрузки данных из внешних СУБД.
Подводя итог, можно сказать, что наиболее универсальным программным способом получения GUID для перечисления является разбор внутренней строки с перестановкой байтов. Это гарантирует получение идентификатора, совместимого с внешними информационными системами — задача решается через модуль организации обмена данными по идентификаторам.