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

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

Как получить ссылку на документ в 1С 8.3 программно

Способы получить ссылку на документ в 1С 8.3 программно: по номеру, через запрос, СКД и уникальный идентификатор. Примеры кода, проверка результата, типичные ошибки.

Ссылка на документ — основной способ обратиться к конкретному объекту базы данных во встроенном языке 1С:Предприятие 8.3. Без ссылки невозможно прочитать реквизиты, изменить проведение, открыть форму или передать объект в другой алгоритм. При этом у разработчика есть несколько способов получить ссылку: через запрос, по номеру и дате, через уникальный идентификатор или через операцию «НайтиПоНомеру».

Выбор способа зависит от исходных данных. Если известен номер документа и период — подойдёт метод НайтиПоНомеру. Если нужна выборка по условиям — оптимален запрос. Если ссылка передаётся между системами или хранится в виде строки — используется уникальный идентификатор. Каждый вариант имеет особенности по производительности и поведению при отсутствии документа.

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

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

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

Через ссылку можно обращаться к реквизитам «напрямую» (платформа неявно выполняет запрос к базе), но изменить документ через ссылку нельзя — для записи нужно вызвать ПолучитьОбъект(). Работа через ссылку быстрее и экономнее по памяти, поэтому в обходах больших выборок всегда используют именно ссылки.

Получение ссылки запросом — универсальный способ

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1

| РеализацияТоваровУслуг.Ссылка КАК Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Номер = &Номер

| И РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("Номер", "0000-000123");

Запрос.УстановитьПараметр("НачалоПериода", НачалоГода(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецДня(ТекущаяДатаСеанса()));

Результат = Запрос.Выполнить();

Если Не Результат.Пустой() Тогда

Выборка = Результат.Выбрать();

Выборка.Следующий();

СсылкаНаДокумент = Выборка.Ссылка;

КонецЕсли;

Обязательно проверяйте Результат.Пустой() перед обращением к выборке: если документ не найден, попытка прочитать поле Ссылка приведёт к ошибке. Для массовой обработки убирайте «ПЕРВЫЕ 1» и обходите выборку в цикле, работая именно со ссылками, а не с объектами.

Получение ссылки по номеру через НайтиПоНомеру

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

НайденнаяСсылка = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("0000-000123", НачалоГода(ТекущаяДатаСеанса()));

Если НайденнаяСсылка.Пустая() Тогда

Сообщить("Документ с таким номером не найден");

Иначе

Сообщить("Найден: " + НайденнаяСсылка);

КонецЕсли;

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

Ссылка через уникальный идентификатор

Уникальный идентификатор (GUID) применяется при обмене между базами, при хранении ссылок во внешних системах и при интеграции через веб-сервисы. Строковое представление идентификатора преобразуется в ссылку методом ПолучитьСсылку:

СтрокаИд = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";

СсылкаНаДокумент = Документы.РеализацияТоваровУслуг.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаИд));

Обратное преобразование выполняется так: СтрокаИд = XMLСтрока(СсылкаНаДокумент) или СокрЛП(СсылкаНаДокумент.УникальныйИдентификатор()). Учтите, что ПолучитьСсылку всегда возвращает непустую ссылку — даже если документа с таким идентификатором в базе нет. Проверка существования обязательна.

Как проверить, что ссылка указывает на существующий документ

Самый надёжный способ проверки — запрос по ссылке или попытка получить объект. Прямое обращение к реквизитам «битой» ссылки вызывает ошибку «Объект не найден», поэтому проверку делают заранее.

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Д.Ссылка ИЗ Документ.РеализацияТоваровУслуг КАК Д ГДЕ Д.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);

ДокументСуществует = Не Запрос.Выполнить().Пустой();

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

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

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

Ссылка не пустая
Норма

Ссылка.Пустая() возвращает Ложь

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

Возвращает Истина — документ не найден методом поиска

Документ существует в базе
Норма

Запрос по ссылке возвращает строку

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

Ошибка «Объект не найден» при обращении к реквизитам

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

ТипЗнч(Ссылка) даёт ожидаемый тип

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

Ссылка относится к другому виду документов

Ссылка на текущий документ внутри модуля объекта и формы

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

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

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

Частые ошибки и ограничения способов

Каждый метод имеет границы применимости. НайтиПоНомеру не работает, если номер неизвестен полностью или документ находится вне указанного периода нумерации. Запрос требует прав на чтение документа — при RLS-ограничениях выборка может вернуть меньше строк, чем ожидает разработчик.

ПолучитьСсылку по идентификатору не проверяет существование и в обменах может вернуть ссылку на ещё не загруженный объект — это нормально для механизмов обмена, но опасно в прикладном коде. Также помните, что помеченный на удаление документ по-прежнему находится всеми способами; проверяйте реквизит ПометкаУдаления, если это важно для логики.

Итог

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

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

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

Как получить ссылку на документ, если известна только дата?

Дата без других условий неоднозначна — документов за дату может быть много. Используйте запрос с отбором по диапазону дат и дополнительными условиями (организация, контрагент, вид операции), а результат обходите выборкой. Если документ гарантированно один, добавьте «ПЕРВЫЕ 1» и проверку на пустой результат.

Чем отличается НайтиПоНомеру от запроса по номеру?

НайтиПоНомеру — специализированный метод, который использует индекс по номеру и работает быстрее, но требует точного номера с префиксом и правильной даты периода нумерации. Запрос гибче: позволяет искать по части номера, комбинировать условия и сразу получать дополнительные поля. Для точного совпадения номера предпочтителен НайтиПоНомеру.

Почему ПолучитьСсылку вернула ссылку, а документа нет?

Метод ПолучитьСсылку конструирует ссылку из идентификатора без обращения к данным — он не знает, существует ли объект. Такая ссылка становится «битой». Перед использованием проверьте существование запросом по ссылке или через функцию СсылкаСуществует из библиотеки стандартных подсистем.

Как преобразовать ссылку в строку для передачи во внешнюю систему?

Используйте XMLСтрока(Ссылка) — получите строковое представление уникального идентификатора. Обратно во внешней базе ссылка восстанавливается через ПолучитьСсылку(Новый УникальныйИдентификатор(Строка)). Обычное строковое представление вида «Реализация товаров и услуг 0000-000123 от…» для идентификации не подходит.

Можно ли получить ссылку на ещё не записанный документ?

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

Как получить ссылку на документ в запросе динамического списка?

В динамическом списке документов ссылка доступна в текущей строке: Элементы.Список.ТекущиеДанные.Ссылка. Для программной обработки выделенных строк обходите Элементы.Список.ВыделенныеСтроки — каждый элемент уже является ссылкой на документ.