Реквизит с GUID в справочнике и документе 1С: от Конфигуратора до обмена
Содержание
Чтобы добавить идентификатор в 1С, откройте объект в Конфигураторе, на вкладке «Данные» создайте реквизит с типом УникальныйИдентификатор, включите индексирование и заполняйте его в модуле объекта через Новый УникальныйИдентификатор. Затем обновите конфигурацию базы данных и одной обработкой заполните уже существующие элементы.
Такой реквизит нужен, когда у справочника или документа должен быть свой стабильный ключ для обмена с сайтом, CRM, складской системой или другой базой 1С. Ниже — порядок работ для платформы 8.3: от структуры метаданных до поиска объекта по GUID, который пришёл извне.
Сначала решите: нужен ли отдельный реквизит
У каждого ссылочного объекта 1С (справочник, документ, план видов характеристик) уже есть GUID — это внутренний идентификатор ссылки. Его получают методом Ссылка.УникальныйИдентификатор(). Многим задачам этого хватает, и новый реквизит не нужен.
| Ситуация | Что использовать | Почему |
|---|---|---|
| Внешняя система принимает ключи от 1С | GUID ссылки | Он уже есть у каждого объекта, ничего добавлять не надо |
| Объекты создаются в 1С из внешней системы, и её ключ надо сохранить | УстановитьСсылкуНового() или отдельный реквизит | Ссылка 1С совпадёт с внешним ключом либо ключ хранится рядом |
| У одного объекта несколько внешних систем со своими ключами | Отдельный реквизит на каждую систему или регистр сведений | Одна ссылка не может хранить два разных GUID |
| Внешний ключ не в формате GUID (число, артикул, строка) | Реквизит типа Строка или Число | Тип УникальныйИдентификатор примет только строку формата GUID |
💡 Приём, о котором часто забывают: при создании объекта по данным извне ему можно сразу задать ссылку с нужным GUID.
УИД = Новый УникальныйИдентификатор(ВходящийGUIDСтрокой);
НовыйЭлемент = Справочники.Контрагенты.СоздатьЭлемент();
НовыйЭлемент.УстановитьСсылкуНового(Справочники.Контрагенты.ПолучитьСсылку(УИД));
НовыйЭлемент.Наименование = ВходящееНаименование;
НовыйЭлемент.Записать();
После этого внешний ключ и ссылка 1С — одно и то же значение. Ищут такой объект через ПолучитьСсылку(), без отдельного реквизита и без запроса по полю.
Отдельный реквизит оправдан, когда ключ должен жить независимо от ссылки: его можно переназначить, очистить, перенести на другой элемент при слиянии дублей. Дальше — про этот вариант.
1. Добавляем реквизит-идентификатор в структуру метаданных
Если конфигурация на поддержке (типовая БП, ЗУП, УТ), не снимайте её с поддержки ради одного реквизита. Добавьте его через расширение: заимствуйте нужный справочник или документ и создайте реквизит уже в расширении. Тогда обновления типовой не потребуют ручного сравнения и объединения.
Порядок для своей или снятой с поддержки конфигурации:
- Сделайте резервную копию базы
:
Администрирование → Выгрузить информационную базув Конфигураторе. - Откройте конфигурацию:
Конфигурация → Открыть конфигурацию. - В дереве метаданных найдите объект, например
Справочники → Контрагенты, и откройте его двойным щелчком. - Перейдите на вкладку «Данные» и в разделе реквизитов нажмите «Добавить».
- Задайте имя без пробелов, например
ВнешнийИДилиИдентификаторCRM. Синоним — понятный пользователю: «Идентификатор в CRM». - В поле «Тип» выберите
УникальныйИдентификатор. Длину и точность задавать не нужно.
Для расширения шаги те же, только объект сначала заимствуют: правой кнопкой по справочнику в основной конфигурации и команда «Добавить в расширение». Новый реквизит создаётся в заимствованном объекте внутри дерева расширения.
У расширения есть свойство «Префикс имён», например Расш1_. Имена новых реквизитов начинайте с него: Расш1_ВнешнийИД. Так поле не столкнётся с одноимённым реквизитом, если фирма-разработчик добавит его в типовую в следующем релизе.
Имя реквизита потом используется в коде, запросах и обменах. Переименовать его позже можно, но придётся править все места, где оно встречается, включая внешние системы, которые читают это поле через OData или HTTP-сервис.
2. Свойства и индексирование поля идентификатора
Реквизит без индекса работает, но поиск по нему в большой таблице будет медленным. Каждая загрузка из внешней системы начинается с вопроса «есть ли уже объект с таким GUID», поэтому индекс нужен почти всегда.
Откройте палитру свойств реквизита (Alt+Enter) и проверьте:
- 🔎 Индексировать — значение «Индексировать». Вариант «Индексировать с доп. упорядочиванием» нужен, только если по полю строят списки с сортировкой. Для поиска хватает обычного индекса.
- ✏️ Проверка заполнения — «Не проверять». Поле заполняется кодом, пользователю его вводить не надо.
- 👁 На форме — выведите поле только для просмотра. Ручная правка GUID почти всегда приводит к рассинхрону с внешней системой.
- 🔐 Права — если ключ служебный, его можно не показывать на форме вовсе, а смотреть в отладке или отчёте.
Индекс не гарантирует уникальности. Платформа не запретит записать два элемента с одинаковым GUID в реквизите. Проверку дубля нужно писать самому — пример в следующем разделе.
После настройки сохраните конфигурацию и выполните Конфигурация → Обновить конфигурацию базы данных (F7). Для изменения структуры таблиц нужен монопольный доступ к базе: предупредите пользователей и запускайте обновление, когда в базе никто не работает
.
3. Автоматическое заполнение идентификатора при записи
Заполнять GUID надёжнее всего в модуле объекта, а не в форме. Модуль объекта срабатывает при любой записи: из формы, из обработки, из обмена. Код формы — только при интерактивной работе.
Откройте модуль объекта (правой кнопкой по справочнику → «Открыть модуль объекта») и добавьте два обработчика:
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если ВнешнийИД = ПустойУИД() Тогда
ВнешнийИД = Новый УникальныйИдентификатор;
КонецЕсли;
Если ЕстьДубльИдентификатора() Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Идентификатор " + Строка(ВнешнийИД) + " уже занят другим элементом.";
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Процедура ПриКопировании(ОбъектКопирования)
ВнешнийИД = ПустойУИД();
КонецПроцедуры
Функция ПустойУИД()
Возврат Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000");
КонецФункции
Функция ЕстьДубльИдентификатора()
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
| Т.Ссылка
|ИЗ
| Справочник.Контрагенты КАК Т
|ГДЕ
| Т.ВнешнийИД = &ИД
| И Т.Ссылка <> &Ссылка");
Запрос.УстановитьПараметр("ИД", ВнешнийИД);
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Возврат НЕ Запрос.Выполнить().Пустой();
КонецФункции
Что здесь важно:
- Новый реквизит типа
УникальныйИдентификаторпо умолчанию содержит нулевой GUID00000000-0000-0000-0000-000000000000. Поэтому пустоту проверяем сравнением с ним. ПриКопированиисбрасывает ключ у копии. Без этого пользователь копирует контрагента — и у двух элементов оказывается один GUID.- При
ОбменДанными.Загрузка = Истинаобработчик ничего не делает: обмен сам передаёт готовый ключ, его нельзя перезаписывать. - У документа сигнатура другая:
ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения). Тело то же, в запросе —Документ.<Имя>.
💡 Если ключ должен совпадать с GUID ссылки, в ПередЗаписью нового объекта ссылки ещё нет. Получите её заранее: Ссылка = ПолучитьСсылкуНового(); если пусто — вызовите УстановитьСсылкуНового(Справочники.Контрагенты.ПолучитьСсылку()) и возьмите УникальныйИдентификатор() у этой ссылки.
4. Как заполнить идентификатор у уже существующих данных
После обновления структуры у всех старых элементов в новом поле нулевой GUID. Их нужно заполнить один раз — внешней обработкой или обработчиком обновления.
Решите заранее, что писать в поле:
- 🔁 GUID ссылки —
Выборка.Ссылка.УникальныйИдентификатор(). Удобно, если внешняя система уже знает объекты по ссылкам 1С. - 🆕 Новый случайный GUID —
Новый УникальныйИдентификатор. Когда ключи ещё никуда не передавались. - 📥 Ключи из внешней системы — загрузка таблицы соответствий «код/ИНН → GUID» из файла.
Пример серверной процедуры внешней обработки:
&НаСервере
Процедура ЗаполнитьИдентификаторыНаСервере()
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Т.Ссылка
|ИЗ
| Справочник.Контрагенты КАК Т
|ГДЕ
| Т.ВнешнийИД = &Пустой");
Запрос.УстановитьПараметр("Пустой",
Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000"));
Выборка = Запрос.Выполнить().Выбрать();
Счетчик = 0;
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.ВнешнийИД = Выборка.Ссылка.УникальныйИдентификатор();
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
Счетчик = Счетчик + 1;
КонецЦикла;
Сообщить("Заполнено элементов: " + Формат(Счетчик, "ЧН=0; ЧГ=0"));
КонецПроцедуры
ОбменДанными.Загрузка = Истина отключает проверки и обработчики модуля объекта. Запись идёт быстрее, а дата изменения и другие поля, которые заполняют обработчики, не трогаются.
Обработка меняет каждый элемент справочника. Запускайте её на копии базы, затем в рабочей — вне рабочего времени. Если в базе настроен обмен, все изменённые элементы попадут в следующий пакет выгрузки: при 50 000 элементах это заметный объём.
Для документов подход тот же, но сначала проверьте на копии, как ведёт себя запись проведённого документа в вашей конфигурации. Движения при Загрузка = Истина не перезаписываются, однако подписки на события и регистрация изменений для обмена всё равно работают.
5. Использование идентификатора во внешних системах и при обмене
Наружу GUID передают строкой: Строка(ВнешнийИД) даёт вид 5f0c2a8e-1b3d-4e7a-9c11-2d6f8a4b0e93. Обратно строку превращают в значение конструктором Новый УникальныйИдентификатор(Строка).
Входящую строку обязательно оборачивайте в Попытка: при неверном формате конструктор вызывает исключение, и без перехвата упадёт весь пакет загрузки.
Функция НайтиПоВнешнемуИД(ИДСтрокой)
Попытка
УИД = Новый УникальныйИдентификатор(ИДСтрокой);
Исключение
Возврат Справочники.Контрагенты.ПустаяСсылка();
КонецПопытки;
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
| Т.Ссылка
|ИЗ
| Справочник.Контрагенты КАК Т
|ГДЕ
| Т.ВнешнийИД = &УИД");
Запрос.УстановитьПараметр("УИД", УИД);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Справочники.Контрагенты.ПустаяСсылка();
КонецФункции
Где идентификатор пригодится:
- 🌐 HTTP-сервис — отдаёте JSON с полем
id, внешний сайт по нему же присылает изменения. - 📊 Стандартный интерфейс OData — реквизит виден как обычное поле объекта, рядом с
Ref_Key(GUID ссылки). Не забудьте добавить объект в состав OData. - 🔄 Обмен между базами 1С — в правилах обмена ключ подходит для сопоставления объектов, когда ссылки в базах разные.
- 📄 Загрузка из Excel и CSV — колонка с GUID позволяет обновлять элементы, а не создавать дубли.
Если внешний ключ совпадает со ссылкой 1С, вместо запроса используйте Справочники.Контрагенты.ПолучитьСсылку(УИД). Учтите: метод вернёт ссылку даже на несуществующий объект. Проверить, есть ли он в базе, можно через Ссылка.ПолучитьОбъект() = Неопределено или запросом.
Ошибки при работе с идентификаторами и как их исправить
Отдельный случай — реквизит типа Строка(36) вместо УникальныйИдентификатор. Он работает, но занимает в базе в несколько раз больше места и принимает любой мусор: пробелы, заглавные и строчные буквы вперемешку, обрезанные значения. Если ключ точно в формате GUID, выбирайте специальный тип.
Проверить результат миграции удобно консолью запросов: посчитайте элементы с нулевым GUID и элементы, у которых ключ повторяется. Обе цифры после заполнения должны быть нулевыми. Если вторая не ноль, исправьте дубли до того, как включите выгрузку во внешнюю систему: иначе она получит два объекта с одним ключом и, скорее всего, склеит их.