Разработка и Конфигурация · 9 мин
1С: как получить ссылку на объект из формы
Как в 1С получить ссылку на объект из формы: методы для обычных и управляемых форм, примеры кода, отличия Объект.Ссылка и Элементы, типичные ошибки.
Получить ссылку на объект из формы — одна из базовых задач при доработке конфигураций 1С. Ссылка нужна, чтобы передать объект в другую процедуру, сохранить его в параметр, открыть связанные данные или выполнить запрос. Способ получения зависит от типа формы: в обычных и управляемых формах механика различается, и путаница между ними — самая частая причина ошибок у начинающих разработчиков.
В управляемой форме основной реквизит (например, «Объект») имеет тип «ДанныеФормыСтруктура», а не сам объект базы данных. Поэтому обратиться к ссылке напрямую через Объект.Ссылка можно только тогда, когда у объекта есть реквизит «Ссылка» — а он есть у всех ссылочных типов: справочников, документов, планов видов характеристик и других. В обычных формах ситуация проще: там доступен объект данных напрямую.
Ниже разобраны рабочие способы для обоих типов форм, получение ссылки из табличной части и списка, а также типичные ошибки и способы проверить, что ссылка получена корректно.
Как устроена ссылка и зачем она нужна
Ссылка — это уникальный идентификатор объекта в базе данных. Два разных объекта одного вида всегда имеют разные ссылки, даже если все их реквизиты совпадают. Именно по ссылке платформа находит объект при открытии формы, выполнении запроса или обращении через метод ПолучитьОбъект().
Важно понимать разницу между ссылкой и объектом. Ссылка — лёгкий указатель, её можно передавать между клиентом и сервером без ограничений. Объект — это полная программная копия данных, она занимает больше ресурсов и не сериализуется между контекстами в управляемом приложении. Поэтому в большинстве сценариев работают именно со ссылкой.
Получение ссылки в управляемой форме объекта
В управляемой форме документа или элемента справочника основной реквизит обычно называется «Объект». Ссылка доступна как его свойство:
&НаКлиенте
Процедура КомандаПолучитьСсылку(Команда)
ТекущаяСсылка = Объект.Ссылка;
Сообщить(ТекущаяСсылка);
КонецПроцедуры
Такой код работает и на клиенте, и на сервере, потому что реквизит «Ссылка» присутствует в данных формы. Это самый простой и правильный способ — не нужно ни преобразовывать данные формы в объект, ни обращаться к базе.
Если форма открыта для нового, ещё не записанного объекта, Объект.Ссылка вернёт пустую ссылку соответствующего типа. Проверить это можно функцией ЗначениеЗаполнено() или сравнением с пустой ссылкой:
Если НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
Сообщить("Объект ещё не записан, ссылка отсутствует");
КонецЕсли;
Получение ссылки в обычной форме
В обычных формах (толстый клиент, обычное приложение) доступен сам объект данных через свойство формы. Для формы документа это может выглядеть так:
Процедура КнопкаПолучитьСсылку(Элемент)
ТекущаяСсылка = ЭтотОбъект.Ссылка;
// или через реквизит формы, если он добавлен
КонецПроцедуры
В модуле формы обычного объекта ЭтотОбъект указывает на объект данных (например, ДокументОбъект), у которого свойство «Ссылка» доступно напрямую. Если форма построена на реквизите с другим именем, обращайтесь к нему: ДокументОбъект.Ссылка.
Обычные формы встречаются всё реже, но поддерживать их приходится в старых конфигурациях. Главное отличие: там нет разделения на клиентский и серверный контекст в том виде, как в управляемом приложении, поэтому ограничений на вызов методов меньше.
Получение ссылки из формы списка и табличной части
Часто ссылка нужна не из формы самого объекта, а из формы списка — например, чтобы обработать выделенный документ. В динамическом списке текущая строка доступна через элемент формы:
&НаКлиенте
Процедура ОбработатьТекущий(Команда)
ТекущаяСсылка = Элементы.Список.ТекущиеДанные.Ссылка;
Если ТекущаяСсылка = Неопределено Тогда
Возврат;
КонецЕсли;
КонецПроцедуры
Обратите внимание: если курсор стоит на пустой области списка, ТекущиеДанные будет равно Неопределено, и обращение к «Ссылка» вызовет ошибку. Проверка обязательна.
Для табличной части объекта логика та же: Элементы.Товары.ТекущиеДанные вернёт строку, но у строк табличной части нет собственной ссылки — у неё есть только ссылки на связанные объекты (номенклатуру, договор и т.п.). Например, Элементы.Товары.ТекущиеДанные.Номенклатура — это уже готовая ссылка на элемент справочника.
Когда нужен объект, а не ссылка: преобразование данных формы
Иногда ссылки недостаточно — нужно программно изменить объект на сервере. Для этого данные формы преобразуют в объект:
&НаСервере
Процедура ИзменитьОбъектНаСервере()
ДокОбъект = РеквизитФормыВЗначение("Объект");
ДокОбъект.Комментарий = "Изменён программно";
ДокОбъект.Записать();
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры
Методы РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы() работают только в серверном контексте. После записи объекта обязательно верните данные обратно в форму, иначе пользователь увидит устаревшие значения.
Если нужно только получить объект по уже известной ссылке (например, вне формы), используйте Ссылка.ПолучитьОбъект(). Но внутри формы объекта это делать не нужно — данные уже загружены в реквизит формы.
Навигационная ссылка на форму объекта
Не путайте ссылку на объект базы данных с навигационной ссылкой формы. Навигационная ссылка — это строка вида e1cib/data/Документ.РеализацияТоваровУслуг?ref=..., которую можно передать коллеге или вставить в письмо, чтобы открыть конкретный объект.
Получить её можно функцией ПолучитьНавигационнуюСсылку(Объект.Ссылка). В пользовательском интерфейсе навигационная ссылка доступна через кнопку «Получить ссылку» в командной панели формы. Для программной обработки данных используйте обычную ссылку, для обмена с пользователями — навигационную.
Сравнение вариантов
Основной способ в форме объекта. Работает на клиенте и сервере, не требует обращения к базе. Для нового объекта вернёт пустую ссылку.
Для форм списков. Требует проверки на Неопределено, работает только на клиенте.
Когда нужен полный объект для изменения на сервере. Избыточен, если нужна только ссылка.
Для передачи ссылки пользователю в виде строки. Не подходит для запросов и программной работы с данными.
Проверка результата и частые проблемы
После получения ссылки убедитесь, что она корректна. Основные контрольные точки: ссылка заполнена, её тип соответствует ожидаемому объекту, а сам объект существует в базе (не удалён и не является «битой» ссылкой).
Если ЗначениеЗаполнено(ТекущаяСсылка)
И ТипЗнч(ТекущаяСсылка) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
// работаем со ссылкой
КонецЕсли;
«Битая» ссылка возникает, когда объект удалён, а ссылки на него остались. Проверить её можно попыткой обращения к реквизиту через запрос или проверкой Ссылка.ПолучитьОбъект() = Неопределено (последний способ ресурсоёмкий, используйте запрос при массовых проверках).
Как проверить результат
ЗначениеЗаполнено(Ссылка) = Истина
Пустая ссылка — объект не записан или строка не выбрана
ТипЗнч() возвращает ожидаемый тип
Неопределено или тип другого объекта — неверный источник данных
Запрос по ссылке возвращает запись
Запрос пуст — объект удалён, ссылка битая
FAQ
Как получить ссылку на объект, открытый в другой форме?
Через параметры при открытии: в форме-источнике вызовите ОткрытьФорму() с параметрами, а в форме-приёмнике обработайте их в ПриСозданииНаСервере через Параметры.Ссылка (или другое имя параметра). Альтернатива — оповещения через Оповестить() и ОбработкаОповещения().
Почему Объект.Ссылка возвращает пустое значение?
Объект ещё не записан в базу. Новый документ или элемент справочника получает ссылку только после записи. Вызовите Записать() или проверьте заполненность перед использованием ссылки.
Можно ли получить ссылку на клиенте без вызова сервера?
Да. Объект.Ссылка и Элементы.Список.ТекущиеДанные.Ссылка доступны в клиентском контексте, серверный вызов не требуется. Сервер нужен только для преобразования данных формы в объект или обращения к базе.
Чем ссылка отличается от уникального идентификатора?
Уникальный идентификатор (GUID) — это часть ссылки, доступная через Ссылка.УникальныйИдентификатор(). Ссылка дополнительно содержит информацию о типе объекта, поэтому платформа знает, к какой таблице она относится.
Как получить ссылку из строки табличной части?
У самой строки табличной части ссылки нет. Но реквизиты строки ссылочного типа (Номенклатура, Контрагент и т.п.) уже являются ссылками: Элементы.Товары.ТекущиеДанные.Номенклатура вернёт ссылку на элемент справочника.
Что делать, если ТекущиеДанные равны Неопределено?
Это значит, что в списке нет активной строки — курсор не установлен или список пуст. Добавьте проверку: Если Элементы.Список.ТекущиеДанные = Неопределено Тогда Возврат; КонецЕсли. Иначе обращение к свойству вызовет ошибку выполнения.
Что важно запомнить
В форме объекта ссылка доступна через Объект.Ссылка, в форме списка — через Элементы.Список.ТекущиеДанные.Ссылка с обязательной проверкой на Неопределено. Новый объект не имеет ссылки до записи. Для изменения данных на сервере используйте РеквизитФормыВЗначение, для передачи пользователю — навигационную ссылку.