К статье
Практический материал

Разработка и Конфигурация · 10 мин

Когда у документа в 1С появляется ссылка

Разбираем, когда у документа 1С появляется ссылка, чем отличается ссылка от объекта, как получить ссылку до записи и почему возникают битые ссылки.

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

Ключевой факт: ссылка у документа существует не всегда. Новый, ещё не записанный документ ссылки не имеет — она появляется только после записи объекта в базу данных либо при явном назначении ссылки программным способом. Понимание этого момента критично при разработке обменов, обработок заполнения и механизмов, где один документ должен ссылаться на другой.

Что такое ссылка документа и чем она отличается от объекта

В 1С у любого документа существуют два представления: ДокументСсылка и ДокументОбъект. Ссылка — это лёгкий идентификатор, который однозначно указывает на запись в базе данных. Объект — это полноценный набор данных документа в памяти: реквизиты, табличные части, движения.

Между ними есть принципиальная разница по «весу» и назначению. Ссылка содержит минимум информации: вид документа и уникальный идентификатор (GUID). Через ссылку нельзя прочитать табличную часть или изменить реквизит — для этого нужно получить объект методом ПолучитьОбъект(). Зато ссылку можно хранить в реквизитах других объектов, передавать в запросы, сравнивать и использовать как ключ.

Важно понимать: номер и дата документа не являются ссылкой. Два документа «Реализация товаров» с одинаковым номером в разных периодах — это разные ссылки. Система различает записи именно по GUID, а не по представлению, которое видит пользователь.

В какой момент ссылка появляется у нового документа

Когда пользователь нажимает «Создать» или код выполняет Документы.РеализацияТоваровУслуг.СоздатьДокумент(), в памяти появляется объект без ссылки. Проверка НовыйОбъект.Ссылка в этот момент вернёт пустую ссылку соответствующего вида документа. Объект ещё не существует для базы данных — он живёт только в оперативной памяти сеанса.

Ссылка формируется в момент первой записи. Как только выполняется Записать() (в любом режиме — запись, проведение или отмена проведения), платформа сохраняет данные в таблицу базы и присваивает записи уникальный идентификатор. После этого свойство Ссылка объекта становится заполненным, и с этим идентификатором можно работать.

Практический признак: в обработчике ПередЗаписью у нового документа ссылка ещё пустая (или ровно та, что назначена вручную), а в обработчике ПриЗаписи и после завершения записи — уже заполненная. Это важно учитывать, если в логике записи нужно сохранить ссылку на текущий документ куда-либо ещё.

Порядок появления ссылки
  1. 1
    Вызов СоздатьДокумент() — объект в памяти, ссылка пустая
  2. 2
    Заполнение реквизитов и табличных частей — ссылки по-прежнему нет
  3. 3
    Вызов Записать() — платформа сохраняет запись в базу
  4. 4
    После успешной записи свойство Ссылка заполнено и доступно для использования

Как получить ссылку до записи: УстановитьСсылкуНового

Есть сценарии, где ссылка нужна до того, как документ записан. Классический пример — документ должен сослаться сам на себя в одном из реквизитов, или два документа создаются одновременно и должны ссылаться друг на друга. Если записывать их последовательно, при записи первого второго ещё не существует, и возникает проблема круговой зависимости.

Для таких случаев платформа предоставляет метод УстановитьСсылкуНового(). Он принимает заранее созданную ссылку, полученную через Документы.ВидДокумента.ПолучитьСсылку() — при вызове без параметров генерируется новый GUID. После назначения объект «знает» свою будущую ссылку ещё до записи, и её можно сохранить в реквизиты других объектов.

bsl
НоваяСсылка = Документы.РеализацияТоваровУслуг.ПолучитьСсылку();
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.УстановитьСсылкуНового(НоваяСсылка);
// Теперь НоваяСсылка можно передать в другой объект
НовыйДокумент.Записать(); // запишется именно с этой ссылкой

При таком подходе есть важное ограничение: если объект с установленной ссылкой так и не будет записан, в базе останется «висячая» ссылка — другие объекты ссылаются на несуществующий документ. Это одна из причин появления битых ссылок, о которых речь ниже.

Ссылка при копировании, обмене и загрузке данных

При копировании документа через интерфейс или метод Скопировать() создаётся новый объект без ссылки — GUID копии будет новым после записи. Это логично: две записи с одинаковым идентификатором в одной базе существовать не могут.

Иная ситуация при обмене данными между базами. В планах обмена и типовых механизмах синхронизации ссылка (GUID) передаётся вместе с данными, чтобы один и тот же документ в разных базах имел одинаковый идентификатор. При загрузке платформа сначала ищет объект по ссылке, и только потом — по ключевым полям. Именно поэтому удаление документа в одной базе и его повторное создание вручную ломает синхронизацию: у нового документа другой GUID, и система воспринимает его как другой объект.

Битые ссылки: откуда берутся и как проверить

Битая ссылка — это ссылка, указывающая на запись, которой уже нет в базе. В запросах и коде она выглядит как «Объект не найден» с отображением GUID. Типичные причины: документ был удалён непосредственным удалением без контроля ссылочной целостности; объект с установленной ссылкой нового не был записан; данные загружались обменом, а сам объект-владелец ссылки не пришёл.

Найти битые ссылки можно штатными средствами. В режиме «Все функции» доступна обработка «Поиск и удаление дублей» и групповое удаление помеченных объектов с контролем ссылок, а в типовых конфигурациях на БСП есть раздел администрирования с инструментами поиска и удаления битых ссылок. Программно проверка выполняется просто: если Ссылка.ПолучитьОбъект() возвращает Неопределено, запись отсутствует.

Практические проверки в коде: как не ошибиться с пустой ссылкой

Частая ошибка разработчика — сравнивать ссылку с Неопределено. Ссылка никогда не бывает Неопределено: у незаписанного документа она просто пустая. Корректная проверка — НовыйДокумент.Ссылка.Пустая() или сравнение с Документы.ВидДокумента.ПустаяСсылка().

Вторая типичная ситуация — передача ссылки в запрос. Запросы работают только со ссылками, а не с объектами: передать ДокументОбъект в параметр запроса нельзя, нужно передавать Объект.Ссылка. Если объект ещё не записан, запрос по такой ссылке ничего не найдёт, потому что записи в базе нет.

Типичные ошибки
01
Сохранение ссылки на незаписанный документ в другой объект — после записи первого ссылка валидна, но до записи это создаёт битую ссылку
02
Сравнение ссылки с Неопределено вместо проверки Пустая() — условие никогда не сработает
03
Использование ПолучитьОбъект() там, где достаточно ссылки — лишнее чтение всей записи из базы и падение производительности в циклах
04
Передача объекта вместо ссылки в параметр запроса — ошибка исполнения или пустой результат

Как проверить результат и выбрать правильный подход

После записи документа убедитесь, что ссылка появилась: свойство Ссылка заполнено, Пустая() возвращает Ложь, а ПолучитьОбъект() по этой ссылке возвращает объект, а не Неопределено. Если ссылка назначалась через УстановитьСсылкуНового(), сверьте, что записанный документ имеет именно тот GUID, который был сгенерирован заранее.

Контрольные точки

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

Свойство Ссылка после Записать()
Норма

Ссылка заполнена, Пустая() = Ложь

Тревожный признак

Ссылка пустая — запись не выполнилась, проверяйте исключения

ПолучитьОбъект() по сохранённой ссылке
Норма

Возвращается объект документа

Тревожный признак

Возвращается Неопределено — записи нет, ссылка битая

Представление в списке документов
Норма

Документ виден с номером и датой

Тревожный признак

Отображается «Объект не найден» — запись удалена

Маршрут решения

Как выбрать действие

Нужно просто создать и сохранить документСоздайте объект, заполните, вызовите Записать() — ссылка появится автоматически
Ссылка нужна до записи для связи объектовИспользуйте ПолучитьСсылку() + УстановитьСсылкуНового() и обязательно запишите объект в той же транзакции
Нужно только прочитать пару реквизитов по ссылкеОбращайтесь через точку к ссылке или запросом — не вызывайте ПолучитьОбъект()
Нужно изменить документ по ссылкеВызовите ПолучитьОбъект(), измените и запишите, проверив блокировки

Общее правило выбора простое: если задача решается ссылкой — используйте ссылку, это дешевле по ресурсам. Объект получайте только тогда, когда нужно читать табличные части, менять данные или вызывать методы объекта. А ссылку до записи назначайте только при реальной необходимости и всегда обеспечивайте последующую запись, иначе база наполнится битыми ссылками.

Итог

Что важно запомнить

Ссылка появляется при первой записи документа в базу. До записи её можно назначить вручную через УстановитьСсылкуНового(). Ссылка неизменна всю жизнь записи и исчезает только при удалении. Проверяйте ссылку через Пустая(), а не через сравнение с Неопределено.

Частые вопросы

Есть ли ссылка у документа, созданного, но не записанного?

Нет. Объект существует только в памяти, его свойство Ссылка содержит пустую ссылку данного вида документа. Ссылка появится после вызова Записать() либо после явного назначения через УстановитьСсылкуНового().

Меняется ли ссылка при перепроведении или изменении документа?

Нет. GUID документа присваивается один раз при записи и остаётся неизменным при любых изменениях реквизитов, дат, номеров и перепроведениях. Ссылка перестаёт существовать только при физическом удалении записи.

Чем пустая ссылка отличается от Неопределено?

Пустая ссылка — это вполне определённое значение конкретного типа документа с нулевым идентификатором. Неопределено — отсутствие значения как такового. Сравнение ссылки с Неопределено всегда даёт Ложь, поэтому проверять нужно методом Пустая().

Почему в реквизите отображается «Объект не найден»?

Это битая ссылка: идентификатор в реквизите указывает на запись, которой нет в базе. Обычно причина — непосредственное удаление объекта без контроля ссылок или обмен, при котором пришла ссылка, но не пришёл сам объект.

Можно ли узнать GUID документа и найти по нему запись?

Да. Получить строку GUID можно через Ссылка.УникальныйИдентификатор(), а обратно ссылку из GUID — через Документы.ВидДокумента.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаGUID)). Это стандартный приём при разборе обменов и поиске битых ссылок.

Что быстрее: работа со ссылкой или с объектом?

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