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