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

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

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

Как в 1С получить объект документа по ссылке: методы ПолучитьОбъект, НайтиПоНомеру, проверка ссылки на пустоту и существование. Примеры кода на встроенном языке.

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

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

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

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

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

Объект (тип ДокументОбъект.ИмяДокумента) — это полная копия данных документа в памяти. Только через объект можно изменять реквизиты, заполнять табличные части и вызывать Записать(). Получение объекта — более тяжёлая операция: платформа читает данные из базы.

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

Основной способ: метод ПолучитьОбъект()

Метод ПолучитьОбъект() вызывается непосредственно у ссылки и возвращает объект документа. Это стандартный путь, когда документ нужно изменить и записать.

ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

ДокОбъект.Комментарий = "Обработан программно";

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

Если ссылка корректна и объект существует, метод вернёт заполненный объект. Если ссылка «битая» (объект удалён из базы, а ссылка осталась в реквизитах), метод вернёт Неопределено — это нужно учитывать в коде.

Обратите внимание: ПолучитьОбъект() нельзя вызывать на клиенте в тонком и веб-клиенте — метод доступен только на сервере. Поэтому в управляемых формах код получения объекта размещают в серверных процедурах с директивой &НаСервере.

Порядок получения документа по ссылке
  1. 1
    Убедитесь, что ссылка не пустая: ЗначениеЗаполнено(Ссылка)
  2. 2
    Проверьте существование объекта в базе (см. раздел о битых ссылках)
  3. 3
    Вызовите Ссылка.ПолучитьОбъект() в серверном контексте
  4. 4
    Проверьте результат на Неопределено
  5. 5
    Внесите изменения и вызовите Записать() с нужным режимом

Проверка ссылки перед получением объекта

Проверка на пустую ссылку

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

Если НЕ ЗначениеЗаполнено(СсылкаНаДокумент) Тогда

Возврат;

КонецЕсли;

// Альтернатива — сравнение с пустой ссылкой

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

Возврат;

КонецЕсли;

Проверка существования объекта в базе

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

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

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

|ГДЕ Ссылка = &Ссылка";

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

Если Запрос.Выполнить().Пустой() Тогда

// Объект не существует — битая ссылка

КонецЕсли;

Как получить документ без ссылки: поиск по номеру и запрос

Если ссылки нет, а есть только номер и дата документа (типично при обмене данными), используется метод менеджера документа НайтиПоНомеру():

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

"00000-000123", ТекущаяДатаСеанса());

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

ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

КонецЕсли;

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

Для чтения данных без изменения документа объект получать не обязательно — достаточно запроса. Запрос вернёт реквизиты по ссылке без загрузки всего объекта в память, что существенно быстрее при массовой обработке.

Способы доступа к данным документа

Ссылка.ПолучитьОбъект()

Нужен, когда документ изменяется и записывается. Медленный при массовом чтении.

Запрос по ссылке

Оптимален для чтения реквизитов и табличных частей без изменения данных.

Обращение через точку (Ссылка.Номер)

Допустимо для 1–2 реквизитов; в цикле вызывает обращение к базе на каждый реквизит.

НайтиПоНомеру()

Используется, когда ссылки нет — например, при загрузке данных из внешних систем.

Работа с битыми ссылками

Битая ссылка возникает, когда объект удалён из базы, а ссылка на него осталась в реквизитах других объектов или в регистрах. В интерфейсе такие ссылки отображаются как «<Объект не найден> (идентификатор)».

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

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

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

Получение документа по уникальному идентификатору

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

УИД = Новый УникальныйИдентификатор("a1b2c3d4-...");

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

// Проверка существования

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

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

Если Запрос.Выполнить().Пустой() Тогда

// Объекта с таким GUID нет в базе

КонецЕсли;

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

Производительность и безопасная запись

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

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

Также помните о правах: код, выполняемый в привилегированном модуле (УстановитьПривилегированныйРежим(Истина)), игнорирует ограничения RLS и прав доступа. Используйте привилегированный режим только там, где это действительно необходимо.

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

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

Объект получен
Норма

Переменная содержит ДокументОбъект, реквизиты доступны

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

Значение Неопределено — ссылка битая или объекта нет

Запись выполнена
Норма

Записать() отработал без исключения, изменения видны в форме

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

Ошибка блокировки или нарушение прав — документ не изменён

Производительность обработки
Норма

Чтение через запрос, объекты получаются только для изменяемых документов

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

ПолучитьОбъект() вызывается в цикле для всех ссылок подряд

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

Чем отличается Ссылка.ПолучитьОбъект() от обращения Ссылка.Номер?

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

Почему ПолучитьОбъект() возвращает Неопределено?

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

Можно ли вызвать ПолучитьОбъект() на клиенте?

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

Как получить ссылку из строки с GUID при обмене?

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

Что быстрее при обработке тысяч документов: ПолучитьОбъект() или запрос?

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

Как программно проверить, пустая ли ссылка?

Используйте функцию ЗначениеЗаполнено(Ссылка) — она вернёт Ложь для пустой ссылки. Альтернатива — сравнение с пустой ссылкой конкретного вида: Ссылка = Документы.ИмяДокумента.ПустаяСсылка(). Первый вариант универсальнее, второй точнее по типу.

Итог

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

Документ по ссылке получают методом ПолучитьОбъект() на сервере, предварительно проверив, что ссылка заполнена и объект существует. Для чтения данных без изменений используйте запрос — это быстрее. Битые ссылки возвращают Неопределено, поэтому проверка результата обязательна в любом сценарии.