Работа со ссылками на объекты метаданных — одна из ключевых задач при программировании в 1С:Предприятие. Часто разработчикам требуется получить сам объект (документ, справочник, регистр) по его ссылке, чтобы прочитать или изменить данные. В этой статье разберём все способы получения объектов по ссылкам, их особенности и типичные ошибки.
Ссылки в 1С — это не просто идентификаторы, а полноценные объекты со своими методами. Например, ссылка на документ Документ.ПоступлениеТоваров.Ссылка123 содержит информацию о типе объекта, его уникальном идентификаторе и даже о базе данных. Умение правильно работать с такими ссылками позволяет оптимизировать код и избегать лишних обращений к базе.
Статья будет полезна как начинающим разработчикам 1С, так и опытным специалистам, которые хотят систематизировать знания о работе с метаданными через ссылки.
Что такое ссылка на объект метаданных в 1С
Ссылка в 1С:Предприятие — это объект, который однозначно идентифицирует другой объект конфигурации (документ, справочник, план счетов и т.д.). Ссылка содержит:
- 🔹 Тип объекта (например,
Справочник.НоменклатураилиДокумент.РеализацияТоваровУслуг) - 🔹 Уникальный идентификатор (GUID или числовой ID)
- 🔹 Ссылку на базу данных (если работа ведётся в распределённой информационной базе)
Важно понимать, что ссылка — это не сам объект, а только указатель на него. Например, если у вас есть ссылка на документ, это не значит, что документ уже загружен в память. Для работы с самим объектом его нужно получить из базы данных.
Ссылки в 1С бывают:
- 📌 Пустые (значение
НеопределеноилиСсылка.ПустаяСсылка()) - 📌 Непустые (указывают на существующий объект)
- 📌 Удаленные (указывают на объект, который был удален, но ссылка сохранена)
⚠️ Внимание: При работе с распределёнными базами данных ссылки могут быть локальными (указывают на объект в текущей базе) или глобальными (указывают на объект в другой базе РИБ). Методы получения объекта по ссылке могут работать по-разному в зависимости от типа ссылки.
Основные методы получения объекта по ссылке
В 1С:Предприятие есть несколько способов получить объект метаданных по его ссылке. Рассмотрим основные методы и их особенности.
1. Метод ПолучитьОбъект()
Самый распространённый способ — использование метода ПолучитьОбъект(). Он доступен для большинства ссылочных типов и возвращает сам объект (документ, элемент справочника и т.д.).
Пример использования:
СсылкаНаДокумент = Документы.ПоступлениеТоваров.НайтиПоНомеру("ПТ-000001");
Если Не СсылкаНаДокумент.Пустая() Тогда
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Сообщить("Дата документа: " + ДокументОбъект.Дата);
КонецЕсли;
Особенности метода ПолучитьОбъект():
- 🔸 Работает для документов, справочников, планов счетов, планов видов характеристик, планов видов расчёта
- 🔸 Возвращает объект в режиме чтения/изменения (в зависимости от прав пользователя)
- 🔸 Может вызвать исключение, если объект удалён или недоступен
2. Метод ПолучитьСсылку()
Обратный метод — ПолучитьСсылку() — используется, когда у вас уже есть объект, и вы хотите получить его ссылку. Но иногда его применяют в комбинации с другими методами для проверки существования объекта.
Пример:
ЭлементСправочника = Справочники.Номенклатура.НайтиПоНаименованию("Товар 1");
Если ЭлементСправочника <> Неопределено Тогда
СсылкаНаЭлемент = ЭлементСправочника.Ссылка;
Сообщить("Ссылка получена: " + СсылкаНаЭлемент);
КонецЕсли;
3. Функция СсылкаНаОбъект()
Для создания ссылки на объект по его типу и идентификатору используется функция СсылкаНаОбъект(). Это полезно, когда вы знаете тип и ID объекта, но не хотите выполнять поиск по базе.
Пример:
Ссылка = СсылкаНаОбъект("Документ.ПоступлениеТоваров", Новый УникальныйИдентификатор("123e4567-e89b-12d3-a456-426614174000"));
Объект = Ссылка.ПолучитьОбъект();
⚠️ Внимание: При использованииСсылкаНаОбъект()с несуществующим идентификатором методПолучитьОбъект()вызовет ошибку. Всегда проверяйте существование объекта черезСсылка.Пустая()илиСсылка.Существует()(если доступен).
Работа с разными типами объектов
Способы получения объектов по ссылке могут отличаться в зависимости от типа метаданных. Рассмотрим особенности работы с наиболее распространёнными типами.
1. Документы
Для документов метод ПолучитьОбъект() возвращает объект документа в режиме чтения или редактирования (в зависимости от прав). РеализацияТоваровУслуг.НайтиПоНомеру("РТУ-00001");
Если Не СсылкаНаДокумент.Пустая() Тогда
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если ДокументОбъект.Проведен Тогда
ДокументОбъект.ОтменитьПроведение();
КонецЕсли;
ДокументОбъект.Дата = ТекущаяДата();
ДокументОбъект.Записать();
КонецЕсли;
2. Справочники
Для элементов справочников метод ПолучитьОбъект() возвращает объект элемента справочника. Особенности:
- 📋 Можно получать как элементы, так и группы справочника
- 📋 Для иерархических справочников доступны методы
ЭтоГруппа()иРодитель - 📋 При работе с подчинёнными справочниками (например,
Справочник.Номенклатура.Баркоды) требуется указывать полный путь
Пример:
СсылкаНаЭлемент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");
Если Не СсылкаНаЭлемент.Пустая() Тогда
ЭлементОбъект = СсылкаНаЭлемент.ПолучитьОбъект();
Сообщить("ИНН контрагента: " + ЭлементОбъект.ИНН);
КонецЕсли;
3. Регистры сведений и накопления
Для регистров метод ПолучитьОбъект() не применяется. Вместо этого используются:
- 📊
ПолучитьПоследний()— для регистров сведений - 📊
СоздатьМенеджерЗаписи()— для создания записи - 📊
Выбрать()— для выборки данных
Пример работы с регистром сведений:
МенеджерЗаписи = РегистрыСведений.ЦеныНоменклатуры.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар 1");
МенеджерЗаписи.Цена = 1000;
МенеджерЗаписи.Записать();
| Тип объекта | Метод получения | Особенности |
|---|---|---|
| Документ | ПолучитьОбъект() |
Может требовать отмены проведения перед редактированием |
| Справочник | ПолучитьОбъект() |
Работает для элементов и групп |
| Регистр сведений | ПолучитьПоследний(), СоздатьМенеджерЗаписи() |
Прямого метода ПолучитьОбъект() нет |
| План счетов | ПолучитьОбъект() |
Возвращает объект счета с реквизитами (валютой, забалансовым и т.д.) |
Типичные ошибки и их решение
При работе со ссылками и получением объектов разработчики часто сталкиваются с ошибками. Рассмотрим наиболее распространённые из них и способы их избежать.
1. Ошибка "Объект не найден"
Эта ошибка возникает, когда вы пытаетесь получить объект по ссылке, которая:
- 🚫 Указывает на удаленный объект
- 🚫 Содержит неверный идентификатор
- 🚫 Ссылается на объект в другой базе РИБ, который недоступен
Решение:
Ссылка =..; // Ваша ссылка
Если Не Ссылка.Пустая() И Ссылка.Существует() Тогда
Объект = Ссылка.ПолучитьОбъект();
Иначе
Сообщить("Объект не существует или недоступен!");
КонецЕсли;
2. Ошибка "Недостаточно прав"
Если у пользователя нет прав на чтение объекта, метод ПолучитьОбъект() вызовет исключение. Чтобы избежать этого, проверяйте права заранее:
Если ПраваДоступа.ПроверкаПравНаОбъект(Ссылка, "Чтение") Тогда
Объект = Ссылка.ПолучитьОбъект();
Иначе
Сообщить("У вас нет прав на просмотр этого объекта!");
КонецЕсли;
3. Ошибка "Объект заблокирован"
В многопользовательском режиме объект может быть заблокирован другим пользователем. В этом случае попытка получить объект вызовет ошибку. Решения:
- 🔓 Использовать
ПолучитьОбъектДляИзменения()с таймаутом - 🔓 Повторять попытку через некоторое время
- 🔓 Уведомить пользователя о блокировке
Пример:
Попытка
Объект = Ссылка.ПолучитьОбъектДляИзменения(10); // Таймаут 10 секунд
Исключение
Сообщить("Объект заблокирован. Попробуйте позже.");
КонецПопытки;
⚠️ Внимание: В 1С:Предприятие 8.3.20+ появился метод ПолучитьОбъектБезОжидания(), который не блокируется на ожидании освобождения объекта, а сразу возвращает ошибку, если объект занят. Это удобно для фоновых задач.
Проверьте, что ссылка не пустая|Убедитесь, что объект существует|Проверьте права доступа|Обработайте возможную блокировку объекта-->
Оптимизация работы со ссылками
При интенсивной работе со ссылками и объектами важно оптимизировать код, чтобы избежать лишних обращений к базе данных. Вот несколько советов:
1. Кэширование объектов
Если вам нужно многократно обращаться к одному и тому же объекту, имеет смысл кэшировать его в памяти:
Если Не ЗначениеЗаполнено(КэшОбъектов) Тогда
КэшОбъектов = Новый Соответствие;
КонецЕсли;
Если Не КэшОбъектов.Содержит(Ссылка.УникальныйИдентификатор()) Тогда
КэшОбъектов.Вставить(Ссылка.УникальныйИдентификатор(), Ссылка.ПолучитьОбъект());
КонецЕсли;
Объект = КэшОбъектов.Получить(Ссылка.УникальныйИдентификатор());
2. Массовое получение объектов
Если нужно получить много объектов по ссылкам, лучше использовать массовые методы, например, ПолучитьОбъектыПоСсылкам() (доступен в некоторых конфигурациях):
СписокСсылок = Новый Массив;
СписокСсылок.Добавить(Ссылка1);
СписокСсылок.Добавить(Ссылка2);
СписокОбъектов = ПолучитьОбъектыПоСсылкам(СписокСсылок);
3. Использование менеджеров объектов
Для некоторых типов объектов (например, документов) удобно использовать менеджеры:
МенеджерДокументов = Документы.ПоступлениеТоваров.ПолучитьМенеджерЗаписи();
МенеджерДокументов.Загрузить(Ссылка);
Объект = МенеджерДокументов.Объект;
Преимущества такого подхода:
- ⚡ Уменьшение количества обращений к базе
- ⚡ Возможность пакетной обработки
- ⚡ Упрощение кода при работе с большими объёмами данных
Если вам нужно получить объекты по ссылкам в цикле, сначала соберите все ссылки в массив, а затем получите объекты пакетом. Это сократит количество транзакций и ускорит выполнение.
Работа со ссылками в распределённых базах (РИБ)
В распределённых информационных базах (РИБ) ссылки могут быть локальными (указывают на объект в текущей базе) или глобальными (указывают на объект в другой базе узла РИБ). Это добавляет сложности при получении объектов.
1. Проверка типа ссылки
Перед получением объекта по ссылке в РИБ необходимо проверить, является ли ссылка локальной:
Если Ссылка.ЭтоЛокальная() Тогда
Объект = Ссылка.ПолучитьОбъект();
Иначе
Сообщить("Ссылка на объект в другой базе РИБ. Невозможно получить напрямую.");
КонецЕсли;
2. Получение объекта из другой базы РИБ
Для работы с глобальными ссылками используйте механизмы обмена данными РИБ:
Если Не Ссылка.ЭтоЛокальная() Тогда
ДанныеОбъекта = ПланыОбмена.ОсновнойПланОбмена.ПолучитьДанныеПоСсылке(Ссылка);
// Обработка полученных данных
КонецЕсли;
3. Особенности работы с РИБ
При работе в РИБ учитывайте:
- 🌐 Задержки синхронизации — объект может ещё не существовать в текущей базе
- 🌐 Конфликты версий — объект мог быть изменён в другой базе
- 🌐 Ограничения прав — доступ к объектам других баз может быть ограничен
⚠️ Внимание: В 1С:Предприятие 8.3.18+ появилась возможность работы с универсальными ссылками, которые автоматически разрешаются в локальные при получении объекта. Это упрощает работу в РИБ, но требует настройки плана обмена.
Как узнать, из какой базы РИБ пришла ссылка?
Чтобы определить узел РИБ, из которого пришла глобальная ссылка, используйте метод Ссылка.ПолучитьИдентификаторУзла(). Он возвращает идентификатор узла РИБ, в котором был создан объект. Например:
Если Не Ссылка.ЭтоЛокальная() Тогда
ИдентификаторУзла = Ссылка.ПолучитьИдентификаторУзла();
Сообщить("Объект создан в узле: " + ИдентификаторУзла);
КонецЕсли;
Практические примеры использования
Рассмотрим несколько реальных сценариев, в которых требуется получить объект по ссылке.
1. Получение и изменение документа
Допустим, нам нужно найти документ по номеру, получить его объект и изменить дату:
СсылкаНаДокумент = Документы.ЗаказПокупателя.НайтиПоНомеру("ЗП-00042");
Если Не СсылкаНаДокумент.Пустая() Тогда
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Если ДокументОбъект.Проведен Тогда
ДокументОбъект.ОтменитьПроведение();
КонецЕсли;
ДокументОбъект.Дата = ТекущаяДата() + 1; // Завтрашняя дата
ДокументОбъект.Записать();
Сообщить("Документ успешно изменён!");
Иначе
Сообщить("Документ не найден!");
КонецЕсли;
2. Проверка и получение элемента справочника
Пример проверки существования элемента справочника и получения его объекта:
СсылкаНаЭлемент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Весна");
Если СсылкаНаЭлемент.Пустая() Тогда
Сообщить("Контрагент не найден!");
ИначеЕсли Не СсылкаНаЭлемент.Существует() Тогда
Сообщить("Контрагент помечен на удаление!");
Иначе
ЭлементОбъект = СсылкаНаЭлемент.ПолучитьОбъект();
Сообщить("ИНН контрагента: " + ЭлементОбъект.ИНН);
КонецЕсли;
3. Массовая обработка ссылок
Пример обработки списка ссылок с оптимизацией:
СписокСсылок = Новый Массив;
СписокСсылок.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 1"));
СписокСсылок.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 2"));
Для Каждого Ссылка Из СписокСсылок Цикл
Если Не Ссылка.Пустая() Тогда
Попытка
Объект = Ссылка.ПолучитьОбъект();
Объект.Комментарий = "Обработано " + ТекущаяДата();
Объект.Записать();
Исключение
Сообщить("Ошибка при обработке: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Всегда обрабатывайте исключения при массовой обработке ссылок. Одна "битая" ссылка не должна прерывать выполнение всего процесса.
FAQ: Часто задаваемые вопросы
Можно ли получить объект по ссылке, если он помечен на удаление?
Да, но только если у вас есть соответствующие права. Метод ПолучитьОбъект() вернёт объект, но при попытке записи может возникнуть ошибка, если объект уже удалён физически. Чтобы избежать проблем, проверяйте статус объекта через Ссылка.ПометкаУдаления():
Если Не Ссылка.ПометкаУдаления() Тогда
Объект = Ссылка.ПолучитьОбъект();
КонецЕсли;
Как получить объект по ссылке в фоновом задании?
В фоновом задании метод ПолучитьОбъект() работает так же, как и в обычном режиме, но важно учитывать:
- 🔄 Фоновые задания выполняются в отдельной транзакции
- 🔄 Объекты, заблокированные в основной сессии, могут быть недоступны
- 🔄 Рекомендуется использовать
ПолучитьОбъектБезОжидания(), чтобы избежать блокировок
Чем отличаются методы ПолучитьОбъект() и ПолучитьОбъектДляИзменения()?
Основные различия:
| Метод | Режим доступа | Блокировка | Использование |
|---|---|---|---|
ПолучитьОбъект() |
Чтение | Не блокирует объект | Для просмотра данных |
ПолучитьОбъектДляИзменения() |
Чтение + изменение | Блокирует объект | Для редактирования данных |
Если вы планируете только читать данные, используйте ПолучитьОбъект() — это снизит нагрузку на базу.
Как получить объект по ссылке в управляемом приложении (тонкий клиент, веб-клиент)?
В управляемом приложении методы работы со ссылками такие же, но учитывайте:
- 🖥️ Объекты передаются между клиентом и сервером автоматически
- 🖥️ Для сложных операций используйте серверные процедуры
- 🖥️ В веб-клиенте может быть ограничение на размер передаваемых данных
Пример серверной функции для получения объекта:
&НаСервере
Функция ПолучитьОбъектПоСсылке(Ссылка)
Возврат Ссылка.ПолучитьОбъект();
КонецФункции
Можно ли получить объект по ссылке из другой конфигурации (например, из БП в УТ)?
Нет, напрямую это невозможно. Ссылки привязаны к конкретной конфигурации и базе данных. Для обмена данными между разными конфигурациями используйте:
- 🔗 Планы обмена (для связанных баз)
- 🔗 Внешние обработки с передачей данных через параметры
- 🔗 Файловый обмен (XML, JSON)
- 🔗 Web-сервисы (для интеграции)