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

Обновлено: 07.07.2024

Структуру подчиненности документа можно увидеть, запустив из документа общую форму "ФормаСтруктурыПодчиненности". Но как получить связанные документы для обработки данных? Я взял процедуры из модуля этой формы, немного поколдовал, и превратил их в пару функций, возвращающих список документов из структуры подчиненности нужного документа. Нужно отметить, что иерархии подчиненности в результатах работы функций нет, в отличие от процедур, работающих с деревом значений в форме. Вот хочу поделиться результатом со всеми, так как мне самому бывает приятно заполучить иногда кусочек готового кода, который впоследствие можно использовать для решения своих задач.

Основной параметр функций "ДокументСсылка" - обязательный. Это ссылка на документ, для которого будем получать родительские (подчиненные) документы.

Также может быть полезен в работе параметр "СписокСвязанныхДокументов". Он не является обязательным, и используется для хранения списка документов из структуры подчиненности. Его можно задать, если, например, нужен общий список и родительских, и подчиненных документов.

Примеры:

1. Получение общего списка родительских документов двух и более документов.

2. Получение общего списка и родительских, и подчиненных документов.

Дополнение:

Функция ПолучитьВыборкуПоКритериюОтбора(ИмяКритерияОтбора, ЗначениеКритерия) Экспорт

Запрос = Новый Запрос;
ТекстЗапроса = "";

Для Каждого ЭлементСостава ИЗ Метаданные.КритерииОтбора[ИмяКритерияОтбора].Состав Цикл

Если Не ЭлементСостава.Тип.СодержитТип(ТипЗнч(ЗначениеКритерия)) Тогда
Продолжить;
КонецЕсли;

ПутьКДанным = ЭлементСостава.ПолноеИмя();
СтруктураПутьКДанным = ОбщегоНазначения.РазобратьПутьКОбъектуМетаданных(ПутьКДанным, ЭлементСостава.Родитель());

ЕСли НЕ ПравоДоступа("Чтение", СтруктураПутьКДанным.Метаданные) Тогда
Продолжить;
КонецЕсли;

ИмяОбъекта = СтруктураПутьКДанным.ТипОбъекта + "." + СтруктураПутьКДанным.ВидОбъекта;
ПсевдонимТаблицы = СтруктураПутьКДанным.ТипОбъекта + "_" + СтруктураПутьКДанным.ВидОбъекта + "_" + СтруктураПутьКДанным.ИмяТаблЧасти;

ТекущаяСтрокаГДЕ = "ГДЕ " + ПсевдонимТаблицы + "." +СтруктураПутьКДанным.ИмяРеквизита + " = &ЗначениеКритерияОтбора";

ИмяТЧ = Лев(СтруктураПутьКДанным.ИмяРеквизита, Найти(СтруктураПутьКДанным.ИмяРеквизита, ".")-1);
ИмяРеквизита = Лев(СтруктураПутьКДанным.ИмяРеквизита, Найти(СтруктураПутьКДанным.ИмяРеквизита, ".")-1);
ТекстЗапроса = ТекстЗапроса + (?(ТекстЗапроса = "", "ВЫБРАТЬ", "ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ") + "
|" + ПсевдонимТаблицы + ".Ссылка ИЗ " + ИмяОбъекта + "." + СтруктураПутьКДанным.ИмяТаблЧасти + " КАК " + ПсевдонимТаблицы + "
|" + СтрЗаменить(ТекущаяСтрокаГДЕ, "..", ".") + "
|");

Если ТекстЗапроса = "" Тогда
Возврат Новый ТаблицаЗначений;
КонецЕсли;

Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерия);
Возврат Запрос.Выполнить().Выгрузить();

Функция РазобратьПутьКОбъектуМетаданных(ПутьКДанным, МетаданныеОбъекта = Неопределено) Экспорт

Структура = Новый Структура;

СоответствиеИмен = Новый Массив();
СоответствиеИмен.Добавить("ТипОбъекта");
СоответствиеИмен.Добавить("ВидОбъекта");
СоответствиеИмен.Добавить("ПутьКДанным");
СоответствиеИмен.Добавить("ИмяТаблЧасти");
СоответствиеИмен.Добавить("ИмяРеквизита");

Для индекс = 1 по 3 Цикл

Точка = Найти(ПутьКДанным, ".");
ТекущееЗначение = Лев(ПутьКДанным, Точка-1);
Структура.Вставить(СоответствиеИмен[индекс-1], ТекущееЗначение);
ПутьКДанным = Сред(ПутьКДанным, Точка+1);

ПутьКДанным = СтрЗаменить(ПутьКДанным, "Реквизит.", "");

Если Структура.ПутьКДанным = "ТабличнаяЧасть" Тогда

Для индекс = 4 по 5 Цикл

Точка = Найти(ПутьКДанным, ".");
Если Точка = 0 Тогда
ТекущееЗначение = ПутьКДанным;
Иначе
ТекущееЗначение = Лев(ПутьКДанным, Точка-1);
КонецЕсли;

Структура.Вставить(СоответствиеИмен[индекс-1], ТекущееЗначение);
ПутьКДанным = Сред(ПутьКДанным, Точка+1);

Структура.Вставить(СоответствиеИмен[3], "");
Структура.Вставить(СоответствиеИмен[4], ПутьКДанным);

Если МетаданныеОбъекта <> Неопределено Тогда
Структура.Вставить("Метаданные", МетаданныеОбъекта);
Иначе
Если Структура.ТипОбъекта = "Документ" Тогда
Структура.Вставить("Метаданные", Метаданные.Документы[Структура.ВидОбъекта]);
Иначе
Структура.Вставить("Метаданные", Метаданные.Справочники[Структура.ВидОбъекта]);
КонецЕсли;
КонецЕсли;

ДеревоДокументов = Новый ДеревоЗначений ;
ДеревоДокументов . Колонки . Добавить ( "Ссылка" );
ДеревоДокументов . Колонки . Добавить ( "ДокументПредставление" );
ДеревоДокументов . Колонки . Добавить ( "Проведен" );
ДеревоДокументов . Колонки . Добавить ( "ПометкаУдаления" );
ДеревоДокументов . Колонки . Добавить ( "ВидДокумента" );
мУжеВСписке = Новый Соответствие ;

мДерево = ДеревоДокументов ;
ВывестиРодительскиеДокументы ( Ссылка , мУжеВСписке , мДерево );
ВывестиПодчиненныеДокументы ( мДерево , мУжеВСписке );

КонецФункции
//
Процедура ВывестиРодительскиеДокументы ( ДокументСсылка , мУжеВСписке , мДерево )

МетаданныеДокумента = ДокументСсылка . Метаданные ();
СписокРеквизитов = Новый СписокЗначений ;

Для Каждого Реквизит ИЗ МетаданныеДокумента . Реквизиты Цикл
ТипыРеквизита = Реквизит . Тип . Типы ();
Для Каждого ТекущийТип ИЗ ТипыРеквизита Цикл
МетаданныеРеквизита = Метаданные . НайтиПоТипу ( ТекущийТип );

Если МетаданныеРеквизита <>Неопределено И Метаданные . Документы . Содержит ( МетаданныеРеквизита )
И ПравоДоступа ( "Чтение" , МетаданныеРеквизита ) Тогда
Попытка
ЗначениеРеквизита = ДокументСсылка [ Реквизит . Имя ];
Исключение
Прервать;
КонецПопытки;
ЕСли ЗначениеРеквизита <>Неопределено И НЕ ЗначениеРеквизита . Пустая () И ТипЗнч ( ЗначениеРеквизита ) = ТекущийТип
И мУжеВСписке [ ЗначениеРеквизита ] = Неопределено И СписокРеквизитов . НайтиПоЗначению ( ДокументСсылка [ Реквизит . Имя ]) = Неопределено Тогда
СписокРеквизитов . Добавить ( ЗначениеРеквизита , Формат ( ЗначениеРеквизита . Дата , "ДФ=yyyyMMddЧЧММсс" ));
КонецЕсли;
КонецЕсли;

Для Каждого ТЧ Из МетаданныеДокумента . ТабличныеЧасти Цикл
СтрРеквизитов = "" ;

Попытка
СодержимоеТЧ = ДокументСсылка [ ТЧ . Имя ]. Выгрузить ();
Исключение
Прервать;
КонецПопытки;

Для Каждого Реквизит ИЗ ТЧ . Реквизиты Цикл
ТипыРеквизита = Реквизит . Тип . Типы ();
Для Каждого ТекущийТип ИЗ ТипыРеквизита Цикл
МетаданныеРеквизита = Метаданные . НайтиПоТипу ( ТекущийТип );
Если МетаданныеРеквизита <>Неопределено И Метаданные . Документы . Содержит ( МетаданныеРеквизита )
И ПравоДоступа ( "Чтение" , МетаданныеРеквизита ) Тогда
СтрРеквизитов = СтрРеквизитов + ?( СтрРеквизитов = "" , "" , ", " ) + Реквизит . Имя ;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;

СодержимоеТЧ . Свернуть ( СтрРеквизитов );
Для Каждого КолонкаТЧ ИЗ СодержимоеТЧ . Колонки Цикл
Для Каждого СтрокаТЧ ИЗ СодержимоеТЧ Цикл
Попытка
ЗначениеРеквизита = СтрокаТЧ [ КолонкаТЧ . Имя ];
Исключение
Продолжить;
КонецПопытки;
МетаданныеЗначения = Метаданные . НайтиПоТипу ( ТипЗнч ( ЗначениеРеквизита ));
Если МетаданныеЗначения = Неопределено Тогда
// базовый тип
Продолжить;
КонецЕсли;

ЕСли ЗначениеРеквизита <>Неопределено И НЕ ЗначениеРеквизита . Пустая ()
И Метаданные . Документы . Содержит ( МетаданныеЗначения )
И мУжеВСписке [ ЗначениеРеквизита ] = Неопределено Тогда
Если СписокРеквизитов . НайтиПоЗначению ( ЗначениеРеквизита ) = Неопределено Тогда
СписокРеквизитов . Добавить ( ЗначениеРеквизита , Формат ( ЗначениеРеквизита . Дата , "ДФ=yyyyMMddЧЧММсс" ));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
СписокРеквизитов . СортироватьПоПредставлению ();
мУжеВСписке . Вставить ( ДокументСсылка , Истина);

Если СписокРеквизитов . Количество () = 1 Тогда
ВывестиРодительскиеДокументы ( СписокРеквизитов [ 0 ]. Значение , мУжеВСписке , мДерево );
ИначеЕсли СписокРеквизитов . Количество () > 1 Тогда
ВывестиБезРодителей ( СписокРеквизитов , мУжеВСписке , мДерево );
КонецЕсли;


СтрокаДерева = мДерево . Строки . Добавить ();
Запрос = Новый Запрос ( "ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка, Проведен, ПометкаУдаления, Представление, """ + МетаданныеДокумента . Имя + """ КАК Метаданные
| ИЗ Документ." + МетаданныеДокумента . Имя + " ГДЕ Ссылка = &Ссылка" );

Запрос . УстановитьПараметр ( "Ссылка" , ДокументСсылка );

Выборка = Запрос . Выполнить (). Выбрать ();
Если Выборка . Следующий () Тогда
СтрокаДерева . Ссылка = Выборка . Ссылка ;
СтрокаДерева . ДокументПредставление = Выборка . Ссылка . Метаданные (). Синоним + " " + Выборка . Ссылка . Номер ;
СтрокаДерева . Проведен = Выборка . Проведен ;
СтрокаДерева . ПометкаУдаления = Выборка . ПометкаУдаления ;
СтрокаДерева . ВидДокумента = Выборка . Метаданные ;
Иначе
СтрокаДерева . Ссылка = ДокументСсылка ;
КонецЕсли;

КонецПроцедуры
//
Процедура ВывестиПодчиненныеДокументы ( СтрокаДерева , мУжеВСписке )

ТекущийДокумент = СтрокаДерева . Ссылка ;
ТипДокумента = ТипЗнч ( ТекущийДокумент );
СтруктураРеквизитов = Новый ТаблицаЗначений ;
СтруктураРеквизитов . Колонки . Добавить ( "ПутьКДанным" );
СтруктураРеквизитов . Колонки . Добавить ( "ИмяРеквизита" );

Для каждого Док ИЗ Метаданные . Документы Цикл
Если НЕ ПравоДоступа ( "Чтение" , Док ) Тогда
Продолжить;
КонецЕсли;

Для Каждого Реквизит Из Док . Реквизиты Цикл
Если Реквизит . Тип . СодержитТип ( ТипДокумента ) Тогда
НовСтр = СтруктураРеквизитов . Добавить ();
НовСтр . ПутьКДанным = Док . Имя ;
НовСтр . ИмяРеквизита = Реквизит . Имя ;
КонецЕсли;
КонецЦикла;

Для Каждого ТЧ ИЗ Док . ТабличныеЧасти Цикл
Для Каждого Реквизит Из ТЧ . Реквизиты Цикл
Если Реквизит . Тип . СодержитТип ( ТипДокумента ) Тогда
НовСтр = СтруктураРеквизитов . Добавить ();
НовСтр . ПутьКДанным = Док . Имя + "." + ТЧ . Имя ;
НовСтр . ИмяРеквизита = Реквизит . Имя ;
КонецЕсли;
КонецЦикла;
КонецЦикла;

КонецЦикла;
ТекстЗапроса = "" ;
Для Каждого КлючИЗначение Из СтруктураРеквизитов Цикл

Если Найти ( КлючИЗначение . ПутьКДанным , "." ) = 0 Тогда

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

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

Если ТекстЗапроса = "" Тогда
Возврат;
КонецЕсли;

ТекстЗапроса = Лев ( ТекстЗапроса , СтрДлина ( ТекстЗапроса )- 15 );
ТекстЗапроса = ТекстЗапроса + "
|УПОРЯДОЧИТЬ ПО ДатаДок" ;

Запрос = Новый Запрос ( ТекстЗапроса );
Запрос . УстановитьПараметр ( "ДокументОснование" , ТекущийДокумент );
Выборка = Запрос . Выполнить (). Выбрать ();


Пока Выборка . Следующий () Цикл
Если мУжеВСписке [ Выборка . Ссылка ] = Неопределено Тогда
НоваяСтрока = СтрокаДерева . Строки . Добавить ();
НоваяСтрока . Ссылка = Выборка . Ссылка ;
НоваяСтрока . ДокументПредставление = Выборка . Ссылка . Метаданные (). Синоним + " " + Выборка . Ссылка . Номер ;
НоваяСтрока . Проведен = Выборка . Проведен ;
НоваяСтрока . ПометкаУдаления = Выборка . ПометкаУдаления ;
НоваяСтрока . ВидДокумента = Выборка . ВидДокумента ;
мУжеВСписке . Вставить ( Выборка . Ссылка , Истина);
ВывестиПодчиненныеДокументы ( НоваяСтрока , мУжеВСписке );
КонецЕсли;
КонецЦикла;

КонецПроцедуры
//
Процедура ВывестиБезРодителей ( СписокДокументов , мУжеВСписке , мДерево )

Для Каждого ЭлементСписка Из СписокДокументов Цикл

МетаданныеДокумента = ЭлементСписка . Значение . Метаданные ();

Запрос = Новый Запрос ( "ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка, Проведен, ПометкаУдаления, Представление, """ + МетаданныеДокумента . Имя + """ КАК Метаданные
| ИЗ Документ." + МетаданныеДокумента . Имя + " ГДЕ Ссылка = &Ссылка" );

Запрос . УстановитьПараметр ( "Ссылка" , ЭлементСписка . Значение );

Выборка = Запрос . Выполнить (). Выбрать ();
ЕСли Выборка . Следующий () Тогда
Если мУжеВСписке [ Выборка . Ссылка ] = Неопределено Тогда
СтрокаДерева = мДерево . Строки . Добавить ();
СтрокаДерева . Ссылка = Выборка . Ссылка ;
СтрокаДерева . ДокументПредставление = Выборка . Ссылка . Метаданные (). Синоним + " " + Выборка . Ссылка . Номер ;
СтрокаДерева . Проведен = Выборка . Проведен ;
СтрокаДерева . ПометкаУдаления = Выборка . ПометкаУдаления ;
СтрокаДерева . ВидДокумента = Выборка . Метаданные ;
мУжеВСписке . Вставить ( Выборка . Ссылка , Истина);
КонецЕсли;
КонецЕсли;
КонецЦикла;

Читайте также: