Уникальный идентификатор 1С — значение типа УникальныйИдентификатор (UUID, он же GUID) из 36 символов вида b1e4c6a0-1234-11e9-80c6-00155d000a01. Такой GUID хранится в каждой ссылке на справочник, документ, план видов характеристик и другой ссылочный объект. Код и номер можно перенумеровать, а GUID остаётся с объектом навсегда, поэтому на нём строят обмены, интеграцию с сайтом и поиск по внешнему ключу.
Примеры рассчитаны на платформу 8.3 и написаны для модуля формы. В серверном общем модуле уберите директивы компиляции, а Номенклатура и ХарактеристикиНоменклатуры замените на объекты своей конфигурации.
| Задача | Код | Результат |
|---|---|---|
| Новый GUID | Новый УникальныйИдентификатор | УникальныйИдентификатор |
| GUID ссылки | Ссылка.УникальныйИдентификатор() | УникальныйИдентификатор |
| GUID строкой | Строка(УИД), XMLСтрока(Ссылка) | Строка, 36 символов |
| GUID из строки | Новый УникальныйИдентификатор(ТекстУИД) | УникальныйИдентификатор |
| Ссылка по GUID | Справочники.Номенклатура.ПолучитьСсылку(УИД) | СправочникСсылка |
| Ссылка по строке и типу | XMLЗначение(Тип("СправочникСсылка.Номенклатура"), ТекстУИД) | СправочникСсылка |
&НаСервереБезКонтекста
Процедура ОсновныеОперацииСУИД()
// Новый случайный GUID и его строковое представление
УИД = Новый УникальныйИдентификатор;
ТекстУИД = Строка(УИД); // 36 символов, строчные буквы, дефисы
Сообщить("Новый GUID: " + ТекстУИД);
// Из строки обратно в УникальныйИдентификатор
УИДИзТекста = Новый УникальныйИдентификатор(ТекстУИД);
Если УИДИзТекста = УИД Тогда
Сообщить("Значения совпадают: GUID сравниваются по содержимому");
КонецЕсли;
// GUID существующей ссылки
Ссылка = Справочники.Номенклатура.НайтиПоНаименованию("Доставка");
Если ЗначениеЗаполнено(Ссылка) Тогда
УИДСсылки = Ссылка.УникальныйИдентификатор(); // объект из базы не читается
Сообщить("GUID элемента: " + Строка(УИДСсылки));
КонецЕсли;
// У пустой ссылки GUID из нулей: 00000000-0000-0000-0000-000000000000
ПустойУИД = Справочники.Номенклатура.ПустаяСсылка().УникальныйИдентификатор();
Сообщить("Пустая ссылка: " + Строка(ПустойУИД));
// GUID нового элемента до записи: ссылку назначаем заранее
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор);
НовыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);
УИДДоЗаписи = НовыйЭлемент.ПолучитьСсылкуНового().УникальныйИдентификатор();
Сообщить("GUID до записи: " + Строка(УИДДоЗаписи));
КонецПроцедуры
Строка(УИД) выдаёт GUID строчными буквами с дефисами — в таком виде его и передавайте во внешние системы.УникальныйИдентификатор() — метод ссылки, а не глобальная функция. GUID хранится внутри ссылки, поэтому вызов не читает объект из базы. У документа то же самое: ДокументСсылка.УникальныйИдентификатор().УникальныйИдентификатор сравниваются по содержимому, поэтому условие УИДИзТекста = УИД истинно.Объект.Ссылка пустая, и её GUID состоит из нулей. Если идентификатор нужен заранее (приложить файл, отправить заказ на сайт), назначьте ссылку через УстановитьСсылкуНового и читайте её методом ПолучитьСсылкуНового().Конструктор Новый УникальныйИдентификатор(Текст) вызывает исключение, если строка не в формате GUID. При загрузке тысяч записей удобнее проверить формат заранее и получить Неопределено вместо ошибки:
// Строку в УникальныйИдентификатор без исключений.
// Неопределено — если это не GUID или GUID из нулей.
&НаСервереБезКонтекста
Функция СтрокаВУИД(Знач ТекстУИД)
Если ТипЗнч(ТекстУИД) <> Тип("Строка") Тогда
Возврат Неопределено;
КонецЕсли;
// GUID бывает в фигурных скобках, с пробелами и в верхнем регистре
ТекстУИД = СтрЗаменить(СтрЗаменить(ТекстУИД, "{", ""), "}", "");
ТекстУИД = НРег(СокрЛП(ТекстУИД));
Если СтрДлина(ТекстУИД) <> 36
Или ТекстУИД = "00000000-0000-0000-0000-000000000000" Тогда
Возврат Неопределено;
КонецЕсли;
Для Позиция = 1 По 36 Цикл
Символ = Сред(ТекстУИД, Позиция, 1);
Если Позиция = 9 Или Позиция = 14 Или Позиция = 19 Или Позиция = 24 Тогда
Если Символ <> "-" Тогда
Возврат Неопределено;
КонецЕсли;
ИначеЕсли СтрНайти("0123456789abcdef", Символ) = 0 Тогда
Возврат Неопределено;
КонецЕсли;
КонецЦикла;
Возврат Новый УникальныйИдентификатор(ТекстУИД);
КонецФункции
Если формат строки гарантирован, хватит конструктора внутри Попытка … Исключение … КонецПопытки.
Метод менеджера ПолучитьСсылку(УИД) не обращается к базе и возвращает ссылку всегда, даже если объекта с таким GUID нет. Такая «битая» ссылка непустая: ЗначениеЗаполнено() для неё возвращает Истина, а в форме она выглядит как <Объект не найден>. Существование проверяют запросом, и функция подходит для любого ссылочного типа:
// Истина, если объект по ссылке есть в базе.
// Для «битой» ссылки ЗначениеЗаполнено() тоже вернёт Истина.
&НаСервереБезКонтекста
Функция СсылкаСуществует(Ссылка)
Если Не ЗначениеЗаполнено(Ссылка) Тогда
Возврат Ложь;
КонецЕсли;
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА КАК Найден
|ИЗ
| #Таблица КАК Т
|ГДЕ
| Т.Ссылка = &Ссылка";
Запрос = Новый Запрос;
Запрос.Текст = СтрЗаменить(ТекстЗапроса, "#Таблица", Ссылка.Метаданные().ПолноеИмя());
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Возврат Не Запрос.Выполнить().Пустой();
КонецФункции
Ссылка.Метаданные().ПолноеИмя() возвращает имя таблицы вида Справочник.Номенклатура или Документ.ЗаказКлиента, его и подставляем в текст запроса.ВЫБРАТЬ ПЕРВЫЕ 1 вместе с Пустой() — самая дешёвая проверка: запись ищется по индексу, объект целиком не загружается.Поиск элемента по строке GUID из внешней системы теперь занимает несколько строк:
// Элемент справочника по GUID из внешней системы.
// Пустая ссылка — если GUID некорректен или объекта нет в базе.
&НаСервереБезКонтекста
Функция НоменклатураПоУИД(Знач ТекстУИД)
УИД = СтрокаВУИД(ТекстУИД);
Если УИД = Неопределено Тогда
Возврат Справочники.Номенклатура.ПустаяСсылка();
КонецЕсли;
// ПолучитьСсылку не обращается к базе и возвращает ссылку всегда
Ссылка = Справочники.Номенклатура.ПолучитьСсылку(УИД);
Если Не СсылкаСуществует(Ссылка) Тогда
Возврат Справочники.Номенклатура.ПустаяСсылка();
КонецЕсли;
Возврат Ссылка;
КонецФункции
Проверка Ссылка.ПолучитьОбъект() = Неопределено тоже работает, но читает объект со всеми табличными частями. Её выбирайте, когда объект всё равно нужен для записи, как в загрузке ниже.
В языке запросов нет функции, которая вернёт GUID ссылки, а поле Ссылка сравнивают только со ссылкой. Поэтому строки GUID превращают в ссылки в коде и передают в запрос массивом — весь пакет из обмена проверяется за одно обращение к базе:
// Проверяет пачку GUID одним запросом.
// Соответствие: ключ — GUID строкой, значение — ссылка.
// GUID, которых нет в базе, в результат не попадают.
&НаСервереБезКонтекста
Функция НайтиНоменклатуруПоСпискуУИД(СписокУИД)
МассивСсылок = Новый Массив;
Для Каждого ТекстУИД Из СписокУИД Цикл
УИД = СтрокаВУИД(ТекстУИД);
Если УИД <> Неопределено Тогда
МассивСсылок.Добавить(Справочники.Номенклатура.ПолучитьСсылку(УИД));
КонецЕсли;
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&МассивСсылок)";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Найденные = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Найденные.Вставить(Строка(Выборка.Ссылка.УникальныйИдентификатор()), Выборка.Ссылка);
КонецЦикла;
Возврат Найденные;
КонецФункции
Найденные.Получить(Строка(СтрокаВУИД(Текст))).УникальныйИдентификатор, например GUID товара на сайте, его сравнивают с параметром того же типа прямо в условии: ГДЕ Номенклатура.ИдентификаторНаСайте = &УИД.Надёжная схема обмена: 1С выгружает на сайт GUID товара, сайт возвращает его в заказах, и 1С находит товар без поиска по наименованию или артикулу. Если пришёл объект, которого в базе нет, его создают с тем же GUID — повторная загрузка обновит элемент, а не создаст дубль:
// Создаёт или обновляет товар с тем же GUID, что пришёл с сайта.
&НаСервереБезКонтекста
Функция ЗагрузитьТоварССайта(Знач ТекстУИД, Знач Наименование)
УИД = СтрокаВУИД(ТекстУИД);
Если УИД = Неопределено Тогда
ВызватьИсключение СтрШаблон("Некорректный GUID товара: %1", ТекстУИД);
КонецЕсли;
Ссылка = Справочники.Номенклатура.ПолучитьСсылку(УИД);
Объект = Ссылка.ПолучитьОбъект(); // Неопределено, если объекта нет
Если Объект = Неопределено Тогда
Объект = Справочники.Номенклатура.СоздатьЭлемент();
Объект.УстановитьСсылкуНового(Ссылка); // элемент получит GUID с сайта
КонецЕсли;
Объект.Наименование = Наименование;
Объект.Записать();
Возврат Объект.Ссылка;
КонецФункции
ПолучитьОбъект() для несуществующего объекта возвращает Неопределено — это и есть проверка «новый или уже загружен».УстановитьСсылкуНового(Ссылка) работает только для нового объекта до первой записи. После Записать() элемент получает ровно тот GUID, который прислал сайт.В CommerceML Ид предложения с характеристикой записывают как «GUID товара#GUID характеристики». Разбор такого идентификатора:
// Разбирает Ид предложения CommerceML вида "GUIDтовара#GUIDхарактеристики".
&НаСервереБезКонтекста
Функция РазобратьИдПредложения(Знач ИдПредложения)
Результат = Новый Структура;
Результат.Вставить("Номенклатура", Справочники.Номенклатура.ПустаяСсылка());
Результат.Вставить("Характеристика", Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка());
Части = СтрРазделить(ИдПредложения, "#");
Если Части.Количество() = 0 Тогда
Возврат Результат;
КонецЕсли;
УИДТовара = СтрокаВУИД(Части[0]);
Если УИДТовара <> Неопределено Тогда
Результат.Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(УИДТовара);
КонецЕсли;
Если Части.Количество() > 1 Тогда
УИДХарактеристики = СтрокаВУИД(Части[1]);
Если УИДХарактеристики <> Неопределено Тогда
Результат.Характеристика =
Справочники.ХарактеристикиНоменклатуры.ПолучитьСсылку(УИДХарактеристики);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция только строит ссылки. Перед созданием заказа проверьте их существование пакетно, как в разделе про запрос.
У каждой управляемой формы есть свойство УникальныйИдентификатор. Его передают вторым параметром в ПоместитьВоВременноеХранилище, чтобы данные жили, пока форма открыта. Новый GUID в параметре «Уникальность» метода ОткрытьФорму открывает ещё одну копию формы вместо активации уже открытой:
// Модуль формы. Реквизит формы АдресДанных имеет тип Строка.
&НаКлиенте
Процедура ОткрытьЕщеОднуКопию(Команда)
// Новый GUID в параметре «Уникальность» — каждый раз отдельное окно
ОткрытьФорму("Обработка.ЗагрузкаССайта.Форма", , ЭтотОбъект, Новый УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Процедура ПодготовитьДанныеНаСервере()
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления");
Таблица = Запрос.Выполнить().Выгрузить();
// УникальныйИдентификатор здесь — свойство формы:
// таблица хранится, пока открыта эта форма
АдресДанных = ПоместитьВоВременноеХранилище(Таблица, УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Функция КоличествоПодготовленныхСтрок()
Если Не ЭтоАдресВременногоХранилища(АдресДанных) Тогда
Возврат 0;
КонецЕсли;
Таблица = ПолучитьИзВременногоХранилища(АдресДанных);
Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Тогда
Возврат 0;
КонецЕсли;
Возврат Таблица.Количество();
КонецФункции
УникальныйИдентификатор без Новый — это GUID самой формы, он не меняется, пока форма открыта.ЭтоАдресВременногоХранилища отсекает пустой адрес, а проверка типа — случай, когда данных в хранилище уже нет.ПолучитьНавигационнуюСсылку(Ссылка) возвращает строку вида e1cib/data/Справочник.Номенклатура?ref=80c600155d000a0111e91234b1e4c6a0. В параметре ref тот же GUID b1e4c6a0-1234-11e9-80c6-00155d000a01, но без дефисов и с группами в порядке хранения в базе: четвёртая, пятая, третья, вторая, первая. Обратное преобразование:
// Ссылка на номенклатуру из навигационной ссылки вида
// e1cib/data/Справочник.Номенклатура?ref=80c600155d000a0111e91234b1e4c6a0
&НаСервереБезКонтекста
Функция НоменклатураИзНавигационнойСсылки(Знач ТекстСсылки)
Маркер = "Справочник.Номенклатура?ref=";
Позиция = СтрНайти(ТекстСсылки, Маркер);
Если Позиция = 0 Тогда
Возврат Справочники.Номенклатура.ПустаяСсылка();
КонецЕсли;
// 32 символа без дефисов, группы GUID идут в порядке 4, 5, 3, 2, 1
Ид = НРег(Сред(ТекстСсылки, Позиция + СтрДлина(Маркер), 32));
ТекстУИД = Сред(Ид, 25, 8) + "-" + Сред(Ид, 21, 4) + "-" + Сред(Ид, 17, 4)
+ "-" + Сред(Ид, 1, 4) + "-" + Сред(Ид, 5, 12);
// Формат и существование проверяет функция НоменклатураПоУИД
Возврат НоменклатураПоУИД(ТекстУИД);
КонецФункции
Маркер с именем таблицы не даёт превратить GUID документа в ссылку на справочник. Ссылку, скопированную из адресной строки браузера, сначала раскодируйте: РаскодироватьСтроку(Текст, СпособКодированияСтроки.КодировкаURL).
УникальныйИдентификатор(Ссылка) написали как глобальную функцию. Такой функции нет, нужен метод ссылки: Ссылка.УникальныйИдентификатор().СтрокаВУИД.Неопределено: например, из JSON пришёл текст, а не ссылка. Тип проверяйте через ТипЗнч.<Объект не найден> в поле формы. Ссылку получили по GUID, которого нет в таблице: объект удалён или GUID документа передали менеджеру справочника. ЗначениеЗаполнено такую ссылку не отсекает, нужна СсылкаСуществует.Строка(Ссылка) возвращает представление объекта, а GUID — Строка(Ссылка.УникальныйИдентификатор()) или XMLСтрока(Ссылка).00000000-0000-0000-0000-000000000000 — это пустая ссылка. Если внешняя система прислала его вместо реального идентификатора, связь с объектом теряется без всякой ошибки.Ключ = УникальныйИдентификатор;, ожидая новое значение, а получили идентификатор формы. Нужен Новый УникальныйИдентификатор.Нет. Ссылка назначается при первой записи и дальше не меняется, а УстановитьСсылкуНового действует только для нового объекта. Если нужен другой GUID, создайте копию с нужной ссылкой, замените на неё ссылки в базе и пометьте старый элемент на удаление.
В копии базы (выгрузка .dt, копия каталога файловой базы) совпадают у всех объектов. В независимо созданных базах — нет, даже при одинаковых наименованиях. При обмене GUID сохраняется, только если правила создают объекты через УстановитьСсылкуНового или ведут таблицу соответствий.
Случайно — практически нет, но при загрузке через УстановитьСсылкуНового такое возможно: уникальность обеспечивается только внутри таблицы объекта. Поэтому во внешней системе храните рядом с GUID и тип, например Справочник.Номенклатура или Документ.ЗаказКлиента.
Если внешняя система отдаёт настоящий GUID, подойдёт тип УникальныйИдентификатор: он компактнее строки и не примет значение неверного формата. Числовые и произвольные идентификаторы сайта храните в строковом реквизите или в регистре сведений «объект — внешний идентификатор».
Если обмен с сайтом плодит дубли товаров, теряет связь заказов с номенклатурой или ломается после переноса базы, схему сопоставления по GUID лучше перестроить целиком — это типовая задача настройки обмена 1С с сайтом. Опишите, какие данные и в какую сторону нужно передавать, на странице размещения задания — исполнители оценят сроки и стоимость.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.