Структуру подчиненности документа можно увидеть, запустив из документа общую форму "ФормаСтруктурыПодчиненности". Но как получить связанные документы для обработки данных? Я взял процедуры из модуля этой формы, немного поколдовал, и превратил их в пару функций, возвращающих список документов из структуры подчиненности нужного документа. Нужно отметить, что иерархии подчиненности в результатах работы функций нет, в отличие от процедур, работающих с деревом значений в форме. Вот хочу поделиться результатом со всеми, так как мне самому бывает приятно заполучить иногда кусочек готового кода, который впоследствие можно использовать для решения своих задач.
Функция ПолучитьРодительскиеДокументы(ДокументСсылка, СписокСвязанныхДокументов = Неопределено, мУжеВСписке = Неопределено) Экспорт
Если СписокСвязанныхДокументов = Неопределено Тогда
СписокСвязанныхДокументов = Новый СписокЗначений;
КонецЕсли;
Если мУжеВСписке = Неопределено Тогда
мУжеВСписке = Новый Соответствие;
КонецЕсли;
МетаданныеДокумента = ДокументСсылка.Метаданные();
СписокРеквизитов = Новый СписокЗначений;
Для Каждого Реквизит ИЗ МетаданныеДокумента.Реквизиты Цикл
ТипыРеквизита = Реквизит.Тип.Типы();
Для Каждого ТекущийТип ИЗ ТипыРеквизита Цикл
МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);
Если МетаданныеРеквизита<>Неопределено И Метаданные.Документы.Содержит(МетаданныеРеквизита)
И ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
Попытка
ЗначениеРеквизита = ДокументСсылка[Реквизит.Имя];
Исключение
Прервать;
КонецПопытки;
ЕСли ЗначениеРеквизита<>Неопределено И НЕ ЗначениеРеквизита.Пустая() И ТипЗнч(ЗначениеРеквизита) = ТекущийТип
И мУжеВСписке[ЗначениеРеквизита] = Неопределено И СписокРеквизитов.НайтиПоЗначению(ДокументСсылка[Реквизит.Имя]) = Неопределено Тогда
Попытка
СписокРеквизитов.Добавить(ЗначениеРеквизита,Формат(ЗначениеРеквизита.Дата,"ДФ=yyyyMMddЧЧММсс"));
Исключение
ОтладкаТекстОшибки = ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Для Каждого ТЧ Из МетаданныеДокумента.ТабличныеЧасти Цикл
СтрРеквизитов = "";
Попытка
СодержимоеТЧ = ДокументСсылка[ТЧ.Имя].Выгрузить();
Исключение
Прервать;
КонецПопытки;
Для Каждого Реквизит ИЗ ТЧ.Реквизиты Цикл
ТипыРеквизита = Реквизит.Тип.Типы();
Для Каждого ТекущийТип ИЗ ТипыРеквизита Цикл
МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);
Если МетаданныеРеквизита<>Неопределено И Метаданные.Документы.Содержит(МетаданныеРеквизита)
И ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
СтрРеквизитов = СтрРеквизитов + ?(СтрРеквизитов = "", "", ", ") + Реквизит.Имя;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
СодержимоеТЧ.Свернуть(СтрРеквизитов);
Для Каждого КолонкаТЧ ИЗ СодержимоеТЧ.Колонки Цикл
Для Каждого СтрокаТЧ ИЗ СодержимоеТЧ Цикл
Попытка
ЗначениеРеквизита = СтрокаТЧ[КолонкаТЧ.Имя];
Исключение
Продолжить;
КонецПопытки;
МетаданныеЗначения = Метаданные.НайтиПоТипу(ТипЗнч(ЗначениеРеквизита));
Если МетаданныеЗначения = Неопределено Тогда
// базовый тип
Продолжить;
КонецЕсли;
ЕСли ЗначениеРеквизита<>Неопределено И НЕ ЗначениеРеквизита.Пустая()
И Метаданные.Документы.Содержит(МетаданныеЗначения)
И мУжеВСписке[ЗначениеРеквизита] = Неопределено Тогда
Если СписокРеквизитов.НайтиПоЗначению(ЗначениеРеквизита) = Неопределено Тогда
Попытка
СписокРеквизитов.Добавить(ЗначениеРеквизита,Формат(ЗначениеРеквизита.Дата,"ДФ=yyyyMMddЧЧММсс"));
Исключение
ОтладкаТекстОшибки = ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
мУжеВСписке.Вставить(ДокументСсылка, Истина);
Для Каждого СтрСЗ Из СписокРеквизитов Цикл
СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(СтрСЗ.Значение, СписокСвязанныхДокументов, мУжеВСписке);
КонецЦикла;
Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка
| ИЗ Документ."+МетаданныеДокумента.Имя + " ГДЕ Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Выборка = Запрос.Выполнить().Выбрать();
ЕСли Выборка.Следующий() Тогда
СписокСвязанныхДокументов.Добавить(Выборка.Ссылка);
Иначе
СписокСвязанныхДокументов.Добавить(ДокументСсылка);
КонецЕсли;
Возврат СписокСвязанныхДокументов;
КонецФункции
Функция ПолучитьПодчиненныеДокументы(ДокументСсылка, СписокСвязанныхДокументов = Неопределено, мУжеВСписке = Неопределено) Экспорт
Если СписокСвязанныхДокументов = Неопределено Тогда
СписокСвязанныхДокументов = Новый СписокЗначений;
КонецЕсли;
Если мУжеВСписке = Неопределено Тогда
мУжеВСписке = Новый Соответствие;
КонецЕсли;
Таблица = ПолныеПрава.ПолучитьВыборкуПоКритериюОтбора("СвязанныеДокументы", ДокументСсылка);
КэшПоТипамДокументов = Новый Соответствие;
Для Каждого СтрокаТаблицы ИЗ Таблица Цикл
МетаданныеДокумента = СтрокаТаблицы.Ссылка.Метаданные();
Если Не ПравоДоступа("Чтение", МетаданныеДокумента) Тогда
Продолжить;
КонецЕсли;
ИмяДокумента = МетаданныеДокумента.Имя;
СинонимДокумента = МетаданныеДокумента.Синоним;
СтруктураТипа = КэшПоТипамДокументов[ИмяДокумента];
Если СтруктураТипа = Неопределено Тогда
СтруктураТипа = Новый Структура("Синоним, МассивСсылок", СинонимДокумента, Новый Массив);
КэшПоТипамДокументов.Вставить(ИмяДокумента, СтруктураТипа);
КонецЕсли;
СтруктураТипа.МассивСсылок.Добавить(СтрокаТаблицы.Ссылка);
КонецЦикла;
ЕСли КэшПоТипамДокументов.Количество() = 0 Тогда
Возврат СписокСвязанныхДокументов;
КонецЕсли;
ТекстЗапросаНачало = "ВЫБРАТЬ РАЗРЕШЕННЫЕ * ИЗ (";
ТекстЗапросаКонец = ") КАК ПодчиненныеДокументы ";
Запрос = Новый Запрос;
Для Каждого КлючИЗначение ИЗ КэшПоТипамДокументов Цикл
Запрос.Текст = Запрос.Текст + ?(Запрос.Текст = "", "
|ВЫБРАТЬ ", "
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ") + "
|Ссылка
|ИЗ Документ." + КлючИЗначение.Ключ + "
|ГДЕ Ссылка В (&" + КлючИЗначение.Ключ + ")";
Запрос.УстановитьПараметр(КлючИЗначение.Ключ, КлючИЗначение.Значение.МассивСсылок);
КонецЦикла;
Запрос.Текст = ТекстЗапросаНачало + Запрос.Текст + ТекстЗапросаКонец;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если мУжеВСписке[Выборка.Ссылка] = Неопределено Тогда
СписокСвязанныхДокументов.Добавить(Выборка.Ссылка);
мУжеВСписке.Вставить(Выборка.Ссылка, Истина);
СписокСвязанныхДокументов = ПолучитьПодчиненныеДокументы(Выборка.Ссылка, СписокСвязанныхДокументов, мУжеВСписке);
КонецЕсли;
КонецЦикла;
Возврат СписокСвязанныхДокументов;
КонецФункции
Основной параметр функций "ДокументСсылка" - обязательный. Это ссылка на документ, для которого будем получать родительские (подчиненные) документы.
Также может быть полезен в работе параметр "СписокСвязанныхДокументов". Он не является обязательным, и используется для хранения списка документов из структуры подчиненности. Его можно задать, если, например, нужен общий список и родительских, и подчиненных документов.
Примеры:
1. Получение общего списка родительских документов двух и более документов.
СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка1);
СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка2, СписокСвязанныхДокументов);
2. Получение общего списка и родительских, и подчиненных документов.
СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка);
СписокСвязанныхДокументов = ПолучитьПодчиненныеДокументы(ДокументСсылка, СписокСвязанныхДокументов);
Дополнение:
Функция ПолучитьВыборкуПоКритериюОтбора(ИмяКритерияОтбора, ЗначениеКритерия) Экспорт
Запрос = Новый Запрос;
ТекстЗапроса = "";
Для Каждого ЭлементСостава ИЗ Метаданные.КритерииОтбора[ИмяКритерияОтбора].Состав Цикл
Если Не ЭлементСостава.Тип.СодержитТип(ТипЗнч(ЗначениеКритерия)) Тогда
Продолжить;
КонецЕсли;
ПутьКДанным = ЭлементСостава.ПолноеИмя();
СтруктураПутьКДанным = ОбщегоНазначения.РазобратьПутьКОбъектуМетаданных(ПутьКДанным, ЭлементСостава.Родитель());
ЕСли НЕ ПравоДоступа("Чтение", СтруктураПутьКДанным.Метаданные) Тогда
Продолжить;
КонецЕсли;
ИмяОбъекта = СтруктураПутьКДанным.ТипОбъекта + "." + СтруктураПутьКДанным.ВидОбъекта;
ПсевдонимТаблицы = СтруктураПутьКДанным.ТипОбъекта + "_" + СтруктураПутьКДанным.ВидОбъекта + "_" + СтруктураПутьКДанным.ИмяТаблЧасти;
ТекущаяСтрокаГДЕ = "ГДЕ " + ПсевдонимТаблицы + "." +СтруктураПутьКДанным.ИмяРеквизита + " = &ЗначениеКритерияОтбора";
ИмяТЧ = Лев(СтруктураПутьКДанным.ИмяРеквизита, Найти(СтруктураПутьКДанным.ИмяРеквизита, ".")-1);
ИмяРеквизита = Лев(СтруктураПутьКДанным.ИмяРеквизита, Найти(СтруктураПутьКДанным.ИмяРеквизита, ".")-1);
ТекстЗапроса = ТекстЗапроса + (?(ТекстЗапроса = "", "ВЫБРАТЬ", "ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ") + "
|" + ПсевдонимТаблицы + ".Ссылка ИЗ " + ИмяОбъекта + "." + СтруктураПутьКДанным.ИмяТаблЧасти + " КАК " + ПсевдонимТаблицы + "
|" + СтрЗаменить(ТекущаяСтрокаГДЕ, "..", ".") + "
|");
КонецЦикла;
Если ТекстЗапроса = "" Тогда
Возврат Новый ТаблицаЗначений;
КонецЕсли;
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерия);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Функция РазобратьПутьКОбъектуМетаданных(ПутьКДанным, МетаданныеОбъекта = Неопределено) Экспорт
Структура = Новый Структура;
СоответствиеИмен = Новый Массив();
СоответствиеИмен.Добавить("ТипОбъекта");
СоответствиеИмен.Добавить("ВидОбъекта");
СоответствиеИмен.Добавить("ПутьКДанным");
СоответствиеИмен.Добавить("ИмяТаблЧасти");
СоответствиеИмен.Добавить("ИмяРеквизита");
Для индекс = 1 по 3 Цикл
Точка = Найти(ПутьКДанным, ".");
ТекущееЗначение = Лев(ПутьКДанным, Точка-1);
Структура.Вставить(СоответствиеИмен[индекс-1], ТекущееЗначение);
ПутьКДанным = Сред(ПутьКДанным, Точка+1);
КонецЦикла;
ПутьКДанным = СтрЗаменить(ПутьКДанным, "Реквизит.", "");
Если Структура.ПутьКДанным = "ТабличнаяЧасть" Тогда
Для индекс = 4 по 5 Цикл
Точка = Найти(ПутьКДанным, ".");
Если Точка = 0 Тогда
ТекущееЗначение = ПутьКДанным;
Иначе
ТекущееЗначение = Лев(ПутьКДанным, Точка-1);
КонецЕсли;
Структура.Вставить(СоответствиеИмен[индекс-1], ТекущееЗначение);
ПутьКДанным = Сред(ПутьКДанным, Точка+1);
КонецЦикла;
Иначе
Структура.Вставить(СоответствиеИмен[3], "");
Структура.Вставить(СоответствиеИмен[4], ПутьКДанным);
КонецЕсли;
Если МетаданныеОбъекта <> Неопределено Тогда
Структура.Вставить("Метаданные", МетаданныеОбъекта);
Иначе
Если Структура.ТипОбъекта = "Документ" Тогда
Структура.Вставить("Метаданные", Метаданные.Документы[Структура.ВидОбъекта]);
Иначе
Структура.Вставить("Метаданные", Метаданные.Справочники[Структура.ВидОбъекта]);
КонецЕсли;
КонецЕсли;
Возврат Структура;
КонецФункции