Каталог решений - Получение списка родительских и подчиненных документов из структуры подчиненности

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

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

В наличии

Достаточно часто стали появляться задачи, требующие получения данных по структуре подчиненности документов. Каждый раз писать все заново надоело. Решил добавить в общий модуль пару экспортных функций…

Категория:

Описание

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

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

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

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

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

 

Примеры:

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

СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка1);
СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка2, СписокСвязанныхДокументов);

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

СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка);
СписокСвязанныхДокументов = ПолучитьПодчиненныеДокументы(ДокументСсылка, СписокСвязанныхДокументов);

 

Дополнение:

Функция ПолучитьВыборкуПоКритериюОтбора(ИмяКритерияОтбора, ЗначениеКритерия) Экспорт
       
    Запрос = Новый Запрос;
    ТекстЗапроса = «»;
   
    Для Каждого ЭлементСостава ИЗ Метаданные.КритерииОтбора[ИмяКритерияОтбора].Состав Цикл
       
        Если Не ЭлементСостава.Тип.СодержитТип(ТипЗнч(ЗначениеКритерия)) Тогда
            Продолжить;
        КонецЕсли;
       
        ПутьКДанным = ЭлементСостава.ПолноеИмя();
        СтруктураПутьКДанным = ОбщегоНазначения.РазобратьПутьКОбъектуМетаданных(ПутьКДанным, ЭлементСостава.Родитель());
       
        ЕСли НЕ ПравоДоступа(«Чтение», СтруктураПутьКДанным.Метаданные) Тогда
            Продолжить;
        КонецЕсли;
       
        ИмяОбъекта = СтруктураПутьКДанным.ТипОбъекта + «.» + СтруктураПутьКДанным.ВидОбъекта;
        ПсевдонимТаблицы = СтруктураПутьКДанным.ТипОбъекта + «_» + СтруктураПутьКДанным.ВидОбъекта + «_» + СтруктураПутьКДанным.ИмяТаблЧасти;
       
        ТекущаяСтрокаГДЕ = «ГДЕ » + ПсевдонимТаблицы + «.» +СтруктураПутьКДанным.ИмяРеквизита + » = &ЗначениеКритерияОтбора»;
           
        ИмяТЧ = Лев(СтруктураПутьКДанным.ИмяРеквизита, Найти(СтруктураПутьКДанным.ИмяРеквизита, «.»)-1);
        ИмяРеквизита = Лев(СтруктураПутьКДанным.ИмяРеквизита, Найти(СтруктураПутьКДанным.ИмяРеквизита, «.»)-1);
        ТекстЗапроса = ТекстЗапроса + (?(ТекстЗапроса = «», «ВЫБРАТЬ», «ОБЪЕДИНИТЬ ВСЕ
        |ВЫБРАТЬ») + «
        |» + ПсевдонимТаблицы + «.Ссылка ИЗ » + ИмяОбъекта + «.» + СтруктураПутьКДанным.ИмяТаблЧасти + » КАК » + ПсевдонимТаблицы + «
        |» + СтрЗаменить(ТекущаяСтрокаГДЕ, «..», «.») + «
        |»);
       
    КонецЦикла;
   
    Если ТекстЗапроса = «» Тогда
        Возврат Новый ТаблицаЗначений;
    КонецЕсли;
   
    Запрос.Текст = ТекстЗапроса;
    Запрос.УстановитьПараметр(«ЗначениеКритерияОтбора», ЗначениеКритерия);
    Возврат Запрос.Выполнить().Выгрузить();
   
КонецФункции

Функция РазобратьПутьКОбъектуМетаданных(ПутьКДанным, МетаданныеОбъекта = Неопределено) Экспорт
   
    Структура = Новый Структура;
   
    СоответствиеИмен = Новый Массив();
    СоответствиеИмен.Добавить(«ТипОбъекта»);
    СоответствиеИмен.Добавить(«ВидОбъекта»);
    СоответствиеИмен.Добавить(«ПутьКДанным»);
    СоответствиеИмен.Добавить(«ИмяТаблЧасти»);
    СоответствиеИмен.Добавить(«ИмяРеквизита»);
   
    Для индекс = 1 по 3 Цикл
       
        Точка = Найти(ПутьКДанным, «.»);
        ТекущееЗначение = Лев(ПутьКДанным, Точка-1);
        Структура.Вставить(СоответствиеИмен[индекс-1], ТекущееЗначение);
        ПутьКДанным = Сред(ПутьКДанным, Точка+1);
       
    КонецЦикла;
   
    ПутьКДанным = СтрЗаменить(ПутьКДанным, «Реквизит.», «»);
   
    Если Структура.ПутьКДанным = «ТабличнаяЧасть» Тогда
       
        Для индекс = 4 по 5  Цикл
           
            Точка = Найти(ПутьКДанным, «.»);
            Если Точка = 0 Тогда
                ТекущееЗначение = ПутьКДанным;
            Иначе
                ТекущееЗначение = Лев(ПутьКДанным, Точка-1);
            КонецЕсли;
           
            Структура.Вставить(СоответствиеИмен[индекс-1], ТекущееЗначение);
            ПутьКДанным = Сред(ПутьКДанным,  Точка+1);
           
        КонецЦикла;
       
    Иначе
       
        Структура.Вставить(СоответствиеИмен[3], «»);
        Структура.Вставить(СоответствиеИмен[4], ПутьКДанным);
       
    КонецЕсли;
   
    Если МетаданныеОбъекта <> Неопределено Тогда
        Структура.Вставить(«Метаданные», МетаданныеОбъекта);
    Иначе
        Если Структура.ТипОбъекта = «Документ» Тогда
            Структура.Вставить(«Метаданные», Метаданные.Документы[Структура.ВидОбъекта]);
        Иначе
            Структура.Вставить(«Метаданные», Метаданные.Справочники[Структура.ВидОбъекта]);
        КонецЕсли;
    КонецЕсли;
   
    Возврат Структура;
   
КонецФункции

has been added to your cart:
Оформление заказа