Работа с иерархией документов в 1С:Предприятие — одна из самых востребованных задач при автоматизации бизнес-процессов. Часто требуется не просто получить список документов, а выстроить их в логическую цепочку: заказ → реализация → оплата → возврат. Без понимания структуры подчиненности невозможно корректно анализировать данные, строить отчеты или настраивать сложные бизнес-логики.
В этой статье мы разберем 5 программных методов извлечения иерархии документов — от стандартных механизмов платформы до неочевидных приемов с использованием Запроса, МенеджераВременныхТаблиц и даже внешних обработок. Особое внимание уделим скрытым связям между документами, которые не отображаются в интерфейсе, но критичны для анализа. Материал будет полезен как начинающим разработчикам, так и опытным специалистам, столкнувшимся с нетипичными сценариями.
1. Стандартные механизмы платформы: движение по ссылкам
Самый очевидный способ — использовать встроенные ссылки между документами. В большинстве типовых конфигураций (1С:Бухгалтерия, 1С:УТ, 1С:ERP) документы автоматически ссылаются друг на друга через реквизиты типа СсылкаНаДокумент или Основание.
Например, в документе "Реализация товаров и услуг" есть реквизит ЗаказКлиента, а в документе "Поступление безналичных ДС" — реквизит Основание, который может ссылаться на реализацию. Чтобы получить цепочку программно, достаточно рекурсивно обходить эти ссылки:
Процедура ПолучитьЦепочкуДокументов(НачальныйДокумент)
Цепочка = Новый Массив;
ТекущийДокумент = НачальныйДокумент;
Пока ТекущийДокумент <> Неопределено Цикл
Цепочка.Добавить(ТекущийДокумент);
// Проверяем возможные типы оснований
Если ТипЗнч(ТекущийДокумент.Основание) = Тип("ДокументСсылка") Тогда
ТекущийДокумент = ТекущийДокумент.Основание.ПолучитьОбъект();
ИначеЕсли ТипЗнч(ТекущийДокумент.ЗаказКлиента) = Тип("ДокументСсылка") Тогда
ТекущийДокумент = ТекущийДокумент.ЗаказКлиента.ПолучитьОбъект();
Иначе
ТекущийДокумент = Неопределено;
КонецЕсли;
КонецЦикла;
Возврат Цепочка;
КонецПроцедуры
Этот метод работает быстро и не требует сложных конструкций, но имеет ограничения:
- 🔹 Подходит только для документов с явными ссылками (не все конфигурации поддерживают полную цепочку)
- 🔹 Не учитывает документы, связанные через регистры (например, заказы поставщикам, привязанные к заказам клиентов через регистр
ЗаказыПоставщикам) - 🔹 Может зациклиться, если в цепочке есть кольцевые ссылки (нужна защита от рекурсии)
Всегда добавляйте в рекурсивные процедуры счетчик итераций (например, Если Цепочка.Количество() > 100 Тогда Прервать;), чтобы избежать зависания при кольцевых ссылках.
2. Использование запроса: универсальный подход для любых связей
Если стандартные ссылки не покрывают вашу задачу, на помощь приходит язык запросов 1С. С его помощью можно построить цепочку документов даже по косвенным связям — через регистры накопления, сведения или произвольные таблицы.
Рассмотрим пример для конфигурации 1С:Управление торговлей, где нужно получить цепочку: Заказ клиента → Реализация → Оплата → Возврат. Здесь связи хранятся в разных местах:
- Заказ и реализация связаны через реквизит ЗаказКлиента в документе реализации.
- Реализация и оплата — через регистр ВзаиморасчетыСКлиентами.
- Возврат ссылается на реализацию через реквизит Реализация.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказы.Ссылка КАК Заказ,
| Реализации.Ссылка КАК Реализация,
| Оплаты.Ссылка КАК Оплата,
| Возвраты.Ссылка КАК Возврат
|ИЗ
| Документ.ЗаказКлиента КАК Заказы
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализации
| ПО Заказы.Ссылка = Реализации.ЗаказКлиента
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ВзаиморасчетыСКлиентами.Остатки КАК Остатки
| ПО Остатки.ДокументРасчетов = Реализации.Ссылка
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеБезналичныхДС КАК Оплаты
| ПО Остатки.Партнер = Оплаты.Контрагент И Остатки.Договор = Оплаты.Договор
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.ВозвратТоваровОтКлиента КАК Возвраты
| ПО Возвраты.Реализация = Реализации.Ссылка
|ГДЕ
| Заказы.Ссылка = &СсылкаНаЗаказ";
Запрос.УстановитьПараметр("СсылкаНаЗаказ", СсылкаНаЗаказКлиента);
Результат = Запрос.Выполнить().Выгрузить();
Этот подход гибкий, но требует глубокого знания структуры базы. Основные сложности:
- 📌 Нужно точно знать, в каких регистрах хранятся связи (в разных конфигурациях они могут отличаться)
- 📌 Запросы с множеством соединений могут тормозить на больших базах
- 📌 Не все связи можно выразить через SQL-подобный синтаксис (иногда нужны временные таблицы)
3. Временные таблицы: обработка сложных иерархий
Когда цепочка документов разветвленная или связи хранятся в нескольких регистрах, на помощь приходят временные таблицы. Они позволяют поэтапно собирать данные и строить иерархию даже для нетривиальных сценариев.
Пример: нужно получить все документы, связанные с заказом поставщику, включая:
- Счета на оплату поставщику
- Поступления товаров
- Корректировки поступлений
- Возвраты поставщику
Алгоритм будет таким:
- Создать временную таблицу для хранения цепочки
- Добавить в нее начальный документ (заказ поставщику)
- Поочередно искать связанные документы каждого типа и добавлять их в таблицу
- Исключать дубли и кольцевые ссылки
Процедура ПостроитьЦепочкуПоставщика(СсылкаНаЗаказ)
// Создаем временную таблицу
ТаблицаЦепочки = Новый ТаблицаЗначений;
ТаблицаЦепочки.Колонки.Добавить("Документ", Новый ОписаниеТипов("ДокументСсылка"));
ТаблицаЦепочки.Колонки.Добавить("ТипСвязи", Новый ОписаниеТипов("Строка"));
// Добавляем начальный документ
НоваяСтрока = ТаблицаЦепочки.Добавить();
НоваяСтрока.Документ = СсылкаНаЗаказ;
НоваяСтрока.ТипСвязи = "Заказ поставщику";
// Ищем связанные счета на оплату
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ Счета.Ссылка
|ИЗ Документ.СчетНаОплатуПоставщику КАК Счета
|ГДЕ Счета.ЗаказПоставщику = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаЗаказ);
Результат = Запрос.Выполнить();
Пока Результат.Следующий() Цикл
НоваяСтрока = ТаблицаЦепочки.Добавить();
НоваяСтрока.Документ = Результат.Ссылка;
НоваяСтрока.ТипСвязи = "Счет на оплату";
КонецЦикла;
// Аналогично добавляем поступления, корректировки и возвраты
// ...
Возврат ТаблицаЦепочки;
КонецПроцедуры
Преимущества этого метода:
- 🔧 Позволяет обрабатывать связи любой сложности
- 🔧 Легко расширяется для новых типов документов
- 🔧 Можно добавлять дополнительные колонки (даты, суммы, статусы)
Создать структуру таблицы с нужными колонками|Добавить защиту от дублей|Определить все возможные типы связей|Проверить производительность на тестовых данных|Обработать исключения (например, отсутствие прав)
-->
4. Рекурсивные функции: обход дерева документов
Для документов с иерархической структурой (например, заказы с подзаказами или проекты с подпроектами) удобно использовать рекурсивные функции. Они позволяют обходить дерево документов вглубь, собирая все уровни подчиненности.
Пример: в конфигурации 1С:ERP заказ клиента может содержать подзаказы (документы "Заказ клиента" с установленным флагом ЭтоПодзаказ и ссылкой на родительский заказ). Чтобы получить полное дерево, напишем рекурсивную процедуру:
Функция ПолучитьДеревоЗаказов(РодительскийЗаказ, Уровень = 0)
Результат = Новый Структура("Заказ, Подзаказы");
Результат.Заказ = РодительскийЗаказ;
// Ищем подзаказы
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка
|ИЗ Документ.ЗаказКлиента
|ГДЕ РодительскийЗаказ = &Родитель И ЭтоПодзаказ = ИСТИНА";
Запрос.УстановитьПараметр("Родитель", РодительскийЗаказ);
Выборка = Запрос.Выполнить().Выбрать();
Подзаказы = Новый Массив;
Пока Выборка.Следующий() Цикл
Подзаказ = ПолучитьДеревоЗаказов(Выборка.Ссылка, Уровень + 1);
Подзаказы.Добавить(Подзаказ);
КонецЦикла;
Результат.Подзаказы = Подзаказы;
Возврат Результат;
КонецФункции
Этот метод идеален для визуализации иерархии, но имеет нюансы:
- 🌳 Глубина рекурсии ограничена (в 1С по умолчанию — 500 уровней)
- 🌳 При большом количестве подзаказов может возникнуть переполнение стека
- 🌳 Для оптимизации можно использовать не рекурсию, а стек или очередь
Как обойти ограничение на глубину рекурсии?
Вместо рекурсивной функции используйте цикл с явным управлением стека:
Стек = Новый Очередь;
Стек.Поместить(НачальныйЗаказ);
Пока Стек.Количество() > 0 Цикл
ТекущийЗаказ = Стек.Извлечь();
// Обработка текущего заказа
// ...
// Добавляем подзаказы в стек
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.ЗаказКлиента ГДЕ РодительскийЗаказ = &Текущий");
Запрос.УстановитьПараметр("Текущий", ТекущийЗаказ);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Стек.Поместить(Выборка.Ссылка);
КонецЦикла;
КонецЦикла;
5. Внешние обработки и расширения: готовые решения
Если вам нужно быстро получить структуру подчиненности без глубокого погружения в код, можно воспользоваться готовыми внешними обработками или расширениями. Многие разработчики выкладывают их на порталах вроде Infostart или 1С:ИТС.
Популярные решения:
- 📄 "Анализ связей документов" — показывает цепочки по всем возможным связям, включая регистры
- 📄 "Дерево документов" — визуализирует иерархию в виде дерева с возможностью фильтрации
- 📄 "Поиск дублей и связей" — находит неочевидные связи через регистры накопления
Преимущества внешних обработок:
| Преимущество | Недостаток |
|---|---|
| 🔹 Не нужно писать код | ❌ Может не подходить под вашу конфигурацию |
| 🔹 Часто содержат дополнительные функции (экспорт в Excel, графическая схема) | ❌ Требуют проверки на безопасность (особенно бесплатные) |
| 🔹 Поддерживаются сообществом (обновления, исправления багов) | ❌ Могут тормозить на больших базах |
Перед использованием внешней обработки всегда проверяйте ее в тестовой базе — некоторые решения могут конфликтовать с вашими доработками или типовыми механизмами.
Если вы решили написать свою обработку, обратите внимание на следующие моменты:
- 🛠 Используйте
Управляемые формыдля удобного интерфейса - 🛠 Добавьте возможность сохранения результатов в файл (
Excel,JSON) - 🛠 Реализуйте фильтры по датам, контрагентам, типам документов
Для визуализации связей между документами можно использовать библиотеку D3.js через механизм ВнедрениеHTML в 1С. Это позволит строить интерактивные графические схемы прямо в форме обработки.
Типичные ошибки и как их избежать
При работе со структурой подчиненности документов разработчики часто сталкиваются с одними и теми же проблемами. Вот наиболее распространенные ошибки и способы их решения:
1. Зацикливание при рекурсивном обходе
Если в цепочке документов есть кольцевые ссылки (например, документ А ссылается на документ Б, а документ Б — обратно на А), рекурсивная функция зависнет. Решение:
Процедура ОбойтиЦепочку(Документ, История = Новый Массив)
Если История.Найти(Документ) <> Неопределено Тогда
Возврат; // Уже обрабатывали этот документ
КонецЕсли;
История.Добавить(Документ);
// Далее обработка документа
// ...
КонецПроцедуры
2. Некорректная работа с правами доступа
Если пользователь не имеет прав на просмотр некоторых документов в цепочке, запрос или обход может прерваться с ошибкой. Решение:
- 🔐 Используйте
Попытка...Исключениедля обработки ошибок доступа - 🔐 Проверяйте права перед выполнением запросов
- 🔐 В внешних обработках запрашивайте повышенные права при необходимости
3. Долгая обработка больших цепочек
Если цепочка содержит сотни документов, обход может занять много времени. Решение:
- ⏳ Разбивайте обработку на части (например, по 50 документов за раз)
- ⏳ Используйте
Фоновые заданиядля длительных операций - ⏳ Кэшируйте промежуточные результаты
Всегда тестируйте ваш код на реальных данных с большим количеством связей — то, что работает на тестовой базе из 10 документов, может упасть на рабочей базе с 10 000 записей.
Практические примеры применения
Знание структуры подчиненности документов пригодится в самых разных задачах. Рассмотрим несколько реальных кейсов:
1. Анализ просроченных оплат
Задача: найти все заказы клиентов, по которым не поступила оплата в срок. Для этого нужно:
- Получить все заказы с просроченной датой оплаты
- Для каждого заказа найти связанные реализации
- Для каждой реализации проверить оплаты в регистре
ВзаиморасчетыСКлиентами - Вывести заказы, по которым сумма оплат меньше суммы реализаций
2. Построение отчета по логистике
Задача: проследить путь товара от заказа поставщику до отгрузки клиенту. Цепочка может включать:
- 📦 Заказ поставщику → Поступление товаров → Перемещение на склад → Отгрузка клиенту
- 📦 Возвраты от клиента → Возврат поставщику
3. Автоматическое формирование пакетов документов
Задача: при создании реализации автоматически формировать связанные документы (счет-фактуру, УПД, акт выполненных работ). Для этого нужно:
- 📑 Найти шаблоны документов в справочнике
ШаблоныДокументов - 📑 Создать новые документы на основе текущей реализации
- 📑 Заполнить реквизиты (контрагент, сумма, номенклатура) из родительского документа
- 📑 Сохранить связи в реквизитах
ОснованиеилиСвязанныйДокумент
4. Проверка корректности цепочек
Задача: найти документы с разорванными связями (например, реализация без заказа или оплата без реализации). Это помогает выявить ошибки ввода данных. Алгоритм:
- Получить все документы за период
- Для каждого документа проверить наличие обязательных связей
- Вывести список документов с отсутствующими ссылками
Как найти документы без связей?
Используйте запрос с условием ЕСТЬ NULL:
ВЫБРАТЬ
Реализации.Ссылка КАК Документ
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализации
ГДЕ
Реализации.ЗаказКлиента ЕСТЬ NULL
FAQ: Ответы на частые вопросы
Можно ли получить структуру подчиненности без программирования?
Да, в некоторых конфигурациях есть встроенные отчеты, показывающие связи между документами. Например, в 1С:ERP есть отчет "Анализ связей документов", а в 1С:УТ — "Движения документа". Однако эти отчеты обычно показывают только прямые связи и не позволяют гибко настраивать вывод.
Для сложных сценариев (например, построение цепочки из 10+ документов разных типов) без программирования не обойтись.
Как получить связи между документами в облачной версии 1С?
В 1С:Фреш и других облачных решениях доступ к базе ограничен, но вы можете:
- Использовать встроенные отчеты (если они есть в вашей конфигурации)
- Написать внешнюю обработку на
1Script(язык для облака) - Экспортировать данные в
Excelи анализировать связи там
Для сложных задач может потребоваться обратиться в поддержку 1С за доступом к расширенным механизмам.
Почему запрос возвращает не все связи?
Это может происходить по нескольким причинам:
- 🔍 Ограничения прав доступа — пользователь не видит некоторые документы
- 🔍 Неправильные соединения в запросе — например, используется
ВНУТРЕННЕЕ СОЕДИНЕНИЕвместоЛЕВОЕ - 🔍 Связи хранятся в неочевидных регистрах — проверьте структуру метаданных
- 🔍 Документы помечены на удаление — они не попадают в выборку без специальных условий
Чтобы диагностировать проблему, выполните запрос в консоли запросов (меню Все функции → Запросы) и проверьте промежуточные результаты.
Как визуализировать цепочку документов?
Есть несколько способов:
- Табличный вывод — простейший вариант, подходит для небольших цепочек. Можно использовать
ТаблицаЗначенийс колонками "Уровень", "Тип документа", "Номер", "Дата". - Дерево значений — в 1С есть объект
ДеревоЗначений, который позволяет отображать иерархию с раскрывающимися узлами. - Графическая схема — для этого понадобится внешняя компонента (например, GanttChart или OrgChart) или интеграция с Excel/Power BI.
- HTML-визуализация — с помощью
ВнедрениеHTMLи библиотек вроде D3.js или Vis.js можно строить интерактивные графики прямо в 1С.
Для быстрого прототипирования удобно использовать внешнюю обработку "Дерево документов" с портала Infostart.
Можно ли получить структуру подчиненности для удаленных документов?
Да, но с оговорками:
- 🗑 Помеченные на удаление документы не попадают в стандартные выборки. Чтобы их увидеть, добавьте в запрос условие
ПометкаУдаления = ЛОЖЬ ИЛИ ПометкаУдаления ЕСТЬ NULL. - 🗑 Удаленные документы (те, что уже физически удалены из базы) восстановить нельзя — их связи теряются безвозвратно.
- 🗑 В некоторых конфигурациях удаленные документы хранятся в архиве — проверьте наличие регистра
АрхивДокументов.
Если документ помечен на удаление, но вам нужны его связи, используйте метод ПолучитьОбъект() с флагом ПропускатьПомеченныеНаУдаление = Ложь:
ДокументОбъект = ДокументСсылка.ПолучитьОбъект(Ложь); // Второй параметр - пропускать помеченные на удаление
Теперь вы знаете все основные способы программного получения структуры подчиненности документов в 1С. Выбор метода зависит от задачи: для простых цепочек подойдут стандартные ссылки, для сложных анализа — запросы или временные таблицы, а для визуализации — внешние обработки. Не забывайте тестировать решения на реальных данных и учитывать особенности вашей конфигурации!