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

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

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

В наличии

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

Категория:

Описание

Потребовалось мне реализовать гибкую систему расшифровок отчёта, в которой для каждой ячейки, в зависимости от значений полей в иерархии этой ячейки становится доступным то или иное действие. Задача не простая, но и не сказать, чтобы сложная, однако я наткнулся на сложность определения полей, находящихся в детальных записях. Если для получения значения полей группировок достаточно получить все поля всех родителей данной ячейки, то для детальных записей такого простого способа нет — нужно определить значения всех "братьев" обрабатываемой ячейки. Также надо учесть, что детальные записи могут располагаться в иерархии других детальных записей.

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

Сподвигло меня оставить этот алгоритм здесь отсутствие его уже готового на просторах интернета при небольшой, но востребованности, и вполне универсальное его назначение.

&НаСервере
Функция ЗначенияПолей(ДанныеРасшифровки, Расшифровка)
    
    Результат = Новый Соответствие;
    
    ОбработанныеЭлементы = Новый Массив;
    
    ПоляРасшифровки(ДанныеРасшифровки, Расшифровка, Результат, ОбработанныеЭлементы);
    
    Возврат Результат;
    
КонецФункции

&НаСервере
Процедура ПоляРасшифровки(ДанныеРасшифровки, Расшифровка, Поля, ОбработанныеЭлементы, ОбрабатыватьБратьев = Истина)
    
    Если ОбработанныеЭлементы.Найти(Расшифровка) = Неопределено Тогда
        ОбработанныеЭлементы.Добавить(Расшифровка);
    Иначе
        Возврат;
    КонецЕсли;
    
    ЭлементРасшифровки = ДанныеРасшифровки.Элементы.Получить(Расшифровка);
    
    Если ТипЗнч(ЭлементРасшифровки) = Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
        ПоляЭлемента = ЭлементРасшифровки.ПолучитьПоля();
        ДополнитьПоляРасшифровки(ПоляЭлемента, Поля);
    ИначеЕсли ТипЗнч(ЭлементРасшифровки) = Тип("ЗначенияПолейРасшифровкиКомпоновкиДанных") Тогда
        ДополнитьПоляРасшифровки(ЭлементРасшифровки, Поля);
        Возврат;
    КонецЕсли;
    
    Родители = ЭлементРасшифровки.ПолучитьРодителей();
    Для каждого Родитель Из Родители Цикл
        
        Если ТипЗнч(ЭлементРасшифровки) = Тип("ЭлементРасшифровкиКомпоновкиДанныхГруппировка") Тогда
            
            РодителиТекущегоУзла = РодителиУзлаВМассив(ЭлементРасшифровки);
            
            Инд = Число(ЭлементРасшифровки.Идентификатор) - 1;
            Пока Инд >= 0 Цикл
                
                РодителиПроверяемогоУзла = РодителиУзлаВМассив(ДанныеРасшифровки.Элементы.Получить(Инд));
                
                Если МассивыСовпадают(РодителиТекущегоУзла, РодителиПроверяемогоУзла) Тогда
                    ПоляРасшифровки(ДанныеРасшифровки, Инд, Поля, ОбработанныеЭлементы, Ложь);
                Иначе
                    Прервать;
                КонецЕсли;
                
                Инд = Инд - 1;
                
            КонецЦикла;
            
        Иначе
            
            Если ОбрабатыватьБратьев  Тогда
                
                Братья = НайтиБратьев(ДанныеРасшифровки, Родитель.Идентификатор, Расшифровка);
                Для каждого Брат Из Братья Цикл
                    ПоляРасшифровки(ДанныеРасшифровки, Брат, Поля, ОбработанныеЭлементы, Ложь);
                КонецЦикла;
                
            КонецЕсли;
            
        КонецЕсли;
        
        ПоляРасшифровки(ДанныеРасшифровки, Родитель.Идентификатор, Поля, ОбработанныеЭлементы, Истина);
        
    КонецЦикла;
    
КонецПроцедуры

&НаСервере
Функция РодителиУзлаВМассив(Узел)
    
    Результат = Новый Массив;
    
    СписокРодителей = Узел.ПолучитьРодителей();
    
    Для каждого Родитель Из СписокРодителей Цикл
        Результат.Добавить(Число(Родитель.Идентификатор));
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции

&НаСервере
Функция МассивыСовпадают(Массив1, Массив2)
    
    Если Массив1.Количество() <> Массив2.Количество() Тогда
        Возврат Ложь;
    КонецЕсли;
    
    Для каждого ИД Из Массив1 Цикл
        Если Массив2.Найти(ИД) = Неопределено Тогда
            Возврат Ложь;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Истина;
    
КонецФункции

&НаСервере
Функция НайтиБратьев(ДанныеРасшифровки, Родитель, ТекущийЭлемент)
    
    Результат = Новый Массив;
    
    Для каждого ЭлементРасшифровки Из ДанныеРасшифровки.Элементы Цикл
        
        Если ЭлементРасшифровки.Идентификатор = ТекущийЭлемент Тогда
            Продолжить;
        КонецЕсли;
        
        Родители = ЭлементРасшифровки.ПолучитьРодителей();
        Для каждого ОбрабатываемыйРодитель Из Родители Цикл
            Если ОбрабатываемыйРодитель.Идентификатор = Родитель Тогда
                Результат.Добавить(ЭлементРасшифровки.Идентификатор);
                Прервать;
            КонецЕсли;
        КонецЦикла;
        
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции

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

 

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