Как получить уникальные идентификаторы (UUID) значений перечислений в 1С для SQL-запросов?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При настройке интеграции 1С с внешними системами или при написании прямых SQL-запросов к базе данных разработчики часто сталкиваются с серьезной проблемой. Нам необходимо сопоставить конкретные значения перечислений (например, Перечисления.ХозяйственныеОперации.АвансовыйОтчет) с их физическим представлением в СУБД. В отличие от справочников или документов, у объектов типа ПеречислениеСсылка в платформе 1С отсутствует стандартный метод УникальныйИдентификатор(). Из-за этого стандартные способы получения UUID не работают.

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

Как перечисления физически хранятся в СУБД

Существует заблуждение, что перечисления хранятся исключительно в метаданных и не имеют собственных таблиц в базе данных СУБД. На самом деле в СУБД для каждого перечисления создается физическая таблица.

Давайте проанализируем структуру этой таблицы:

Главная сложность: В СУБД отсутствуют понятные текстовые имена (например, "АвансовыйОтчет" или "БезНДС"). Там содержатся только бинарные UUID и числовой порядок. Чтобы сопоставить текстовые имена элементов конфигурации с их бинарными идентификаторами в SQL, нам необходимо программно выгрузить связи "Имя — UUID". Ниже мы разберем, как это сделать.

Способ №1. Декодирование строки ЗначениеВСтрокуВнутр()

Этот способ основан на использовании системной функции ЗначениеВСтрокуВнутр(). Если передать в нее ссылку на значение перечисления, мы получим строковое представление системного формата 1С.

Рассмотрим конкретный пример. Вызов функции:


Сообщить(ЗначениеВСтрокуВнутр(Перечисления.ХозяйственныеОперации.АвансовыйОтчет));

Вернет следующую строку:

{"#",ae0f3889-6e23-4a7a-bf5d-cd197ab78fb7,1523:b4ea6960515f917b461f6aa3f786c0b6}

Разберем структуру полученных данных:

Чтобы преобразовать эту строку в стандартный UUID формата 8-4-4-4-12, выполним пошаговую перестановку символов. Разобьем 32-символьный хвост b4ea6960515f917b461f6aa3f786c0b6 на 5 блоков:

  1. Блок 1 (символы 1-4): b4ea
  2. Блок 2 (символы 5-16): 6960515f917b
  3. Блок 3 (символы 17-20): 461f
  4. Блок 4 (символы 21-24): 6aa3
  5. Блок 5 (символы 25-32): f786c0b6

Склеим блоки в правильной последовательности: [Блок 5]-[Блок 4]-[Блок 3]-[Блок 1]-[Блок 2]. В результате мы получаем:

f786c0b6-6aa3-461f-b4ea-6960515f917b

Этот результат полностью совпадает с UUID из XML-файла конфигурации! Напишем готовую функцию для автоматического декодирования:


Функция ПолучитьUUIDИзВнутреннейСтроки(СсылкаПеречисления) Экспорт
    
    ВнутренняяСтрока = ЗначениеВСтрокуВнутр(СсылкаПеречисления);
    
    // Находим позицию двоеточия, после которого идет нужный нам хвост
    ПозицияДвоеточия = Найти(ВнутренняяСтрока, ":");
    Если ПозицияДвоеточия = 0 Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    // Вырезаем 32 символа идентификатора
    Хвост = Сред(ВнутренняяСтрока, ПозицияДвоеточия + 1, 32);
    
    // Разбиваем на блоки согласно алгоритму перестановки байт 1С
    Блок1 = Сред(Хвост, 1, 4);
    Блок2 = Сред(Хвост, 5, 12);
    Блок3 = Сред(Хвост, 17, 4);
    Блок4 = Сред(Хвост, 21, 4);
    Блок5 = Сред(Хвост, 25, 8);
    
    // Собираем стандартный GUID
    СтандартныйUUID = Блок5 + "-" + Блок4 + "-" + Блок3 + "-" + Блок1 + "-" + Блок2;
    
    Возврат НРег(СтандартныйUUID);
    
КонецФункции

Способ №2. XML-сериализация (Рекомендуемый способ)

Хотя первый способ отлично работает, функция ЗначениеВСтрокуВнутр() является недокументированной, а структура возвращаемой ею строки теоретически может измениться в будущих версиях платформы.

Существует полностью легальный, безопасный и крайне элегантный способ получить UUID значения перечисления — использовать штатные механизмы XML-сериализации. Если стандартная функция XMLСтрока(СсылкаПеречисления) возвращает лишь имя элемента (например, "БезНДС"), то принудительная выгрузка через объект ЗаписьXML возвращает полноценный UUID.

Рассмотрим пример кода, реализующий этот подход:


Функция ПолучитьUUIDЧерезXML(СсылкаПеречисления) Экспорт
    
    // Создаем объект записи XML и настраиваем вывод в строку
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    
    // Записываем ссылку перечисления в XML-формате
    ЗаписатьXML(ЗаписьXML, СсылкаПеречисления);
    СтрокаXML = ЗаписьXML.Закрыть();
    
    // На выходе получаем строку вида:
    // <Value xsi:type="EnumRef.ХозяйственныеОперации">f786c0b6-6aa3-461f-b4ea-6960515f917b</Value>
    
    // Извлекаем UUID с помощью простых строковых функций
    ПозицияНачала = Найти(СтрокаXML, ">") + 1;
    ПозицияКонца = Найти(СтрокаXML, "</");
    
    Если ПозицияНачала > 1 И ПозицияКонца > ПозицияНачала Тогда
        Возврат Сред(СтрокаXML, ПозицияНачала, ПозицияКонца - ПозицияНачала);
    КонецЕсли;
    
    Возврат "";
    
КонецФункции

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

Автоматическое создание таблицы соответствий

Теперь решим главную практическую задачу: как автоматически сформировать таблицу соответствий "Имя значения" — "UUID" для перечислений, содержащих сотни элементов (например, ХозяйственныеОперации), чтобы использовать ее при построении SQL-запросов или выгрузке во внешнюю СУБД.

Напишем процедуру, которая обходит все значения метаданных перечисления и заполняет результирующую таблицу значений:


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

Как использовать результат

Полученную таблицу соответствий вы можете:

  1. Записать во временную или постоянную таблицу в вашей внешней СУБД (например, MS SQL Server, PostgreSQL).
  2. Использовать оператор JOIN в прямых SQL-запросах для связи таблиц документов или регистров с таблицей перевода UUID в человекочитаемые имена, полностью отказавшись от громоздких конструкций CASE WHEN ... THEN.
  3. Передавать во внешние BI-системы (например, Power BI, ClickHouse) для построения аналитической отчетности.

Использование XML-сериализации позволяет динамически обновлять данные соответствий при каждом запуске системы или по регламентному заданию, что исключает рассинхронизацию при добавлении новых значений перечисления разработчиками 1С.

← На главную