Разработка и Конфигурация · 12 мин
Как получить ссылку ещё не записанного документа в 1С
Как получить ссылку ещё не записанного документа в 1С: ПолучитьСсылку, УстановитьСсылкуНового, УникальныйИдентификатор. Примеры кода, ошибки и FAQ.
В типовой логике 1С ссылка на документ появляется только после записи объекта в базу данных. Однако на практике часто требуется знать ссылку заранее: чтобы заполнить реквизит «ДокументОснование» у подчинённого документа, связать несколько объектов до их записи или передать идентификатор во внешнюю систему. Платформа 1С:Предприятие даёт для этого штатные механизмы — метод ПолучитьСсылку() с уникальным идентификатором и метод УстановитьСсылкуНового().
Ключевая идея проста: ссылка документа — это по сути уникальный идентификатор (GUID), и его можно сгенерировать до записи объекта. Сначала создаётся новый УникальныйИдентификатор, из него формируется ссылка через Документы.ИмяДокумента.ПолучитьСсылку(Ид), а затем эта ссылка назначается объекту через УстановитьСсылкуНового(). После записи объект сохранится в базе именно с этой ссылкой.
Важно понимать ограничение: пока объект не записан, ссылка существует только в памяти и не указывает на реальные данные. Обращение к реквизитам через такую ссылку до записи даст пустые значения, а попытка получить объект через ПолучитьОбъект() вернёт Неопределено. Ниже разобраны рабочие сценарии, полный код, типовые ошибки и способы проверки результата.
Как устроена ссылка документа в 1С
Ссылка любого объекта в 1С — это структура, содержащая тип объекта и уникальный идентификатор (GUID) из 32 шестнадцатеричных символов. Идентификатор генерируется платформой в момент записи нового объекта, но ничто не мешает сгенерировать его заранее в коде: класс УникальныйИдентификатор доступен и на сервере, и на клиенте.
Менеджер документа (Документы.РеализацияТоваровУслуг и т.п.) имеет перегруженный метод ПолучитьСсылку(). Вызванный без параметров, он возвращает новую ссылку со сгенерированным платформой идентификатором. Вызванный с параметром типа УникальныйИдентификатор, он возвращает ссылку именно с этим идентификатором — независимо от того, есть ли такой документ в базе.
Сам по себе ПолучитьСсылку() не создаёт документ и ничего не пишет в базу. Это лишь «заготовка» ссылки. Чтобы объект при записи получил эту ссылку, а не новую, нужен второй шаг — УстановитьСсылкуНового(). Если этот шаг пропустить, ссылка останется «битой» — указывающей на несуществующий объект.
Базовый сценарий: получить ссылку до записи
Стандартная последовательность состоит из четырёх шагов: создать идентификатор, получить ссылку, создать объект и назначить ему эту ссылку, затем записать. Порядок важен: УстановитьСсылкуНового() вызывается до Записать(), иначе объект уйдёт в базу с другой ссылкой.
// 1. Генерируем идентификатор
НовыйИд = Новый УникальныйИдентификатор;
// 2. Получаем ссылку ещё не существующего документа
НоваяСсылка = Документы.РеализацияТоваровУслуг.ПолучитьСсылку(НовыйИд);
// 3. Создаём объект и назначаем ему ссылку
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.УстановитьСсылкуНового(НоваяСсылка);
// 4. Заполняем и записываем
НовыйДокумент.Дата = ТекущаяДатаСеанса();
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
// Теперь НоваяСсылка указывает на реальный документ
- 1Создайте Новый УникальныйИдентификатор
- 2Получите ссылку: Документы.ВидДокумента.ПолучитьСсылку(НовыйИд)
- 3Создайте объект методом СоздатьДокумент()
- 4Вызовите УстановитьСсылкуНового(НоваяСсылка) до записи
- 5Заполните реквизиты и выполните Записать()
- 6Проверьте, что ссылка теперь указывает на существующий документ
После записи переменная НоваяСсылка и значение НовыйДокумент.Ссылка равны — это один и тот же идентификатор. Проверить равенство можно обычным сравнением: НоваяСсылка = НовыйДокумент.Ссылка вернёт Истина.
Упрощённый вариант — вызвать ПолучитьСсылку() без параметра. Платформа сама сгенерирует идентификатор, и отдельная переменная для УникальныйИдентификатор не нужна. Результат идентичен: вы получаете ссылку, которую можно передавать в другие объекты до записи самого документа.
Сценарий: связать два документа до записи обоих
Наиболее частая практическая задача — создать документ-основание и подчинённый документ в одной транзакции, при этом в подчинённом нужно сразу проставить ссылку на основание. Если записывать основание первым, возникает промежуточное состояние, при ошибке в котором в базе останется «висячий» документ. Предварительное получение ссылки решает проблему.
СсылкаОснования = Документы.ЗаказКлиента.ПолучитьСсылку();
Заказ = Документы.ЗаказКлиента.СоздатьДокумент();
Заказ.УстановитьСсылкуНового(СсылкаОснования);
Заказ.Дата = ТекущаяДатаСеанса();
Реализация = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
Реализация.Дата = ТекущаяДатаСеанса();
Реализация.ДокументОснование = СсылкаОснования; // ссылка уже известна
НачатьТранзакцию();
Заказ.Записать();
Реализация.Записать();
ЗафиксироватьТранзакцию();
Оба документа записываются в одной транзакции: если запись реализации падает, откатывается и заказ. При этом реквизит ДокументОснование заполнен корректной ссылкой ещё до того, как заказ физически появился в базе. Это же работает для справочников, задач и любых ссылочных типов.
При обмене данными между базами удобно генерировать GUID на стороне источника и передавать его вместе с данными документа. Приёмник создаёт документ через ПолучитьСсылку(Ид) + УстановитьСсылкуНового — и ссылки в обеих базах совпадают, что упрощает сопоставление объектов без регистра соответствия.
Как проверить, что ссылка не «битая»
Ссылка, полученная через ПолучитьСсылку(), но не привязанная к записанному объекту, — классическая «битая ссылка». В запросах она даст NULL при соединении, а в пользовательском интерфейсе отобразится как «Объект не найден». Поэтому перед использованием заранее полученной ссылки стоит убедиться, что документ действительно записан.
Самый надёжный способ проверки — запрос к базе:
Функция ДокументСуществует(Ссылка)
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1 ИСТИНА
|ИЗ Документ.РеализацияТоваровУслуг
|ГДЕ Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Возврат Не Запрос.Выполнить().Пустой();
КонецФункции
Альтернатива без запроса — попытка получить объект: Ссылка.ПолучитьОбъект() вернёт Неопределено, если документа нет в базе. Этот способ проще в коде, но медленнее при массовых проверках, так как вычитывает объект целиком.
Как проверить результат
НоваяСсылка = Документ.Ссылка после записи
Ссылки различаются — УстановитьСсылкуНового не вызван или вызван после Записать()
Запрос возвращает строку документа
Пустой результат — документ не записан, ссылка битая
Возвращается объект документа
Возвращается Неопределено
Ссылка.Номер возвращает номер
Ошибка или пустое значение при обращении к полям
Типичные ошибки и ограничения
Первая и самая частая ошибка — вызов УстановитьСсылкуНового() после Записать() или вообще без последующей записи. В первом случае метод бесполезен: документ уже сохранён с другой ссылкой. Во втором — в базе остаются ссылки на несуществующий объект, которые потом приходится вычищать обработками поиска битых ссылок.
Вторая ошибка — ожидание, что по ссылке до записи доступны данные. Выражение НоваяСсылка.Номер до записи вернёт пустое значение, а попытка обратиться к табличной части вызовет ошибку. Ссылка до записи — это только идентификатор, а не объект.
Третья группа проблем связана с нумерацией и правами. Номер документу присваивается при записи, а не при получении ссылки, поэтому предсказать номер заранее нельзя. Кроме того, ПолучитьСсылку() и УстановитьСсылкуНового() недоступны в безопасном режиме внешних обработок без соответствующих разрешений, а в разделённых данных (SaaS) требуют аккуратности с областью данных.
Альтернативные подходы и когда они лучше
Не всегда нужна именно предварительная ссылка. Если задача — просто создать пару документов, проще записать основание первым и взять его готовую ссылку. Предварительное получение оправдано, когда требуется атомарность, кольцевая связь объектов или синхронизация идентификаторов между системами.
Для обмена данными вместо ручной генерации GUID часто используют планы обмена и механизмы конвертации, которые сами сопоставляют ссылки. Ручное управление ссылками там оправдано только при нестандартной интеграции, когда типовые механизмы недоступны.
Сравнение вариантов
Простой способ получить ссылку заранее; идентификатор генерирует платформа. Подходит для связки документов в одной базе
Полный контроль над GUID; нужен для интеграций и обменов, где идентификатор приходит извне
Проще и безопаснее, но не даёт атомарности и не подходит для кольцевых связей
Штатное сопоставление ссылок между базами; избыточно для разовой задачи внутри одной базы
Ещё одна альтернатива — хранить связь не ссылкой, а служебным реквизитом (например, строковым ключом операции) и проставлять ссылки пост-обработкой после записи всех объектов. Это удобно при пакетной загрузке, когда порядок создания документов заранее неизвестен.
Что важно запомнить
Ссылку незаписанного документа получают через Документы.Вид.ПолучитьСсылку(Новый УникальныйИдентификатор), затем назначают объекту методом УстановитьСсылкуНового() до вызова Записать(). До записи ссылка — только идентификатор без данных; после записи проверяйте, что объект реально существует, чтобы не оставить в базе битые ссылки.
Частые вопросы
Можно ли получить номер документа до его записи?
Нет. Номер присваивается платформой в момент записи с учётом нумератора и периодичности. Если нужен предсказуемый идентификатор до записи, используйте GUID ссылки или собственный служебный реквизит, а не номер.
Что произойдёт, если вызвать УстановитьСсылкуНового для уже записанного документа?
Метод предназначен только для новых объектов. Для уже существующего документа изменить ссылку штатными средствами нельзя — ссылка является неизменным ключом объекта в базе. Решение — создать новый документ с нужной ссылкой и перенести данные.
Работает ли ПолучитьСсылку на клиенте (в тонком или веб-клиенте)?
Конструктор Новый УникальныйИдентификатор доступен на клиенте, но ПолучитьСсылку менеджера документа и УстановитьСсылкуНового — серверные методы. Обычно вся логика выполняется в серверной процедуре, а на клиент возвращается готовая ссылка.
Чем опасны битые ссылки, оставшиеся после незавершённой записи?
Они дают NULL при соединениях в запросах, отображаются как «Объект не найден», ломают отчёты и могут блокировать обмены данными. Удаляются они штатной обработкой поиска и удаления битых ссылок, но лучше не допускать их появления — оборачивая запись связанных объектов в транзакцию.
Можно ли получить ссылку с конкретным GUID, который прислала внешняя система?
Да. Создайте идентификатор из строки: Новый УникальныйИдентификатор("a1b2c3d4-..."), затем ПолучитьСсылку(Ид). Перед записью проверьте, что документа с таким GUID ещё нет в базе, иначе запись нового объекта с той же ссылкой завершится ошибкой или перезапишет существующий.
Работает ли этот приём для справочников, задач и планов счетов?
Да, механизм универсален для всех ссылочных типов: Справочники.Номенклатура.ПолучитьСсылку(), Задачи.ЗадачаИсполнителя.ПолучитьСсылку() и так далее. У каждого объектного менеджера есть и ПолучитьСсылку, и соответствующий УстановитьСсылкуНового у объекта.