К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как программно получить структуру подчиненности документа в 1С

Как программно получить структуру подчиненности документа в 1С: критерии отбора, запросы по вводу на основании, примеры кода, типичные ошибки и проверка результата.

Структура подчиненности — это цепочка связанных документов, построенная по принципу «ввод на основании»: заказ → реализация → счет-фактура → оплата. В интерфейсе 1С она отображается отдельной формой, но разработчику часто нужно получить те же связи программно — для отчетов, обменов, проверок заполненности и автоматических обработок.

Универсального метода «вернуть структуру подчиненности» во встроенном языке нет. Есть три рабочих подхода: критерий отбора, прямой запрос к реквизитам-основаниям и обход по метаданным. Выбор зависит от конфигурации, глубины цепочки и требований к производительности.

Ниже разобраны все три способа с примерами кода, ограничениями каждого и способами проверить, что результат соответствует тому, что видит пользователь в форме «Структура подчиненности».

Как устроена связь документов в 1С

Подчиненность документов в 1С не хранится отдельной таблицей. Связь физически зашита в реквизиты документа: у «Реализации товаров и услуг» есть реквизит, содержащий ссылку на заказ, у счета-фактуры — ссылку на реализацию. Именно по этим ссылкам платформа и строит дерево.

Чтобы документ мог выступать основанием, у него в конфигураторе на вкладке «Ввод на основании» перечислены документы-основания и вводимые на его основе документы. Эти настройки определяют, какие реквизиты платформа будет считать связующими.

Важное следствие: если разработчик добавил свой реквизит со ссылкой на документ, но не включил его в механизм ввода на основании и в критерий отбора, стандартная форма структуры подчиненности такую связь не покажет. Программные способы, описанные ниже, позволяют обойти это ограничение.

Способ 1: критерий отбора «Структура подчиненности»

В типовых конфигурациях (БП, УТ, ERP, ЗУП) предопределен критерий отбора с именем «СтруктураПодчиненности». Он включает все реквизиты, через которые документы ссылаются друг на друга. Это самый короткий способ получить связанные документы:

bsl
СвязанныеДокументы = КритерииОтбора.СтруктураПодчиненности.Найти(ДокументСсылка);
Для Каждого Док Из СвязанныеДокументы Цикл
    Сообщить(Строка(Док));
КонецЦикла;

Метод Найти() возвращает массив ссылок на документы, у которых хотя бы один реквизит, входящий в критерий, равен переданной ссылке. То есть вы получите «потомков» — документы, введенные на основании текущего.

Чтобы найти документы-основания («родителей»), критерий не подходит напрямую — нужно перебрать реквизиты самого документа и отобрать те, что содержат ссылки на документы. Поэтому критерий отбора чаще используют для движения «вниз» по цепочке, а для движения «вверх» читают реквизиты объекта.

Ограничение способа: он возвращает плоский список без иерархии. Если нужно дерево «заказ → реализация → счет-фактура», придется вызывать Найти() рекурсивно для каждого найденного документа.

Способ 2: запрос по реквизитам-основаниям

Когда состав связей известен заранее (а в конкретной конфигурации это почти всегда так), эффективнее написать прямой запрос. Он выполняется одним обращением к базе и позволяет отбирать только нужные виды документов:

bsl
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Реализация.Ссылка
|ИЗ Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ Реализация.ДокументОснование = &Основание
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ СчетФактура.Ссылка
|ИЗ Документ.СчетФактура КАК СчетФактура
|ГДЕ СчетФактура.ДокументОснование = &Основание";
Запрос.УстановитьПараметр("Основание", ДокументСсылка);
Результат = Запрос.Выполнить().Выгрузить();

Имена реквизитов-оснований зависят от конфигурации: в одних это «ДокументОснование», в других — «ЗаказКлиента», «Сделка» и т.п. Точные имена смотрите в конфигураторе у конкретного документа или в свойствах критерия отбора — там перечислены все реквизиты, участвующие в связях.

Преимущество запроса — скорость и гибкость: можно сразу фильтровать по пометке удаления, проведенности, дате. Недостаток — при добавлении нового вида документов в цепочку запрос придется дорабатывать вручную.

Способ 3: универсальный обход по метаданным

Для универсальной обработки, которая должна работать с любой конфигурацией, перебирают метаданные документов и ищут реквизиты с типом «ссылка на документ». Схема такая:

Порядок действий
  1. 1
    Перебрать Метаданные.Документы и отобрать те, у которых есть реквизиты со ссылочным типом на документы
  2. 2
    Сформировать динамический запрос по каждому виду документа с условием Реквизит = &Ссылка
  3. 3
    Выполнить запросы пакетом и собрать найденные ссылки
  4. 4
    Для каждой найденной ссылки повторить поиск рекурсивно с контролем глубины
  5. 5
    Построить дерево значений: узел — документ, подчиненные строки — введенные на его основании

Такой подход лежит в основе типовых процедур построения структуры подчиненности в БСП (Библиотека стандартных подсистем). Если конфигурация построена на БСП, посмотрите модуль, отвечающий за структуру подчиненности, — там уже реализованы готовые функции получения дерева связанных документов, и изобретать механизм не нужно.

Универсальный обход — самый медленный вариант: поиск выполняется по всем видам документов, даже не участвующим в реальных цепочках. Используйте его, когда состав конфигурации заранее неизвестен, и обязательно ограничивайте глубину рекурсии и список проверяемых видов документов.

Сравнение способов и выбор под задачу

Сравнение вариантов

Критерий отбора

Подходит для быстрого поиска подчиненных документов в типовых конфигурациях. Ограничение: нет иерархии, не ищет основания, зависит от настройки критерия.

Прямой запрос

Оптимален для отчетов и обменов, когда состав цепочки известен. Ограничение: требует доработки при изменении конфигурации.

Обход метаданных

Единственный вариант для универсальных обработок и незнакомых конфигураций. Ограничение: низкая скорость, нужен контроль рекурсии.

Механизмы БСП

Готовое дерево подчиненности в конфигурациях на библиотеке стандартных подсистем. Ограничение: привязка к версии БСП и ее API.

Практическое правило: сначала проверьте, есть ли в конфигурации критерий «СтруктураПодчиненности» и какие реквизиты в него включены. Если он покрывает нужные связи — используйте его. Для регламентных отчетов с фиксированным составом документов пишите прямой запрос. Универсальный обход оставьте для сервисных обработок.

Маршрут решения

Как выбрать действие

Нужно быстро найти, что введено на основании документа, в типовой конфигурацииВызовите КритерииОтбора.СтруктураПодчиненности.Найти(Ссылка)
Нужны и основания, и потомки с фильтрами по дате и проведениюНапишите запрос по известным реквизитам-основаниям
Конфигурация неизвестна или обработка должна быть универсальнойРеализуйте обход метаданных с ограничением глубины рекурсии
Конфигурация на БСПИспользуйте готовые функции модуля структуры подчиненности библиотеки

Проверка результата и типичные ошибки

Простейший способ проверки — сравнить программный результат с формой «Структура подчиненности» в интерфейсе: откройте документ, вызовите стандартную команду и сверьте состав документов. Расхождение означает, что часть реквизитов не входит в критерий отбора либо в вашем запросе пропущен вид документа.

Контрольные точки

Как проверить результат

Состав найденных документов
Норма

Совпадает со стандартной формой структуры подчиненности

Тревожный признак

Часть документов отсутствует — не все реквизиты учтены

Помеченные на удаление
Норма

Отфильтрованы или явно обработаны

Тревожный признак

Попадают в отчеты и обмены как действующие

Глубина цепочки
Норма

Дерево обрывается на последнем реальном документе

Тревожный признак

Рекурсия не ограничена — риск зацикливания при циклических ссылках

Права доступа
Норма

Пользователь видит только доступные ему документы

Тревожный признак

Запрос в привилегированном режиме раскрывает лишние данные

Типичные ошибки
01
Использовать реквизит с именем «ДокументОснование», не проверив его реальное имя в конфигурации — запрос падает с ошибкой или возвращает пустоту
02
Забыть про циклические ссылки (корректировки, исправления) — рекурсивный обход уходит в бесконечный цикл; храните обработанные ссылки в соответствии
03
Не фильтровать пометку удаления — в структуру попадают «мертвые» документы
04
Выполнять поиск в цикле по одному документу вместо пакетного запроса — обработка большого массива работает в десятки раз медленнее
05
Полагаться только на критерий отбора в самописной конфигурации, где он не настроен — результат всегда пустой

Отдельный риск — права доступа. Если обработка выполняется в привилегированном режиме, она увидит документы, недоступные пользователю. Для интерактивных отчетов это может стать утечкой данных; решайте вопрос осознанно: либо не используйте привилегированный режим, либо явно фильтруйте результат по правам.

FAQ

Почему КритерииОтбора.СтруктураПодчиненности.Найти() возвращает пустой массив?

Чаще всего критерий отбора в конфигурации не заполнен или в него не включены нужные реквизиты. Откройте критерий в конфигураторе и проверьте его состав. Вторая причина — связь реализована через табличную часть или регистр сведений, а не через реквизит шапки: такие связи критерий не видит.

Как получить не только потомков, но и документы-основания?

Переберите реквизиты документа через метаданные: ДокументСсылка.Метаданные().Реквизиты, отберите те, чей тип содержит ссылки на документы, и прочитайте их значения из объекта. Непустые ссылки — это основания. Комбинируя это с поиском потомков, можно построить полную цепочку в обе стороны.

Как избежать зацикливания при рекурсивном обходе?

Ведите соответствие уже обработанных ссылок и перед рекурсивным вызовом проверяйте, не встречался ли документ раньше. Дополнительно задайте максимальную глубину (например, 10–20 уровней) — в реальных учетных цепочках она редко превышает 5–6.

Что делать, если связь документов хранится в табличной части?

Критерий отбора и стандартная форма такую связь не покажут. Пишите запрос с обращением к табличной части: ИЗ Документ.Оплата.ДокументыОснования с условием по реквизиту строки. Состав таких табличных частей определяется по конкретной конфигурации.

Можно ли получить структуру подчиненности без программирования?

Да, интерактивно: откройте документ и используйте стандартную команду «Структура подчиненности» (обычно в меню «Ещё» или на панели навигации). Но для отчетов, обменов и пакетных проверок нужен именно программный доступ — форма не экспортирует данные.

Итог

Что важно запомнить

Структура подчиненности строится по реквизитам-ссылкам, а не по отдельной таблице. В типовых конфигурациях используйте критерий отбора, для отчетов — прямой запрос, для универсальных обработок — обход метаданных с защитой от зацикливания. Всегда фильтруйте помеченные на удаление документы и сверяйте результат со стандартной формой.