Как установить свой уникальный идентификатор (GUID) новому элементу справочника в 1С

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

При интеграции 1С:Предприятия с внешними информационными системами (сайтами, CRM, ERP-системами) разработчики часто сталкиваются с необходимостью синхронизации данных. Лучший способ связать объекты в двух разных базах — использовать единый уникальный идентификатор (UUID/GUID). При импорте данных из XML или JSON файлов нам нужно, чтобы создаваемый в 1С элемент справочника получил точно такой же идентификатор, какой у него был во внешней системе.

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

Суть проблемы и классическое недопонимание

В процессе обсуждения на форумах часто возникает ситуация, когда разработчик пытается передать подготовленную ссылку в метод УстановитьСсылкуНового(), но при просмотре значения в отладчике видит странное представление: (177:9009e840f2b901b811e6d50b578c7c46) вместо привычного формата GUID 578c7c46-d50b-11e6-9009-e840f2b901b8. Из-за этого складывается ложное впечатление, что платформа проигнорировала переданное значение и сгенерировала случайный идентификатор. На самом деле это не так.

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

Пошаговое руководство по установке GUID новому объекту

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

  1. Получить строковое представление GUID из файла XML.
  2. Преобразовать эту строку в объект типа УникальныйИдентификатор.
  3. Сгенерировать пустую ссылку для нужного справочника на основании полученного идентификатора.
  4. Создать новый объект справочника в оперативной памяти (до его записи в базу данных).
  5. Применить метод УстановитьСсылкуНового() к созданному объекту, передав туда подготовленную ссылку.
  6. Заполнить необходимые реквизиты и записать объект в базу данных.

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


// Шаг 1: Получаем строку GUID из внешнего источника
СтрокаGUID = "578c7c46-d50b-11e6-9009-e840f2b901b8";

// Шаг 2: Создаем объект УникальныйИдентификатор
УИД = Новый УникальныйИдентификатор(СтрокаGUID);

// Шаг 3: Получаем ссылку для справочника "Контрагенты" по нашему УИД
НоваяСсылка = Справочники.Контрагенты.ПолучитьСсылку(УИД);

// Шаг 4: Создаем новый элемент справочника в памяти
НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();

// Шаг 5: Связываем новый объект с подготовленной ссылкой
НовыйКонтрагент.УстановитьСсылкуНового(НоваяСсылка);

// Шаг 6: Заполняем реквизиты и производим запись
НовыйКонтрагент.Наименование = "ООО ""Новые Технологии""";
НовыйКонтрагент.ОбменДанными.Загрузка = Истина; // Рекомендуется при импорте данных
НовыйКонтрагент.Записать();

Этот код абсолютно рабочий. После выполнения метода Записать() в базе данных появится новый контрагент именно с тем GUID, который мы передали в самом начале.

Более лаконичный способ через функцию XMLЗначение

Платформа 1С:Предприятие предоставляет встроенную глобальную функцию XMLЗначение(), которая позволяет выполнить преобразование строки во внутренний тип платформы более компактно. Мы можем существенно сократить наш код, избежав ручного создания объекта УникальныйИдентификатор:


СтрокаGUID = "578c7c46-d50b-11e6-9009-e840f2b901b8";

// Быстрое получение ссылки напрямую из строки GUID
НоваяСсылка = XMLЗначение(Тип("СправочникСсылка.Контрагенты"), СтрокаGUID);

НовыйКонтрагент = Справочники.Contragents.СоздатьЭлемент();
НовыйКонтрагент.УстановитьСсылкуНового(НоваяСсылка);
НовыйКонтрагент.Наименование = "ООО ""Ромашка""";
НовыйКонтрагент.Записать();

Этот вариант работает быстрее и лаконичнее, минимизируя промежуточные преобразования типов в кодовой базе.

Разгадка тайны: почему в отладчике отображается "Объект не найден" и странные цифры?

Вернемся к главному сомнению разработчиков. Почему при просмотре переменной НоваяСсылка в табло отладчика до момента записи элемента мы видим надпись вида "Объект не найден (177:9009e840f2b901b811e6d50b578c7c46)"?

Во-первых, надпись "Объект не найден" логична. Объект действительно еще не записан в базу данных физически. Ссылка указывает на пустую ячейку памяти СУБД, где в будущем появится наша запись. Платформа честно предупреждает нас об этом.

Во-вторых, формат представления (177:9009e840f2b901b811e6d50b578c7c46) — это внутреннее представление нетипизированной битой ссылки в СУБД. Давайте разберем его структуру:

Для ускорения поиска по индексам СУБД переставляет байты GUID версии 1 (которые зависят от времени создания). Давайте применим алгоритм обратной перестановки байтов платформы 1С к строке 9009e840f2b901b811e6d50b578c7c46:

  1. Берем символы с 25 по 32 (578c7c46) — они становятся первой группой: 578c7c46.
  2. Берем символы с 21 по 24 (d50b) — они становятся второй группой: d50b.
  3. Берем символы с 17 по 20 (11e6) — они становятся третьей группой: 11e6.
  4. Берем символы с 1 по 4 (9009) — они становятся четвертой группой: 9009.
  5. Берем символы с 5 по 16 (e840f2b901b8) — они становятся пятой группой: e840f2b901b8.

Объединяем полученные группы через дефис: 578c7c46-d50b-11e6-9009-e840f2b901b8. Как мы видим, это в точности соответствует исходному GUID! Платформа ничего не испортила и не изменила, она просто отобразила внутреннее представление бинарного буфера в СУБД.

Для того чтобы убедиться в правильности установки GUID у еще не записанного объекта в коде, используйте следующий метод:


ИдентификаторНового = НовыйКонтрагент.ПолучитьСсылкуНового().УникальныйИдентификатор();
Сообщить(Строка(ИдентификаторНового)); // Выведет привычный "578c7c46-d50b-11e6-9009-e840f2b901b8"

Важные правила работы с методом УстановитьСсылкуНового()

Для успешного применения данного механизма на практике необходимо придерживаться нескольких важных технических правил:

Оптимизация производительности: решение проблемы "двойной записи"

Понимание работы УстановитьСсылкуНового() позволяет существенно оптимизировать производительность системы при создании связанных объектов. Рассмотрим классический пример:

Нам необходимо программно создать нового контрагента и сразу же создать его договор (где контрагент является владельцем договора), а затем записать этот договор в реквизит контрагента ОсновнойДоговор.

Без использования метода УстановитьСсылкуНового() нам пришлось бы совершить двойную запись контрагента:

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

С помощью механизма предварительной генерации ссылок мы можем связать объекты прямо в оперативной памяти и записать каждый из них в базу данных СУБД ровно один раз:


// Генерируем уникальные идентификаторы заранее
УИДКонтрагента = Новый УникальныйИдентификатор();
УИДДоговора = Новый УникальныйИдентификатор();

СсылкаКонтрагента = Справочники.Контрагенты.ПолучитьСсылку(УИДКонтрагента);
СсылкаДоговора = Справочники.ДоговорыКонтрагентов.ПолучитьСсылку(УИДДоговора);

// Создаем договор в памяти и сразу указываем ссылку контрагента-владельца
НовыйДоговор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
НовыйДоговор.УстановитьСсылкуНового(СсылкаДоговора);
НовыйДоговор.Владелец = СсылкаКонтрагента;
НовыйДоговор.Наименование = "Основной договор";
НовыйДоговор.Записать(); // Первая запись в БД (Договор)

// Создаем контрагента в памяти и сразу ссылаемся на еще не записанный в СУБД договор
НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();
НовыйКонтрагент.УстановитьСсылкуНового(СсылкаКонтрагента);
НовыйКонтрагент.Наименование = "ООО ""Партнер""";
НовыйКонтрагент.ОсновнойДоговор = СсылкаДоговора;
НовыйКонтрагент.Записать(); // Вторая запись в БД (Контрагент)

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

← На главную