Разработка и Конфигурация · 10 мин
Как получить вышестоящее подразделение в 1С
Как получить вышестоящее подразделение в 1С: реквизит Родитель, запрос с иерархией, функция обхода уровней, проверка результата и типичные ошибки разработчика.
Вышестоящее подразделение в 1С — это родительский элемент справочника «Подразделения» (или «Подразделения организаций»), к которому относится текущая запись. Получить его можно двумя базовыми способами: через стандартный реквизит Родитель (Parent) либо через запрос с учётом иерархии. Выбор зависит от задачи: нужен только ближайший уровень вверх или вся цепочка до корня структуры.
В типовых конфигурациях (БП, ЗУП, ERP, УТ) справочник подразделений имеет иерархию вида «иерархия элементов» или «иерархия групп и элементов». Это принципиально важно: при иерархии групп и элементов родителем элемента может быть только группа, и обращение к реквизиту работает иначе, чем в плоской структуре. Перед написанием кода откройте свойства справочника в конфигураторе и уточните вид иерархии.
Ниже разобраны рабочие способы: обращение через точку, безопасное чтение реквизита, запрос с конструкцией ИЕРАРХИЯ, функция поиска верхнего уровня и варианты для тонкого клиента без обращения к серверу лишний раз. Приведены проверки результата и типичные ошибки, из-за которых код возвращает пустую ссылку или падает с исключением.
Как устроена иерархия подразделений в 1С
Справочник «Подразделения» в типовых решениях — иерархический. Каждый элемент хранит ссылку на родителя в системном реквизите Родитель. Если элемент находится на верхнем уровне, реквизит содержит пустую ссылку — это нормальное состояние, а не ошибка данных.
Различайте два режима иерархии. При «иерархии элементов» любое подразделение может быть родителем другого подразделения. При «иерархии групп и элементов» родителем выступает только группа (папка), а конечные подразделения не могут иметь потомков. В ЗУП и ERP чаще встречается второй вариант, в Бухгалтерии — зависит от настроек и версии.
Также учитывайте, что в некоторых конфигурациях существуют два разных справочника: «Подразделения» (структура предприятия) и «Подразделения организаций» (учётная структура). Убедитесь, что работаете именно с тем справочником, который используется в ваших документах и отчётах.
Получение родителя через реквизит Родитель
Самый быстрый способ — обратиться к реквизиту через точку от ссылки. Платформа выполнит неявный запрос к базе и вернёт ссылку на родительский элемент:
ВышестоящееПодразделение = ТекущееПодразделение.Родитель;
Если ЗначениеЗаполнено(ВышестоящееПодразделение) Тогда
Сообщить("Вышестоящее: " + ВышестоящееПодразделение);
Иначе
Сообщить("Это подразделение верхнего уровня");
КонецЕсли;
Обращение через точку удобно для разовых операций, но в цикле по сотням элементов оно генерирует отдельный запрос на каждое обращение — это заметно замедляет код. В массовых обработках получайте родителя запросом сразу для всей выборки.
Если у вас есть не ссылка, а объект (например, в модуле объекта или формы элемента), реквизит Родитель доступен напрямую без дополнительного обращения к базе: Объект.Родитель.
- 1Убедитесь, что переменная содержит заполненную ссылку на подразделение
- 2Прочитайте реквизит: Ссылка.Родитель
- 3Проверьте результат функцией ЗначениеЗаполнено()
- 4Если родитель пуст — обработайте случай верхнего уровня отдельно
Получение родителя запросом
Запрос — правильный выбор, когда родитель нужен для списка подразделений или когда требуется сразу получить дополнительные поля родителя (наименование, код, руководителя). Пример:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Подразделения.Ссылка КАК Подразделение,
| Подразделения.Родитель КАК ВышестоящееПодразделение,
| Подразделения.Родитель.Наименование КАК НаименованиеРодителя
|ИЗ
| Справочник.ПодразделенияОрганизаций КАК Подразделения
|ГДЕ
| Подразделения.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ТекущееПодразделение);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
РодительНайден = Выборка.ВышестоящееПодразделение;
КонецЕсли;
Обратите внимание на конструкцию Подразделения.Родитель.Наименование — это разыменование через точку в запросе. Оно допустимо, но при больших выборках лучше использовать левое соединение к той же таблице по полю Родитель: запрос становится прозрачнее и легче оптимизируется.
Имя справочника в тексте запроса должно совпадать с именем в конфигураторе: в одних конфигурациях это Справочник.Подразделения, в других — Справочник.ПодразделенияОрганизаций или Справочник.СтруктураПредприятия. Если запрос возвращает ошибку «поле не найдено», первым делом проверьте имя.
Получение всей цепочки вышестоящих подразделений
Реквизит Родитель возвращает только один уровень вверх. Если нужен корень структуры или вся цепочка (например, для построения полного пути «Холдинг / Департамент / Отдел»), используйте итоги по иерархии или цикл.
Цикл обхода родителей
Универсальный вариант — функция с циклом, которая поднимается вверх до пустой ссылки:
Функция ПолучитьВышестоящиеПодразделения(Подразделение) Экспорт
Результат = Новый Массив;
Текущий = Подразделение.Родитель;
Пока ЗначениеЗаполнено(Текущий) Цикл
Результат.Добавить(Текущий);
Текущий = Текущий.Родитель;
КонецЦикла;
Возврат Результат;
КонецФункции
Массив заполняется от ближайшего родителя к самому верхнему. Если нужен только корень — берите последний элемент массива. Для защиты от зацикливания при некорректных данных можно добавить счётчик итераций с разумным пределом.
Запрос с ИЕРАРХИЯ
Для проверки вхождения подразделения в конкретную ветку используйте оператор В ИЕРАРХИИ. Он отвечает на обратный вопрос — «входит ли элемент в поддерево заданного родителя» — и широко применяется в отборах отчётов:
ГДЕ
| Подразделения.Ссылка В ИЕРАРХИИ(&ГоловноеПодразделение)
Этот оператор учитывает все уровни вложенности автоматически, без циклов и рекурсии. Именно его рекомендуется применять в отчётах СКД, когда пользователь выбирает вышестоящее подразделение и ожидает данные по всем подчинённым.
Как выбрать способ
Проверка результата и обработка крайних случаев
Любой код, получающий вышестоящее подразделение, должен корректно обрабатывать три ситуации: пустая исходная ссылка, отсутствие родителя (верхний уровень) и удалённый или битый родитель. Пропуск этих проверок — частая причина ошибок «Поле объекта не обнаружено» в журнале регистрации.
Проверяйте результат через ЗначениеЗаполнено() до обращения к его реквизитам. Если нужно отличить «родителя нет» от «ссылка битая», используйте Родитель.ПолучитьОбъект() в попытке или проверку через запрос — битая ссылка в запросе просто не даст строк при соединении.
Как проверить результат
Заполненная ссылка или осознанно обработанная пустая ссылка
Обращение к реквизитам без проверки на пустоту
Код корректно завершается и сообщает об отсутствии родителя
Исключение или молчаливая запись пустого значения в документ
Один запрос для всей выборки
Обращение Ссылка.Родитель внутри цикла по сотням элементов
Типичные ошибки и ограничения
Первая ошибка — обращение Ссылка.Родитель.Родитель без промежуточных проверок. Если промежуточный родитель пуст, вторая часть выражения вызовет исключение. Разбивайте цепочку на шаги с проверками.
Вторая ошибка — путаница между справочниками. Код ищет родителя в «Подразделения», а документ использует «Подразделения организаций» — результат всегда пустой, хотя структура в базе заполнена. Сверяйте тип реквизита документа в конфигураторе.
Третья ошибка — игнорирование прав доступа. Пользователь с ограниченными правами может не видеть часть ветки: запрос вернёт меньше данных, чем ожидает разработчик. Тестируйте код под профилем реального пользователя, а не только под полными правами.
Отдельное ограничение касается клиентского кода: в тонком клиенте обращение Ссылка.Родитель недоступно вне контекста сервера в ряде сценариев. Выносите получение родителя в серверную процедуру общего модуля с признаком «Сервер» и «Вызов сервера».
FAQ
Как получить подразделение самого верхнего уровня?
Используйте цикл обхода родителей: поднимайтесь от текущего элемента вверх, пока реквизит Родитель не станет пустым. Последний непустой элемент цепочки и есть корень. Готовая функция приведена в разделе про цепочку вышестоящих подразделений.
Почему Родитель возвращает пустую ссылку, хотя структура заполнена?
Чаще всего элемент действительно находится на верхнем уровне, либо вы работаете не с тем справочником (например, «Подразделения» вместо «Подразделения организаций»). Проверьте элемент в режиме предприятия: откройте его форму и посмотрите поле «Входит в группу» или аналогичное.
Можно ли получить вышестоящее подразделение без программирования?
Да. Откройте справочник подразделений в режиме предприятия, включите отображение в виде дерева — родитель виден визуально. Также в карточке элемента обычно выводится группа-родитель, а в отчётах по структуре организации доступна вся иерархия.
Как в запросе выбрать все подразделения, подчинённые вышестоящему?
Примените условие ГДЕ Ссылка В ИЕРАРХИИ(&Родитель). Оператор учитывает все уровни вложенности. Если параметр может быть пустым, добавьте ветку условия, иначе отбор не вернёт ожидаемых данных.
Работает ли обращение Ссылка.Родитель в тонком клиенте?
Разыменование ссылки на клиенте ограничено и зависит от контекста. Надёжный подход — вызывать серверную функцию общего модуля, которая вернёт родителя или нужные его поля одним вызовом.
Чем отличается Родитель от Владельца у справочника?
Родитель — это элемент иерархии внутри самого справочника (вышестоящее подразделение). Владелец — ссылка на объект другого справочника, которому подчинён элемент (например, организация). Для вышестоящего подразделения нужен именно Родитель.
Что важно запомнить
Вышестоящее подразделение хранится в системном реквизите Родитель. Для разового доступа достаточно Ссылка.Родитель, для массовой обработки — запроса, для цепочки вверх — цикла, для отбора потомков — оператора В ИЕРАРХИИ. Всегда проверяйте результат на пустую ссылку и используйте правильный справочник конфигурации.