Работа со справочниками в 1С:Предприятие часто требует доступа не только к самим элементам, но и к их владельцам — объектам, которым эти элементы подчинены. Например, в справочнике "Номенклатура" владельцем может выступать склад, подразделение или контрагент. Неправильное обращение к владельцу приводит к ошибкам типа "Объект не найден" или "Недопустимое значение", а в некоторых случаях — к нарушению логики бизнес-процессов.
В этой статье разберём 5 проверенных способов получить ссылку на владельца справочника: от простых методов встроенного языка до работы с метаданными через конфигуратор. Все примеры актуальны для платформ 1С 8.3 и 8.2, но с учётом особенностей конкретных конфигураций (например, УТ 11, БП 3.0, ЗУП 3.1). Если вы разрабатываете типовой отчёт или дорабатываете функционал, эти методы помогут избежать типичных ошибок и оптимизировать код.
Особое внимание уделим разнице между получением владельца через свойство Владелец и метод ПолучитьОбъект() — это критично для справочников с иерархией и подчинёнными объектами. Также рассмотрим, как обойти ограничения, когда владелец не виден в пользовательском режиме, но доступен через конфигуратор.
1. Способ: Использование свойства "Владелец" объекта справочника
Самый очевидный и быстрый метод — обращение к свойству Владелец у элемента справочника. Он работает, если:
- 📌 Справочник имеет владельца (настроено в конфигураторе).
- 🔍 Вы работаете с конкретным элементом, а не со списком.
- 🔄 Владелец не скрыт настройками прав доступа.
Пример кода для получения владельца элемента справочника "Контрагенты":
СсылкаНаЭлемент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");
Если Не СсылкаНаЭлемент.Пустая() Тогда
Владелец = СсылкаНаЭлемент.Владелец;
Сообщить("Владелец: " + Владелец.Наименование);
КонецЕсли;
⚠️ Внимание: Если справочник не имеет владельца (например, Номенклатура в базовой поставке УТ 11), свойство Владелец вернёт Неопределённое значение. Перед использованием проверяйте наличие владельца через функцию ТипЗнч(СсылкаНаЭлемент.Владелец) <> Тип("Неопределено").
Чтобы узнать, имеет ли справочник владельца, откройте его в конфигураторе: правой кнопкой по справочнику → Свойства → вкладка Владельцы.
2. Способ: Метод "ПолучитьОбъект()" для подчинённых справочников
Если справочник подчинён другому объекту (например, "Договоры контрагентов" подчинён "Контрагентам"), владелец может быть получен через метод ПолучитьОбъект(). Этот метод возвращает объект владельца, а не просто ссылку, что удобно для дальнейшей работы с его свойствами.
Пример для справочника "ДоговорыКонтрагентов":
СсылкаНаДоговор = Справочники.ДоговорыКонтрагентов.НайтиПоНаименованию("Договор №123");
Если Не СсылкаНаДоговор.Пустая() Тогда
ОбъектДоговора = СсылкаНаДоговор.ПолучитьОбъект();
Владелец = ОбъектДоговора.Владелец; // Ссылка на контрагента
Сообщить("Владелец договора: " + Владелец.Наименование);
КонецЕсли;
Ключевое отличие от первого способа: ПолучитьОбъект() позволяет работать с реквизитами владельца напрямую, без дополнительных запросов. Например, вы можете сразу получить ИНН контрагента:
ИННВладельца = Владелец.ИНН;
Что делать, если метод возвращает ошибку "Объект не найден"?
Ошибка возникает, если:
1. Элемент справочника удалён, но ссылка ещё существует в базе.
2. У пользователя нет прав на чтение владельца.
3. Владелец — это объект другой базы (в распределённых информационных системах).
В таких случаях используйте конструкцию Попытка...Исключение для обработки ошибки.
3. Способ: Запрос к базе данных с JOIN по владельцу
Для массовой обработки элементов справочника (например, в отчётах или обработках) удобно использовать запросы с соединением по полю владельца. Это позволяет получить владельцев для всех элементов за один проход, не нагружая систему циклами.
Пример запроса для справочника "Сотрудники" (владелец — "Подразделения"):
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Сотрудники.Ссылка КАК Сотрудник,
| Сотрудники.Владелец КАК Подразделение
|ИЗ
| Справочник.Сотрудники КАК Сотрудники
|ГДЕ
| НЕ Сотрудники.ПометкаУдаления
| И Сотрудники.Владелец ССЫЛКА Справочник.Подразделения";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Сотрудник.Наименование + " → " + Выборка.Подразделение.Наименование);
КонецЦикла;
Преимущества метода:
- ⚡ Быстродействие: один запрос вместо сотен обращений к свойству
Владелец. - 🔗 Гибкость: можно добавить фильтры по дате, статусу или другим реквизитам.
- 📊 Удобство для отчётов: результат выборки можно сразу передать в СКД.
Используйте псевдонимы (например, КАК Подразделение) для удобства чтения кода и избежания конфликтов имён.
4. Способ: Работа с метаданными через конфигуратор
Если владелец справочника не виден в пользовательском режиме (например, из-за ограничений прав), его можно найти через конфигуратор. Этот способ полезен для администраторов и разработчиков, которые настраивают обмены данными или исправляют ошибки конфигурации.
Инструкция:
- Откройте конфигуратор (
1Cv8.exe /config). - Найдите нужный справочник в дереве метаданных (раздел
Справочники). - Правой кнопкой →
Свойства→ вкладкаВладельцы. - Посмотрите, какой объект указан как владелец (например, Справочник.Контрагенты).
Если владелец динамический (зависит от условий), его можно найти через глобальный поиск:
- В конфигураторе нажмите
Ctrl+Shift+F. - Введите название справочника (например,
ДоговорыКонтрагентов). - Просмотрите результаты, чтобы найти код, где назначается владелец.
Убедитесь, что база не заблокирована другими пользователями|
Сделайте резервную копию перед изменениями|
Проверьте права доступа в роли "Администратор"|
Запишите путь к владельцу для дальнейшего использования в коде-->
5. Способ: Отладчик и выражение "Вычислить"
Когда стандартные методы не работают (например, владелец не отображается из-за ошибки в конфигурации), поможет отладчик. С его помощью можно вручную вычислить владельца для конкретного элемента.
Пошаговая инструкция:
- Откройте нужный справочник в пользовательском режиме.
- Найдите элемент, владелец которого вас интересует.
- Нажмите
Ctrl+Alt+F9(илиОтладка → Вычислить выражение). - Введите выражение:
ТекущийЭлемент.Владелецили (если владелец скрыт):
ТекущийЭлемент.ПолучитьОбъект().Владелец - Нажмите
Вычислить— отладчик покажет ссылку на владельца или ошибку.
Если выражение возвращает Неопределено, проверьте:
- 🔍 Настроена ли иерархия владельцев в конфигураторе.
- 🔒 Есть ли у текущего пользователя права на чтение владельца.
- 🗑️ Не помечен ли элемент или владелец на удаление.
В отладчике можно использовать ?ТекущийЭлемент (со знаком вопроса), чтобы увидеть все свойства объекта, включая скрытые.
Сравнение методов: какой выбрать?
Выбор способа зависит от задачи, объёма данных и ограничений конфигурации. Ниже таблица с сравнением ключевых параметров:
| Способ | Скорость | Подходит для массовой обработки | Требует прав администратора | Работает с удалёнными объектами |
|---|---|---|---|---|
Свойство Владелец |
⚡ Быстро | ❌ Нет | ❌ Нет | ❌ Нет |
Метод ПолучитьОбъект() |
⚡ Быстро | ❌ Нет | ❌ Нет | ✅ Да |
| Запрос с JOIN | ⚡⚡ Очень быстро | ✅ Да | ❌ Нет | ❌ Нет |
| Конфигуратор | 🐢 Медленно | ❌ Нет | ✅ Да | ✅ Да |
| Отладчик | 🐢 Медленно | ❌ Нет | ✅ Да | ✅ Да |
⚠️ Внимание: Если вы работаете с распределённой базой 1С (РИБ), владелец может находиться в другой базе. В этом случае используйте методы ПланыОбмена или обратитесь к администратору для синхронизации данных.
Типичные ошибки и как их избежать
Ошибка 1: "Объект не найден" при обращении к владельцу
Причина: владельца не существует (удалён) или у пользователя нет прав. Решение:
Попытка
Владелец = Элемент.Владелец;
Исключение
Сообщить("Владелец не найден или недоступен!");
Владелец = Неопределено;
КонецПопытки;
Ошибка 2: Циклическая ссылка при рекурсивном получении владельцев
Причина: справочник ссылается сам на себя (например, в иерархических структурах). Решение — ограничить глубину рекурсии:
Процедура ПолучитьВладельца(Элемент, МаксГлубина = 5)
Если МаксГлубина = 0 Тогда
Возврат Неопределено;
КонецЕсли;
Возврат ?(Элемент.Владелец <> Неопределено, ПолучитьВладельца(Элемент.Владелец, МаксГлубина - 1), Неопределено);
КонецПроцедуры
Ошибка 3: Некорректное сравнение ссылок на владельцев
Причина: ссылки сравниваются как объекты, а не как значения. Решение — использовать Ссылка1.Сравнить(Ссылка2) или приведение к строке:
Если Строка(Владелец1) = Строка(Владелец2) Тогда
// Владельцы совпадают
КонецЕсли;
Почему иногда владелец возвращается, но его свойства недоступны?
Это происходит, если владелец — объект другой конфигурации (например, в комплектах расширений) или его метаданные изменены. В таких случаях используйте Метаданные().НайтиПоИмени(), чтобы проверить структуру владельца.
FAQ: Частые вопросы по работе с владельцами справочников
Можно ли изменить владельца элемента справочника программно?
Да, но только если это разрешено настройками справочника. Используйте метод УстановитьВладельца():
Элемент.УстановитьВладельца(НовыйВладелец);
⚠️ Внимание: изменение владельца может нарушить ссылки в связанных документах (например, в заказах или актах).
Как получить владельца для группы справочника?
Группы в справочниках (например, папки в Номенклатуре) тоже могут иметь владельцев. Используйте тот же метод:
Группа = Справочники.Номенклатура.НайтиПоНаименованию("Мебель");
ВладелецГруппы = Группа.Владелец;
Если группа — корневая, владелец будет Неопределено.
Почему при обмене данными владельцы справочников не передаются?
В настройках плана обмена (ПланыОбмена.Основной) может быть отключена передача владельцев. Проверьте:
- Откройте план обмена в конфигураторе.
- Перейдите на вкладку
Правила обмена. - Убедитесь, что для справочника включено свойство
Владелец.
Если проблема остаётся, используйте обработку ПриЗаписи для ручного назначения владельцев после загрузки.
Как найти все элементы справочника без владельца?
Используйте запрос с фильтром по Владелец Есть NULL:
Запрос.Текст =
"ВЫБРАТЬ
| Элементы.Ссылка
|ИЗ
| Справочник.ИмяСправочника КАК Элементы
|ГДЕ
| Элементы.Владелец Есть NULL";
Можно ли получить владельца через OData или REST?
Да, но только если владелец опубликован в интерфейсе OData. Пример запроса:
GET /odata/standard.odata/Catalog_Номенклатура?$expand=Owner
Если владелец не отображается, проверьте настройки публикации в Администрирование → Публикация на веб-сервере.